Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afdb028070 | ||
|
|
80d4615f32 | ||
|
|
5a12a7fb31 | ||
|
|
17c10b8a45 | ||
|
|
f8e2c8e319 | ||
|
|
9ea82fdaaf | ||
|
|
3d01a83c85 | ||
|
|
13f8b1a10c | ||
|
|
f78e172eda | ||
|
|
bd452f90b2 | ||
|
|
2b1f150f02 | ||
|
|
e7a9457249 | ||
|
|
d3ab2e73d5 | ||
|
|
860f40ca63 | ||
|
|
59a7db56a4 | ||
|
|
01e5107a96 | ||
|
|
8765dbbe0f | ||
|
|
d125b0b95b | ||
|
|
1d2fc4b8f5 | ||
|
|
146ea115bf | ||
|
|
4f44188997 | ||
|
|
ac5fb303eb | ||
|
|
31a14997f8 | ||
|
|
4cd4ff2c5e | ||
|
|
26ef508966 | ||
|
|
28b4badb9a | ||
|
|
8e2e2420b0 | ||
|
|
67349627f4 | ||
|
|
cfe825f94a | ||
|
|
53e79915fa | ||
|
|
9fb5f688ed | ||
|
|
c2cdae0615 | ||
|
|
2516bb59a1 | ||
|
|
13c78fae58 | ||
|
|
91c0a31800 | ||
|
|
277137c8e6 | ||
|
|
4556a355a2 | ||
|
|
7dafb07438 | ||
|
|
3c8e7a1364 | ||
|
|
921cd46c10 | ||
|
|
b0f6dc4e16 | ||
|
|
1499b19575 | ||
|
|
877b867cef | ||
|
|
837808bd77 | ||
|
|
10a69f4338 | ||
|
|
7bc603f380 | ||
|
|
6c1cc6fc96 |
@@ -1,4 +1,4 @@
|
|||||||
## 2.6.1
|
## 2.6.1 - 2.6.4
|
||||||
|
|
||||||
Attention all users: For pre 2.6 applications to work with web2py >=2.6, you must copy static/js/web2py.js, controllers/appadmin.py, and views/appadmin.html from the welcome app to your own apps (all of them).
|
Attention all users: For pre 2.6 applications to work with web2py >=2.6, you must copy static/js/web2py.js, controllers/appadmin.py, and views/appadmin.html from the welcome app to your own apps (all of them).
|
||||||
|
|
||||||
@@ -38,6 +38,8 @@ Attention MySQL users: The length of string fields changed from 255 to 512 bytes
|
|||||||
- speedup for define_table, thanks Michele
|
- speedup for define_table, thanks Michele
|
||||||
- settings.cfg to admin, thanks Paolo
|
- settings.cfg to admin, thanks Paolo
|
||||||
- many bugs fixed, thanks Niphlod, Michele, Roberto, Jonathan, and many others
|
- many bugs fixed, thanks Niphlod, Michele, Roberto, Jonathan, and many others
|
||||||
|
- 2.6,3 specifically fixed a possible DoS vulnerability
|
||||||
|
- 2.6.4 specifically fixes major problem introduced in 2.6.1 with session logic
|
||||||
|
|
||||||
## 2.5.2
|
## 2.5.2
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ update:
|
|||||||
echo "remember that pymysql was tweaked"
|
echo "remember that pymysql was tweaked"
|
||||||
src:
|
src:
|
||||||
### Use semantic versioning
|
### Use semantic versioning
|
||||||
echo 'Version 2.6.1-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
echo 'Version 2.6.4-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
||||||
### rm -f all junk files
|
### rm -f all junk files
|
||||||
make clean
|
make clean
|
||||||
### clean up baisc apps
|
### clean up baisc apps
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
Version 2.6.1-stable+timestamp.2013.09.12.17.08.08
|
Version 2.6.4-stable+timestamp.2013.09.21.20.41.28
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ if request.function == 'manage':
|
|||||||
auth.requires_membership(manager_role)(lambda: None)()
|
auth.requires_membership(manager_role)(lambda: None)()
|
||||||
menu = False
|
menu = False
|
||||||
elif (request.application == 'admin' and not session.authorized) or \
|
elif (request.application == 'admin' and not session.authorized) or \
|
||||||
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
|
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
|
||||||
redirect(URL('admin', 'default', 'index',
|
redirect(URL('admin', 'default', 'index',
|
||||||
vars=dict(send=URL(args=request.args, vars=request.vars))))
|
vars=dict(send=URL(args=request.args, vars=request.vars))))
|
||||||
else:
|
else:
|
||||||
@@ -540,30 +540,30 @@ def table_template(table):
|
|||||||
|
|
||||||
def bg_graph_model():
|
def bg_graph_model():
|
||||||
graph = pgv.AGraph(layout='dot', directed=True, strict=False, rankdir='LR')
|
graph = pgv.AGraph(layout='dot', directed=True, strict=False, rankdir='LR')
|
||||||
|
|
||||||
subgraphs = dict()
|
subgraphs = dict()
|
||||||
for tablename in db.tables:
|
for tablename in db.tables:
|
||||||
if hasattr(db[tablename],'_meta_graphmodel'):
|
if hasattr(db[tablename],'_meta_graphmodel'):
|
||||||
meta_graphmodel = db[tablename]._meta_graphmodel
|
meta_graphmodel = db[tablename]._meta_graphmodel
|
||||||
else:
|
else:
|
||||||
meta_graphmodel = dict(group='Undefined', color='#ECECEC')
|
meta_graphmodel = dict(group='Undefined', color='#ECECEC')
|
||||||
|
|
||||||
group = meta_graphmodel['group'].replace(' ', '')
|
group = meta_graphmodel['group'].replace(' ', '')
|
||||||
if not subgraphs.has_key(group):
|
if not subgraphs.has_key(group):
|
||||||
subgraphs[group] = dict(meta=meta_graphmodel, tables=[])
|
subgraphs[group] = dict(meta=meta_graphmodel, tables=[])
|
||||||
subgraphs[group]['tables'].append(tablename)
|
subgraphs[group]['tables'].append(tablename)
|
||||||
else:
|
else:
|
||||||
subgraphs[group]['tables'].append(tablename)
|
subgraphs[group]['tables'].append(tablename)
|
||||||
|
|
||||||
graph.add_node(tablename, name=tablename, shape='plaintext',
|
graph.add_node(tablename, name=tablename, shape='plaintext',
|
||||||
label=table_template(tablename))
|
label=table_template(tablename))
|
||||||
|
|
||||||
for n, key in enumerate(subgraphs.iterkeys()):
|
for n, key in enumerate(subgraphs.iterkeys()):
|
||||||
graph.subgraph(nbunch=subgraphs[key]['tables'],
|
graph.subgraph(nbunch=subgraphs[key]['tables'],
|
||||||
name='cluster%d' % n,
|
name='cluster%d' % n,
|
||||||
style='filled',
|
style='filled',
|
||||||
color=subgraphs[key]['meta']['color'],
|
color=subgraphs[key]['meta']['color'],
|
||||||
label=subgraphs[key]['meta']['group'])
|
label=subgraphs[key]['meta']['group'])
|
||||||
|
|
||||||
for tablename in db.tables:
|
for tablename in db.tables:
|
||||||
for field in db[tablename]:
|
for field in db[tablename]:
|
||||||
@@ -580,14 +580,14 @@ def bg_graph_model():
|
|||||||
#return graph.draw(format='png', prog='dot')
|
#return graph.draw(format='png', prog='dot')
|
||||||
if not request.args:
|
if not request.args:
|
||||||
return graph.draw(format='png', prog='dot')
|
return graph.draw(format='png', prog='dot')
|
||||||
else:
|
else:
|
||||||
response.headers['Content-Disposition']='attachment;filename=graph.%s'%request.args(0)
|
response.headers['Content-Disposition']='attachment;filename=graph.%s'%request.args(0)
|
||||||
if request.args(0) == 'dot':
|
if request.args(0) == 'dot':
|
||||||
return graph.string()
|
return graph.string()
|
||||||
else:
|
else:
|
||||||
return graph.draw(format=request.args(0), prog='dot')
|
return graph.draw(format=request.args(0), prog='dot')
|
||||||
|
|
||||||
def graph_model():
|
def graph_model():
|
||||||
return dict(databases=databases, pgv=pgv)
|
return dict(databases=databases, pgv=pgv)
|
||||||
|
|
||||||
def manage():
|
def manage():
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ def toggle_breakpoint():
|
|||||||
except Exception, e:
|
except Exception, e:
|
||||||
session.flash = str(e)
|
session.flash = str(e)
|
||||||
return response.json({'ok': ok, 'lineno': lineno})
|
return response.json({'ok': ok, 'lineno': lineno})
|
||||||
|
|
||||||
def list_breakpoints():
|
def list_breakpoints():
|
||||||
"Return a list of linenumbers for current breakpoints"
|
"Return a list of linenumbers for current breakpoints"
|
||||||
|
|
||||||
@@ -234,4 +234,3 @@ def list_breakpoints():
|
|||||||
session.flash = str(e)
|
session.flash = str(e)
|
||||||
ok = False
|
ok = False
|
||||||
return response.json({'ok': ok, 'breakpoints': breakpoints})
|
return response.json({'ok': ok, 'breakpoints': breakpoints})
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ def safe_write(a, value, b='w'):
|
|||||||
|
|
||||||
def get_app(name=None):
|
def get_app(name=None):
|
||||||
app = name or request.args(0)
|
app = name or request.args(0)
|
||||||
if (app and os.path.exists(apath(app, r=request)) and
|
if (app and os.path.exists(apath(app, r=request)) and
|
||||||
(not MULTI_USER_MODE or is_manager() or
|
(not MULTI_USER_MODE or is_manager() or
|
||||||
db(db.app.name == app)(db.app.owner == auth.user.id).count())):
|
db(db.app.name == app)(db.app.owner == auth.user.id).count())):
|
||||||
return app
|
return app
|
||||||
@@ -108,7 +108,7 @@ def index():
|
|||||||
if session.authorized:
|
if session.authorized:
|
||||||
redirect(send)
|
redirect(send)
|
||||||
elif request.vars.password:
|
elif request.vars.password:
|
||||||
if verify_password(request.vars.password):
|
if verify_password(request.vars.password[:1024]):
|
||||||
session.authorized = True
|
session.authorized = True
|
||||||
login_record(True)
|
login_record(True)
|
||||||
|
|
||||||
@@ -583,11 +583,11 @@ def edit():
|
|||||||
|
|
||||||
# show settings tab and save prefernces
|
# show settings tab and save prefernces
|
||||||
if 'settings' in request.vars:
|
if 'settings' in request.vars:
|
||||||
if request.post_vars: #save new preferences
|
if request.post_vars: #save new preferences
|
||||||
if config.save(request.post_vars.items()):
|
if config.save(request.post_vars.items()):
|
||||||
response.headers["web2py-component-flash"] = T('Preferences saved correctly')
|
response.headers["web2py-component-flash"] = T('Preferences saved correctly')
|
||||||
else:
|
else:
|
||||||
response.headers["web2py-component-flash"] = T('Preferences saved on session only')
|
response.headers["web2py-component-flash"] = T('Preferences saved on session only')
|
||||||
response.headers["web2py-component-command"] = "update_theme('%s'); jQuery('a[href=#editor_settings] button.close').click();" % config.read()['theme']
|
response.headers["web2py-component-command"] = "update_theme('%s'); jQuery('a[href=#editor_settings] button.close').click();" % config.read()['theme']
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
'%s %%{row} updated': '%s filas actualizadas',
|
'%s %%{row} updated': '%s filas actualizadas',
|
||||||
'%Y-%m-%d': '%Y-%m-%d',
|
'%Y-%m-%d': '%Y-%m-%d',
|
||||||
'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
|
'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
|
||||||
|
'(requires internet access, experimental)': '(requires internet access, experimental)',
|
||||||
'(something like "it-it")': '(algo como "it-it")',
|
'(something like "it-it")': '(algo como "it-it")',
|
||||||
'@markmin\x01(file **gluon/contrib/plural_rules/%s.py** is not found)': '(file **gluon/contrib/plural_rules/%s.py** is not found)',
|
'@markmin\x01(file **gluon/contrib/plural_rules/%s.py** is not found)': '(file **gluon/contrib/plural_rules/%s.py** is not found)',
|
||||||
'@markmin\x01Searching: **%s** %%{file}': 'Searching: **%s** files',
|
'@markmin\x01Searching: **%s** %%{file}': 'Searching: **%s** files',
|
||||||
@@ -32,6 +33,7 @@
|
|||||||
'application "%s" uninstalled': 'aplicación "%s" desinstalada',
|
'application "%s" uninstalled': 'aplicación "%s" desinstalada',
|
||||||
'application compiled': 'aplicación compilada',
|
'application compiled': 'aplicación compilada',
|
||||||
'application is compiled and cannot be designed': 'la aplicación está compilada y no puede ser modificada',
|
'application is compiled and cannot be designed': 'la aplicación está compilada y no puede ser modificada',
|
||||||
|
'Application name:': 'Application name:',
|
||||||
'are not used': 'are not used',
|
'are not used': 'are not used',
|
||||||
'are not used yet': 'are not used yet',
|
'are not used yet': 'are not used yet',
|
||||||
'Are you sure you want to delete file "%s"?': '¿Está seguro que desea eliminar el archivo "%s"?',
|
'Are you sure you want to delete file "%s"?': '¿Está seguro que desea eliminar el archivo "%s"?',
|
||||||
@@ -47,6 +49,7 @@
|
|||||||
'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATENCION: NO EJECUTE VARIAS PRUEBAS SIMULTANEAMENTE, NO SON THREAD SAFE.',
|
'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATENCION: NO EJECUTE VARIAS PRUEBAS SIMULTANEAMENTE, NO SON THREAD SAFE.',
|
||||||
'ATTENTION: you cannot edit the running application!': 'ATENCION: no puede modificar la aplicación que se ejecuta!',
|
'ATTENTION: you cannot edit the running application!': 'ATENCION: no puede modificar la aplicación que se ejecuta!',
|
||||||
'Autocomplete': 'Autocomplete',
|
'Autocomplete': 'Autocomplete',
|
||||||
|
'Autocomplete Python Code': 'Autocomplete Python Code',
|
||||||
'Available databases and tables': 'Bases de datos y tablas disponibles',
|
'Available databases and tables': 'Bases de datos y tablas disponibles',
|
||||||
'back': 'atrás',
|
'back': 'atrás',
|
||||||
'breakpoint': 'breakpoint',
|
'breakpoint': 'breakpoint',
|
||||||
@@ -54,14 +57,17 @@
|
|||||||
'browse': 'buscar',
|
'browse': 'buscar',
|
||||||
'cache': 'cache',
|
'cache': 'cache',
|
||||||
'cache, errors and sessions cleaned': 'cache, errores y sesiones eliminados',
|
'cache, errors and sessions cleaned': 'cache, errores y sesiones eliminados',
|
||||||
|
'can be a git repo': 'can be a git repo',
|
||||||
'Cannot be empty': 'No puede estar vacío',
|
'Cannot be empty': 'No puede estar vacío',
|
||||||
'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'No se puede compilar: hay errores en su aplicación. Depure, corrija errores y vuelva a intentarlo.',
|
'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'No se puede compilar: hay errores en su aplicación. Depure, corrija errores y vuelva a intentarlo.',
|
||||||
'Cannot compile: there are errors in your app:': 'No se puede compilar: hay errores en su aplicación:',
|
'Cannot compile: there are errors in your app:': 'No se puede compilar: hay errores en su aplicación:',
|
||||||
'cannot create file': 'no es posible crear archivo',
|
'cannot create file': 'no es posible crear archivo',
|
||||||
'cannot upload file "%(filename)s"': 'no es posible subir archivo "%(filename)s"',
|
'cannot upload file "%(filename)s"': 'no es posible subir archivo "%(filename)s"',
|
||||||
'Change admin password': 'cambie contraseña admin',
|
'Change admin password': 'cambie contraseña admin',
|
||||||
|
'change editor settings': 'change editor settings',
|
||||||
'Change Password': 'Cambie Contraseña',
|
'Change Password': 'Cambie Contraseña',
|
||||||
'check all': 'marcar todos',
|
'check all': 'marcar todos',
|
||||||
|
'Check for upgrades': 'Check for upgrades',
|
||||||
'Check to delete': 'Marque para eliminar',
|
'Check to delete': 'Marque para eliminar',
|
||||||
'Checking for upgrades...': 'Buscando actulizaciones...',
|
'Checking for upgrades...': 'Buscando actulizaciones...',
|
||||||
'Clean': 'limpiar',
|
'Clean': 'limpiar',
|
||||||
@@ -91,6 +97,7 @@
|
|||||||
'Current request': 'Solicitud en curso',
|
'Current request': 'Solicitud en curso',
|
||||||
'Current response': 'Respuesta en curso',
|
'Current response': 'Respuesta en curso',
|
||||||
'Current session': 'Sesión en curso',
|
'Current session': 'Sesión en curso',
|
||||||
|
'currently running': 'currently running',
|
||||||
'currently saved or': 'actualmente guardado o',
|
'currently saved or': 'actualmente guardado o',
|
||||||
'customize me!': 'Adaptame!',
|
'customize me!': 'Adaptame!',
|
||||||
'data uploaded': 'datos subidos',
|
'data uploaded': 'datos subidos',
|
||||||
@@ -107,14 +114,21 @@
|
|||||||
'delete plugin': 'eliminar plugin',
|
'delete plugin': 'eliminar plugin',
|
||||||
'Delete this file (you will be asked to confirm deletion)': 'Delete this file (you will be asked to confirm deletion)',
|
'Delete this file (you will be asked to confirm deletion)': 'Delete this file (you will be asked to confirm deletion)',
|
||||||
'Delete:': 'Elimine:',
|
'Delete:': 'Elimine:',
|
||||||
|
'Deploy': 'Deploy',
|
||||||
'Deploy on Google App Engine': 'Instale en Google App Engine',
|
'Deploy on Google App Engine': 'Instale en Google App Engine',
|
||||||
|
'Deploy to OpenShift': 'Deploy to OpenShift',
|
||||||
'Description': 'Descripción',
|
'Description': 'Descripción',
|
||||||
'design': 'modificar',
|
'design': 'modificar',
|
||||||
'DESIGN': 'DISEÑO',
|
'DESIGN': 'DISEÑO',
|
||||||
'Design for': 'Diseño para',
|
'Design for': 'Diseño para',
|
||||||
|
'Detailed traceback description': 'Detailed traceback description',
|
||||||
|
'details': 'details',
|
||||||
'direction: ltr': 'direction: ltr',
|
'direction: ltr': 'direction: ltr',
|
||||||
|
'Disable': 'Disable',
|
||||||
'docs': 'docs',
|
'docs': 'docs',
|
||||||
'done!': 'listo!',
|
'done!': 'listo!',
|
||||||
|
'Download': 'Download',
|
||||||
|
'download files via http:': 'download files via http:',
|
||||||
'download layouts': 'download layouts',
|
'download layouts': 'download layouts',
|
||||||
'download plugins': 'download plugins',
|
'download plugins': 'download plugins',
|
||||||
'E-mail': 'Correo electrónico',
|
'E-mail': 'Correo electrónico',
|
||||||
@@ -122,17 +136,25 @@
|
|||||||
'Edit': 'editar',
|
'Edit': 'editar',
|
||||||
'Edit application': 'Editar aplicación',
|
'Edit application': 'Editar aplicación',
|
||||||
'edit controller': 'editar controlador',
|
'edit controller': 'editar controlador',
|
||||||
|
'edit controller:': 'edit controller:',
|
||||||
'Edit current record': 'Edite el registro actual',
|
'Edit current record': 'Edite el registro actual',
|
||||||
'Edit Profile': 'Editar Perfil',
|
'Edit Profile': 'Editar Perfil',
|
||||||
'edit views:': 'editar vistas:',
|
'edit views:': 'editar vistas:',
|
||||||
'Editing file': 'Editando archivo',
|
'Editing file': 'Editando archivo',
|
||||||
'Editing file "%s"': 'Editando archivo "%s"',
|
'Editing file "%s"': 'Editando archivo "%s"',
|
||||||
'Editing Language file': 'Editando archivo de lenguaje',
|
'Editing Language file': 'Editando archivo de lenguaje',
|
||||||
|
'Editing myclientapi': 'Editing myclientapi',
|
||||||
|
'Editing myemail': 'Editing myemail',
|
||||||
|
'Editing rbare': 'Editing rbare',
|
||||||
|
'Editing ul': 'Editing ul',
|
||||||
'Enterprise Web Framework': 'Armazón Empresarial para Internet',
|
'Enterprise Web Framework': 'Armazón Empresarial para Internet',
|
||||||
'Error': 'Error',
|
'Error': 'Error',
|
||||||
'Error logs for "%(app)s"': 'Bitácora de errores en "%(app)s"',
|
'Error logs for "%(app)s"': 'Bitácora de errores en "%(app)s"',
|
||||||
|
'Error snapshot': 'Error snapshot',
|
||||||
|
'Error ticket': 'Error ticket',
|
||||||
'Errors': 'errores',
|
'Errors': 'errores',
|
||||||
'Exception instance attributes': 'Atributos de la instancia de Excepción',
|
'Exception instance attributes': 'Atributos de la instancia de Excepción',
|
||||||
|
'Expand Abbreviation': 'Expand Abbreviation',
|
||||||
'export as csv file': 'exportar como archivo CSV',
|
'export as csv file': 'exportar como archivo CSV',
|
||||||
'exposes': 'expone',
|
'exposes': 'expone',
|
||||||
'exposes:': 'exposes:',
|
'exposes:': 'exposes:',
|
||||||
@@ -154,6 +176,7 @@
|
|||||||
'Find Next': 'Find Next',
|
'Find Next': 'Find Next',
|
||||||
'Find Previous': 'Find Previous',
|
'Find Previous': 'Find Previous',
|
||||||
'First name': 'Nombre',
|
'First name': 'Nombre',
|
||||||
|
'Frames': 'Frames',
|
||||||
'Functions with no doctests will result in [passed] tests.': 'Funciones sin doctests equivalen a pruebas [aceptadas].',
|
'Functions with no doctests will result in [passed] tests.': 'Funciones sin doctests equivalen a pruebas [aceptadas].',
|
||||||
'Globals##debug': 'Globals',
|
'Globals##debug': 'Globals',
|
||||||
'graph model': 'graph model',
|
'graph model': 'graph model',
|
||||||
@@ -166,6 +189,7 @@
|
|||||||
'includes': 'incluye',
|
'includes': 'incluye',
|
||||||
'insert new': 'inserte nuevo',
|
'insert new': 'inserte nuevo',
|
||||||
'insert new %s': 'inserte nuevo %s',
|
'insert new %s': 'inserte nuevo %s',
|
||||||
|
'inspect attributes': 'inspect attributes',
|
||||||
'Install': 'instalar',
|
'Install': 'instalar',
|
||||||
'Installed applications': 'Aplicaciones instaladas',
|
'Installed applications': 'Aplicaciones instaladas',
|
||||||
'Interaction at %s line %s': 'Interaction at %s line %s',
|
'Interaction at %s line %s': 'Interaction at %s line %s',
|
||||||
@@ -175,10 +199,12 @@
|
|||||||
'Invalid action': 'Acción inválida',
|
'Invalid action': 'Acción inválida',
|
||||||
'Invalid email': 'Correo inválido',
|
'Invalid email': 'Correo inválido',
|
||||||
'invalid password': 'contraseña inválida',
|
'invalid password': 'contraseña inválida',
|
||||||
|
'invalid password.': 'invalid password.',
|
||||||
'Invalid Query': 'Consulta inválida',
|
'Invalid Query': 'Consulta inválida',
|
||||||
'invalid request': 'solicitud inválida',
|
'invalid request': 'solicitud inválida',
|
||||||
'invalid ticket': 'tiquete inválido',
|
'invalid ticket': 'tiquete inválido',
|
||||||
'Key bindings': 'Key bindings',
|
'Key bindings': 'Key bindings',
|
||||||
|
'Key bindings for ZenCoding Plugin': 'Key bindings for ZenCoding Plugin',
|
||||||
'language file "%(filename)s" created/updated': 'archivo de lenguaje "%(filename)s" creado/actualizado',
|
'language file "%(filename)s" created/updated': 'archivo de lenguaje "%(filename)s" creado/actualizado',
|
||||||
'Language files (static strings) updated': 'Archivos de lenguaje (cadenas estáticas) actualizados',
|
'Language files (static strings) updated': 'Archivos de lenguaje (cadenas estáticas) actualizados',
|
||||||
'languages': 'lenguajes',
|
'languages': 'lenguajes',
|
||||||
@@ -188,6 +214,7 @@
|
|||||||
'Last saved on:': 'Guardado en:',
|
'Last saved on:': 'Guardado en:',
|
||||||
'License for': 'Licencia para',
|
'License for': 'Licencia para',
|
||||||
'loading...': 'cargando...',
|
'loading...': 'cargando...',
|
||||||
|
'locals': 'locals',
|
||||||
'Locals##debug': 'Locals',
|
'Locals##debug': 'Locals',
|
||||||
'Login': 'Inicio de sesión',
|
'Login': 'Inicio de sesión',
|
||||||
'login': 'inicio de sesión',
|
'login': 'inicio de sesión',
|
||||||
@@ -195,6 +222,7 @@
|
|||||||
'Logout': 'fin de sesión',
|
'Logout': 'fin de sesión',
|
||||||
'Lost Password': 'Contraseña perdida',
|
'Lost Password': 'Contraseña perdida',
|
||||||
'manage': 'manage',
|
'manage': 'manage',
|
||||||
|
'Manage': 'Manage',
|
||||||
'merge': 'combinar',
|
'merge': 'combinar',
|
||||||
'Models': 'Modelos',
|
'Models': 'Modelos',
|
||||||
'models': 'modelos',
|
'models': 'modelos',
|
||||||
@@ -202,16 +230,22 @@
|
|||||||
'modules': 'módulos',
|
'modules': 'módulos',
|
||||||
'Name': 'Nombre',
|
'Name': 'Nombre',
|
||||||
'new application "%s" created': 'nueva aplicación "%s" creada',
|
'new application "%s" created': 'nueva aplicación "%s" creada',
|
||||||
|
'New application wizard': 'New application wizard',
|
||||||
'new plugin installed': 'nuevo plugin instalado',
|
'new plugin installed': 'nuevo plugin instalado',
|
||||||
'New Record': 'Registro nuevo',
|
'New Record': 'Registro nuevo',
|
||||||
'new record inserted': 'nuevo registro insertado',
|
'new record inserted': 'nuevo registro insertado',
|
||||||
|
'New simple application': 'New simple application',
|
||||||
'next': 'next',
|
'next': 'next',
|
||||||
'next 100 rows': '100 filas siguientes',
|
'next 100 rows': '100 filas siguientes',
|
||||||
'NO': 'NO',
|
'NO': 'NO',
|
||||||
'No databases in this application': 'No hay bases de datos en esta aplicación',
|
'No databases in this application': 'No hay bases de datos en esta aplicación',
|
||||||
'No Interaction yet': 'No Interaction yet',
|
'No Interaction yet': 'No Interaction yet',
|
||||||
'no match': 'no encontrado',
|
'no match': 'no encontrado',
|
||||||
|
'no package selected': 'no package selected',
|
||||||
|
'No ticket_storage.txt found under /private folder': 'No ticket_storage.txt found under /private folder',
|
||||||
|
'online designer': 'online designer',
|
||||||
'or alternatively': 'or alternatively',
|
'or alternatively': 'or alternatively',
|
||||||
|
'Or Get from URL:': 'Or Get from URL:',
|
||||||
'or import from csv file': 'o importar desde archivo CSV',
|
'or import from csv file': 'o importar desde archivo CSV',
|
||||||
'or provide app url:': 'o provea URL de la aplicación:',
|
'or provide app url:': 'o provea URL de la aplicación:',
|
||||||
'or provide application url:': 'o provea URL de la aplicación:',
|
'or provide application url:': 'o provea URL de la aplicación:',
|
||||||
@@ -220,6 +254,7 @@
|
|||||||
'Overwrite installed app': 'sobreescriba aplicación instalada',
|
'Overwrite installed app': 'sobreescriba aplicación instalada',
|
||||||
'Pack all': 'empaquetar todo',
|
'Pack all': 'empaquetar todo',
|
||||||
'Pack compiled': 'empaquete compiladas',
|
'Pack compiled': 'empaquete compiladas',
|
||||||
|
'Pack custom': 'Pack custom',
|
||||||
'pack plugin': 'empaquetar plugin',
|
'pack plugin': 'empaquetar plugin',
|
||||||
'PAM authenticated user, cannot change password here': 'usuario autenticado por PAM, no puede cambiar la contraseña aquí',
|
'PAM authenticated user, cannot change password here': 'usuario autenticado por PAM, no puede cambiar la contraseña aquí',
|
||||||
'Password': 'Contraseña',
|
'Password': 'Contraseña',
|
||||||
@@ -236,6 +271,7 @@
|
|||||||
'Private files': 'Private files',
|
'Private files': 'Private files',
|
||||||
'private files': 'private files',
|
'private files': 'private files',
|
||||||
'Query:': 'Consulta:',
|
'Query:': 'Consulta:',
|
||||||
|
'Rapid Search': 'Rapid Search',
|
||||||
'record': 'registro',
|
'record': 'registro',
|
||||||
'record does not exist': 'el registro no existe',
|
'record does not exist': 'el registro no existe',
|
||||||
'record id': 'id de registro',
|
'record id': 'id de registro',
|
||||||
@@ -244,11 +280,14 @@
|
|||||||
'Register': 'Registrese',
|
'Register': 'Registrese',
|
||||||
'Registration key': 'Contraseña de Registro',
|
'Registration key': 'Contraseña de Registro',
|
||||||
'reload': 'reload',
|
'reload': 'reload',
|
||||||
|
'Reload routes': 'Reload routes',
|
||||||
'Remove compiled': 'eliminar compiladas',
|
'Remove compiled': 'eliminar compiladas',
|
||||||
'Removed Breakpoint on %s at line %s': 'Removed Breakpoint on %s at line %s',
|
'Removed Breakpoint on %s at line %s': 'Removed Breakpoint on %s at line %s',
|
||||||
'Replace': 'Replace',
|
'Replace': 'Replace',
|
||||||
'Replace All': 'Replace All',
|
'Replace All': 'Replace All',
|
||||||
|
'request': 'request',
|
||||||
'Resolve Conflict file': 'archivo Resolución de Conflicto',
|
'Resolve Conflict file': 'archivo Resolución de Conflicto',
|
||||||
|
'response': 'response',
|
||||||
'restore': 'restaurar',
|
'restore': 'restaurar',
|
||||||
'return': 'return',
|
'return': 'return',
|
||||||
'revert': 'revertir',
|
'revert': 'revertir',
|
||||||
@@ -256,26 +295,32 @@
|
|||||||
'Rows in table': 'Filas en la tabla',
|
'Rows in table': 'Filas en la tabla',
|
||||||
'Rows selected': 'Filas seleccionadas',
|
'Rows selected': 'Filas seleccionadas',
|
||||||
'rules are not defined': 'rules are not defined',
|
'rules are not defined': 'rules are not defined',
|
||||||
|
'Run tests in this file': 'Run tests in this file',
|
||||||
"Run tests in this file (to run all files, you may also use the button labelled 'test')": "Run tests in this file (to run all files, you may also use the button labelled 'test')",
|
"Run tests in this file (to run all files, you may also use the button labelled 'test')": "Run tests in this file (to run all files, you may also use the button labelled 'test')",
|
||||||
|
'Running on %s': 'Running on %s',
|
||||||
'Save': 'Save',
|
'Save': 'Save',
|
||||||
'save': 'guardar',
|
'save': 'guardar',
|
||||||
'Save file:': 'Save file:',
|
'Save file:': 'Save file:',
|
||||||
|
'Save file: %s': 'Save file: %s',
|
||||||
'Save via Ajax': 'Save via Ajax',
|
'Save via Ajax': 'Save via Ajax',
|
||||||
'Saved file hash:': 'Hash del archivo guardado:',
|
'Saved file hash:': 'Hash del archivo guardado:',
|
||||||
'selected': 'seleccionado(s)',
|
'selected': 'seleccionado(s)',
|
||||||
|
'session': 'session',
|
||||||
'session expired': 'sesión expirada',
|
'session expired': 'sesión expirada',
|
||||||
'Set Breakpoint on %s at line %s: %s': 'Set Breakpoint on %s at line %s: %s',
|
'Set Breakpoint on %s at line %s: %s': 'Set Breakpoint on %s at line %s: %s',
|
||||||
'shell': 'shell',
|
'shell': 'shell',
|
||||||
'Site': 'sitio',
|
'Site': 'sitio',
|
||||||
'some files could not be removed': 'algunos archivos no pudieron ser removidos',
|
'some files could not be removed': 'algunos archivos no pudieron ser removidos',
|
||||||
'Start searching': 'Start searching',
|
'Start searching': 'Start searching',
|
||||||
|
'Start wizard': 'Start wizard',
|
||||||
'state': 'estado',
|
'state': 'estado',
|
||||||
'static': 'estáticos',
|
|
||||||
'Static': 'Static',
|
'Static': 'Static',
|
||||||
|
'static': 'estáticos',
|
||||||
'Static files': 'Archivos estáticos',
|
'Static files': 'Archivos estáticos',
|
||||||
'step': 'step',
|
'step': 'step',
|
||||||
'stop': 'stop',
|
'stop': 'stop',
|
||||||
'submit': 'enviar',
|
'submit': 'enviar',
|
||||||
|
'Submit': 'Submit',
|
||||||
'successful': 'successful',
|
'successful': 'successful',
|
||||||
'Sure you want to delete this object?': '¿Está seguro que desea eliminar este objeto?',
|
'Sure you want to delete this object?': '¿Está seguro que desea eliminar este objeto?',
|
||||||
'table': 'tabla',
|
'table': 'tabla',
|
||||||
@@ -303,6 +348,7 @@
|
|||||||
'This is the %(filename)s template': 'Esta es la plantilla %(filename)s',
|
'This is the %(filename)s template': 'Esta es la plantilla %(filename)s',
|
||||||
'this page to see if a breakpoint was hit and debug interaction is required.': 'this page to see if a breakpoint was hit and debug interaction is required.',
|
'this page to see if a breakpoint was hit and debug interaction is required.': 'this page to see if a breakpoint was hit and debug interaction is required.',
|
||||||
'Ticket': 'Tiquete',
|
'Ticket': 'Tiquete',
|
||||||
|
'Ticket ID': 'Ticket ID',
|
||||||
'Timestamp': 'Timestamp',
|
'Timestamp': 'Timestamp',
|
||||||
'TM': 'MR',
|
'TM': 'MR',
|
||||||
'to previous version.': 'a la versión previa.',
|
'to previous version.': 'a la versión previa.',
|
||||||
@@ -311,10 +357,13 @@
|
|||||||
'to use the debugger!': 'to use the debugger!',
|
'to use the debugger!': 'to use the debugger!',
|
||||||
'toggle breakpoint': 'toggle breakpoint',
|
'toggle breakpoint': 'toggle breakpoint',
|
||||||
'Toggle Fullscreen': 'Toggle Fullscreen',
|
'Toggle Fullscreen': 'Toggle Fullscreen',
|
||||||
|
'Traceback': 'Traceback',
|
||||||
'translation strings for the application': 'cadenas de caracteres de traducción para la aplicación',
|
'translation strings for the application': 'cadenas de caracteres de traducción para la aplicación',
|
||||||
'Translation strings for the application': 'Translation strings for the application',
|
'Translation strings for the application': 'Translation strings for the application',
|
||||||
'try': 'intente',
|
'try': 'intente',
|
||||||
'try something like': 'intente algo como',
|
'try something like': 'intente algo como',
|
||||||
|
'Try the mobile interface': 'Try the mobile interface',
|
||||||
|
'try view': 'try view',
|
||||||
'Type some Python code in here and hit Return (Enter) to execute it.': 'Type some Python code in here and hit Return (Enter) to execute it.',
|
'Type some Python code in here and hit Return (Enter) to execute it.': 'Type some Python code in here and hit Return (Enter) to execute it.',
|
||||||
'Unable to check for upgrades': 'No es posible verificar la existencia de actualizaciones',
|
'Unable to check for upgrades': 'No es posible verificar la existencia de actualizaciones',
|
||||||
'unable to create application "%s"': 'no es posible crear la aplicación "%s"',
|
'unable to create application "%s"': 'no es posible crear la aplicación "%s"',
|
||||||
@@ -332,9 +381,12 @@
|
|||||||
'update': 'actualizar',
|
'update': 'actualizar',
|
||||||
'update all languages': 'actualizar todos los lenguajes',
|
'update all languages': 'actualizar todos los lenguajes',
|
||||||
'Update:': 'Actualice:',
|
'Update:': 'Actualice:',
|
||||||
|
'upgrade now to %s': 'upgrade now to %s',
|
||||||
'upgrade web2py now': 'actualize web2py ahora',
|
'upgrade web2py now': 'actualize web2py ahora',
|
||||||
'Upload': 'Upload',
|
'Upload': 'Upload',
|
||||||
'Upload & install packed application': 'Suba e instale aplicación empaquetada',
|
'Upload & install packed application': 'Suba e instale aplicación empaquetada',
|
||||||
|
'Upload a package:': 'Upload a package:',
|
||||||
|
'Upload and install packed application': 'Upload and install packed application',
|
||||||
'upload application:': 'subir aplicación:',
|
'upload application:': 'subir aplicación:',
|
||||||
'Upload existing application': 'Suba esta aplicación',
|
'Upload existing application': 'Suba esta aplicación',
|
||||||
'upload file:': 'suba archivo:',
|
'upload file:': 'suba archivo:',
|
||||||
@@ -348,6 +400,7 @@
|
|||||||
'view': 'vista',
|
'view': 'vista',
|
||||||
'Views': 'Vistas',
|
'Views': 'Vistas',
|
||||||
'views': 'vistas',
|
'views': 'vistas',
|
||||||
|
'Web Framework': 'Web Framework',
|
||||||
'web2py is up to date': 'web2py está actualizado',
|
'web2py is up to date': 'web2py está actualizado',
|
||||||
'web2py online debugger': 'web2py online debugger',
|
'web2py online debugger': 'web2py online debugger',
|
||||||
'web2py Recent Tweets': 'Tweets Recientes de web2py',
|
'web2py Recent Tweets': 'Tweets Recientes de web2py',
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ def verify_password(password):
|
|||||||
session.pam_user = None
|
session.pam_user = None
|
||||||
if DEMO_MODE:
|
if DEMO_MODE:
|
||||||
return True
|
return True
|
||||||
elif not 'password' in _config:
|
elif not _config.get('password'):
|
||||||
return False
|
return False
|
||||||
elif _config['password'].startswith('pam_user:'):
|
elif _config['password'].startswith('pam_user:'):
|
||||||
session.pam_user = _config['password'][9:].strip()
|
session.pam_user = _config['password'][9:].strip()
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[DEFAULT]
|
||||||
|
theme = web2py
|
||||||
|
|
||||||
|
[editor]
|
||||||
|
theme = web2py
|
||||||
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
position: absolute ! important;
|
position: absolute ! important;
|
||||||
top: 0; left: 0;
|
top: 0; left: 0;
|
||||||
width: 100% ! important;
|
width: 100% ! important;
|
||||||
z-index: 9999;
|
z-index: 1028;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BREAKPOINTS */
|
/* BREAKPOINTS */
|
||||||
|
|||||||
@@ -179,7 +179,7 @@
|
|||||||
});
|
});
|
||||||
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
||||||
doc.on('click', "input.datetime", function () {
|
doc.on('click', "input.datetime", function () {
|
||||||
var tformat = $(this).data('w2p_datetime_format')
|
var tformat = $(this).data('w2p_datetime_format');
|
||||||
var active = $(this).data('w2p_datetime');
|
var active = $(this).data('w2p_datetime');
|
||||||
var format = (typeof tformat != 'undefined') ? tformat : datetime_format;
|
var format = (typeof tformat != 'undefined') ? tformat : datetime_format;
|
||||||
if(active === undefined) {
|
if(active === undefined) {
|
||||||
@@ -196,7 +196,7 @@
|
|||||||
});
|
});
|
||||||
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
||||||
doc.on('click', "input.date", function () {
|
doc.on('click', "input.date", function () {
|
||||||
var tformat = $(this).data('w2p_date_format')
|
var tformat = $(this).data('w2p_date_format');
|
||||||
var active = $(this).data('w2p_date');
|
var active = $(this).data('w2p_date');
|
||||||
var format = (typeof tformat != 'undefined') ? tformat : date_format;
|
var format = (typeof tformat != 'undefined') ? tformat : date_format;
|
||||||
if(active === undefined) {
|
if(active === undefined) {
|
||||||
@@ -277,6 +277,8 @@
|
|||||||
ajax_page: function (method, action, data, target, element) {
|
ajax_page: function (method, action, data, target, element) {
|
||||||
/* element is a new parameter, but should be put be put in front */
|
/* element is a new parameter, but should be put be put in front */
|
||||||
if(element == undefined) element = $(document);
|
if(element == undefined) element = $(document);
|
||||||
|
/* if target is not there, fill it with something that there isn't in the page*/
|
||||||
|
if(target == undefined || target == '') target = 'w2p_none';
|
||||||
if(web2py.fire(element, 'ajax:before', null, target )) { /*test a usecase, should stop here if returns false */
|
if(web2py.fire(element, 'ajax:before', null, target )) { /*test a usecase, should stop here if returns false */
|
||||||
$.ajax({
|
$.ajax({
|
||||||
'type': method,
|
'type': method,
|
||||||
@@ -303,12 +305,7 @@
|
|||||||
},
|
},
|
||||||
'complete': function (xhr, status) {
|
'complete': function (xhr, status) {
|
||||||
web2py.fire(element, 'ajax:complete', [xhr, status], target);
|
web2py.fire(element, 'ajax:complete', [xhr, status], target);
|
||||||
var html = xhr.responseText;
|
web2py.updatePage(xhr, target); /* Parse and load the html received */
|
||||||
var content = xhr.getResponseHeader('web2py-component-content');
|
|
||||||
var t = $('#' + target);
|
|
||||||
if(content == 'prepend') t.prepend(html);
|
|
||||||
else if(content == 'append') t.append(html);
|
|
||||||
else if(content != 'hide') t.html(html);
|
|
||||||
web2py.trap_form(action, target);
|
web2py.trap_form(action, target);
|
||||||
web2py.trap_link(target);
|
web2py.trap_link(target);
|
||||||
web2py.ajax_init('#' + target);
|
web2py.ajax_init('#' + target);
|
||||||
@@ -378,6 +375,20 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
updatePage: function (xhr, target) {
|
||||||
|
var t = $('#' + target);
|
||||||
|
var html = $.parseHTML(xhr.responseText, document, true);
|
||||||
|
var title_elements = $(html).filter('title').add($(html).find('title'));
|
||||||
|
var title = title_elements.last().text();
|
||||||
|
if (title) {
|
||||||
|
title_elements.remove(); /* Remove any title elements from the response */
|
||||||
|
document.title = $.trim(title); /* Set the new document title */
|
||||||
|
}
|
||||||
|
var content = xhr.getResponseHeader('web2py-component-content');
|
||||||
|
if(content == 'prepend') t.prepend(xhr.responseText);
|
||||||
|
else if(content == 'append') t.append(xhr.responseText);
|
||||||
|
else if(content != 'hide') t.html(html);
|
||||||
|
},
|
||||||
calc_entropy: function (mystring) {
|
calc_entropy: function (mystring) {
|
||||||
/* calculate a simple entropy for a given string */
|
/* calculate a simple entropy for a given string */
|
||||||
var csets = new Array(
|
var csets = new Array(
|
||||||
@@ -569,9 +580,9 @@
|
|||||||
}
|
}
|
||||||
if(target == undefined) {
|
if(target == undefined) {
|
||||||
if(method == 'GET') {
|
if(method == 'GET') {
|
||||||
web2py.ajax_page('get', action, [], 'bogus', el); //fixme?
|
web2py.ajax_page('get', action, [], '', el);
|
||||||
} else if(method == 'POST') {
|
} else if(method == 'POST') {
|
||||||
web2py.ajax_page('post', action, [], 'bogus', el); //fixme?
|
web2py.ajax_page('post', action, [], '', el);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(method == 'GET') {
|
if(method == 'GET') {
|
||||||
@@ -689,3 +700,4 @@ web2py_trap_link = jQuery.web2py.trap_link;
|
|||||||
web2py_calc_entropy = jQuery.web2py.calc_entropy;
|
web2py_calc_entropy = jQuery.web2py.calc_entropy;
|
||||||
*/
|
*/
|
||||||
/* compatibility code - end*/
|
/* compatibility code - end*/
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,4 @@ jQuery(function(){
|
|||||||
hoverMenu(); // first page load
|
hoverMenu(); // first page load
|
||||||
jQuery(window).resize(hoverMenu); // on resize event
|
jQuery(window).resize(hoverMenu); // on resize event
|
||||||
jQuery('ul.nav li.dropdown a').click(function(){window.location=jQuery(this).attr('href');});
|
jQuery('ul.nav li.dropdown a').click(function(){window.location=jQuery(this).attr('href');});
|
||||||
// make all buttons bootstrap buttons
|
|
||||||
jQuery('button, form input[type="submit"], form input[type="button"]').addClass('btn');
|
|
||||||
});
|
});
|
||||||
@@ -79,8 +79,8 @@
|
|||||||
return marker;
|
return marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
{{if filetype=='html':}}
|
{{if filetype in ('html', 'js', 'css'):}}
|
||||||
// must be here or break emmet/zencoding for html
|
// must be here or break emmet/zencoding
|
||||||
CodeMirror.defaults.extraKeys["Ctrl-S"] =
|
CodeMirror.defaults.extraKeys["Ctrl-S"] =
|
||||||
function(instance) {
|
function(instance) {
|
||||||
doClickSave();};
|
doClickSave();};
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ if request.function == 'manage':
|
|||||||
auth.requires_membership(manager_role)(lambda: None)()
|
auth.requires_membership(manager_role)(lambda: None)()
|
||||||
menu = False
|
menu = False
|
||||||
elif (request.application == 'admin' and not session.authorized) or \
|
elif (request.application == 'admin' and not session.authorized) or \
|
||||||
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
|
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
|
||||||
redirect(URL('admin', 'default', 'index',
|
redirect(URL('admin', 'default', 'index',
|
||||||
vars=dict(send=URL(args=request.args, vars=request.vars))))
|
vars=dict(send=URL(args=request.args, vars=request.vars))))
|
||||||
else:
|
else:
|
||||||
@@ -540,30 +540,30 @@ def table_template(table):
|
|||||||
|
|
||||||
def bg_graph_model():
|
def bg_graph_model():
|
||||||
graph = pgv.AGraph(layout='dot', directed=True, strict=False, rankdir='LR')
|
graph = pgv.AGraph(layout='dot', directed=True, strict=False, rankdir='LR')
|
||||||
|
|
||||||
subgraphs = dict()
|
subgraphs = dict()
|
||||||
for tablename in db.tables:
|
for tablename in db.tables:
|
||||||
if hasattr(db[tablename],'_meta_graphmodel'):
|
if hasattr(db[tablename],'_meta_graphmodel'):
|
||||||
meta_graphmodel = db[tablename]._meta_graphmodel
|
meta_graphmodel = db[tablename]._meta_graphmodel
|
||||||
else:
|
else:
|
||||||
meta_graphmodel = dict(group='Undefined', color='#ECECEC')
|
meta_graphmodel = dict(group='Undefined', color='#ECECEC')
|
||||||
|
|
||||||
group = meta_graphmodel['group'].replace(' ', '')
|
group = meta_graphmodel['group'].replace(' ', '')
|
||||||
if not subgraphs.has_key(group):
|
if not subgraphs.has_key(group):
|
||||||
subgraphs[group] = dict(meta=meta_graphmodel, tables=[])
|
subgraphs[group] = dict(meta=meta_graphmodel, tables=[])
|
||||||
subgraphs[group]['tables'].append(tablename)
|
subgraphs[group]['tables'].append(tablename)
|
||||||
else:
|
else:
|
||||||
subgraphs[group]['tables'].append(tablename)
|
subgraphs[group]['tables'].append(tablename)
|
||||||
|
|
||||||
graph.add_node(tablename, name=tablename, shape='plaintext',
|
graph.add_node(tablename, name=tablename, shape='plaintext',
|
||||||
label=table_template(tablename))
|
label=table_template(tablename))
|
||||||
|
|
||||||
for n, key in enumerate(subgraphs.iterkeys()):
|
for n, key in enumerate(subgraphs.iterkeys()):
|
||||||
graph.subgraph(nbunch=subgraphs[key]['tables'],
|
graph.subgraph(nbunch=subgraphs[key]['tables'],
|
||||||
name='cluster%d' % n,
|
name='cluster%d' % n,
|
||||||
style='filled',
|
style='filled',
|
||||||
color=subgraphs[key]['meta']['color'],
|
color=subgraphs[key]['meta']['color'],
|
||||||
label=subgraphs[key]['meta']['group'])
|
label=subgraphs[key]['meta']['group'])
|
||||||
|
|
||||||
for tablename in db.tables:
|
for tablename in db.tables:
|
||||||
for field in db[tablename]:
|
for field in db[tablename]:
|
||||||
@@ -580,14 +580,14 @@ def bg_graph_model():
|
|||||||
#return graph.draw(format='png', prog='dot')
|
#return graph.draw(format='png', prog='dot')
|
||||||
if not request.args:
|
if not request.args:
|
||||||
return graph.draw(format='png', prog='dot')
|
return graph.draw(format='png', prog='dot')
|
||||||
else:
|
else:
|
||||||
response.headers['Content-Disposition']='attachment;filename=graph.%s'%request.args(0)
|
response.headers['Content-Disposition']='attachment;filename=graph.%s'%request.args(0)
|
||||||
if request.args(0) == 'dot':
|
if request.args(0) == 'dot':
|
||||||
return graph.string()
|
return graph.string()
|
||||||
else:
|
else:
|
||||||
return graph.draw(format=request.args(0), prog='dot')
|
return graph.draw(format=request.args(0), prog='dot')
|
||||||
|
|
||||||
def graph_model():
|
def graph_model():
|
||||||
return dict(databases=databases, pgv=pgv)
|
return dict(databases=databases, pgv=pgv)
|
||||||
|
|
||||||
def manage():
|
def manage():
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ def get(args):
|
|||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
obj = globals(),get(args[0])
|
obj = globals(),get(args[0])
|
||||||
for k in range(1,len(args)):
|
for k in range(1,len(args)):
|
||||||
obj = getattr(obj,args[k])
|
obj = getattr(obj,args[k])
|
||||||
return obj
|
return obj
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def vars():
|
def vars():
|
||||||
"""the running controller function!"""
|
"""the running controller function!"""
|
||||||
title = '.'.join(request.args)
|
title = '.'.join(request.args)
|
||||||
@@ -27,7 +27,7 @@ def vars():
|
|||||||
d = getattr(obj,'__bases__',None)
|
d = getattr(obj,'__bases__',None)
|
||||||
|
|
||||||
for key in keys:
|
for key in keys:
|
||||||
a = getattr(obj,key,None)
|
a = getattr(obj,key,None)
|
||||||
if a and not isinstance(a,DAL):
|
if a and not isinstance(a,DAL):
|
||||||
doc1 = getattr(a, '__doc__', '')
|
doc1 = getattr(a, '__doc__', '')
|
||||||
t1 = type(a)
|
t1 = type(a)
|
||||||
@@ -38,7 +38,7 @@ def vars():
|
|||||||
else:
|
else:
|
||||||
doc = 'Unkown'
|
doc = 'Unkown'
|
||||||
keys = []
|
keys = []
|
||||||
t = c = d = None
|
t = c = d = None
|
||||||
else:
|
else:
|
||||||
raise HTTP(400)
|
raise HTTP(400)
|
||||||
return dict(
|
return dict(
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
def hello1():
|
def hello1():
|
||||||
""" simple page without template """
|
""" simple page without template """
|
||||||
|
|
||||||
|
|||||||
@@ -179,7 +179,7 @@
|
|||||||
});
|
});
|
||||||
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
||||||
doc.on('click', "input.datetime", function () {
|
doc.on('click', "input.datetime", function () {
|
||||||
var tformat = $(this).data('w2p_datetime_format')
|
var tformat = $(this).data('w2p_datetime_format');
|
||||||
var active = $(this).data('w2p_datetime');
|
var active = $(this).data('w2p_datetime');
|
||||||
var format = (typeof tformat != 'undefined') ? tformat : datetime_format;
|
var format = (typeof tformat != 'undefined') ? tformat : datetime_format;
|
||||||
if(active === undefined) {
|
if(active === undefined) {
|
||||||
@@ -196,7 +196,7 @@
|
|||||||
});
|
});
|
||||||
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
||||||
doc.on('click', "input.date", function () {
|
doc.on('click', "input.date", function () {
|
||||||
var tformat = $(this).data('w2p_date_format')
|
var tformat = $(this).data('w2p_date_format');
|
||||||
var active = $(this).data('w2p_date');
|
var active = $(this).data('w2p_date');
|
||||||
var format = (typeof tformat != 'undefined') ? tformat : date_format;
|
var format = (typeof tformat != 'undefined') ? tformat : date_format;
|
||||||
if(active === undefined) {
|
if(active === undefined) {
|
||||||
@@ -277,6 +277,8 @@
|
|||||||
ajax_page: function (method, action, data, target, element) {
|
ajax_page: function (method, action, data, target, element) {
|
||||||
/* element is a new parameter, but should be put be put in front */
|
/* element is a new parameter, but should be put be put in front */
|
||||||
if(element == undefined) element = $(document);
|
if(element == undefined) element = $(document);
|
||||||
|
/* if target is not there, fill it with something that there isn't in the page*/
|
||||||
|
if(target == undefined || target == '') target = 'w2p_none';
|
||||||
if(web2py.fire(element, 'ajax:before', null, target )) { /*test a usecase, should stop here if returns false */
|
if(web2py.fire(element, 'ajax:before', null, target )) { /*test a usecase, should stop here if returns false */
|
||||||
$.ajax({
|
$.ajax({
|
||||||
'type': method,
|
'type': method,
|
||||||
@@ -303,12 +305,7 @@
|
|||||||
},
|
},
|
||||||
'complete': function (xhr, status) {
|
'complete': function (xhr, status) {
|
||||||
web2py.fire(element, 'ajax:complete', [xhr, status], target);
|
web2py.fire(element, 'ajax:complete', [xhr, status], target);
|
||||||
var html = xhr.responseText;
|
web2py.updatePage(xhr, target); /* Parse and load the html received */
|
||||||
var content = xhr.getResponseHeader('web2py-component-content');
|
|
||||||
var t = $('#' + target);
|
|
||||||
if(content == 'prepend') t.prepend(html);
|
|
||||||
else if(content == 'append') t.append(html);
|
|
||||||
else if(content != 'hide') t.html(html);
|
|
||||||
web2py.trap_form(action, target);
|
web2py.trap_form(action, target);
|
||||||
web2py.trap_link(target);
|
web2py.trap_link(target);
|
||||||
web2py.ajax_init('#' + target);
|
web2py.ajax_init('#' + target);
|
||||||
@@ -378,6 +375,20 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
updatePage: function (xhr, target) {
|
||||||
|
var t = $('#' + target);
|
||||||
|
var html = $.parseHTML(xhr.responseText, document, true);
|
||||||
|
var title_elements = $(html).filter('title').add($(html).find('title'));
|
||||||
|
var title = title_elements.last().text();
|
||||||
|
if (title) {
|
||||||
|
title_elements.remove(); /* Remove any title elements from the response */
|
||||||
|
document.title = $.trim(title); /* Set the new document title */
|
||||||
|
}
|
||||||
|
var content = xhr.getResponseHeader('web2py-component-content');
|
||||||
|
if(content == 'prepend') t.prepend(xhr.responseText);
|
||||||
|
else if(content == 'append') t.append(xhr.responseText);
|
||||||
|
else if(content != 'hide') t.html(html);
|
||||||
|
},
|
||||||
calc_entropy: function (mystring) {
|
calc_entropy: function (mystring) {
|
||||||
/* calculate a simple entropy for a given string */
|
/* calculate a simple entropy for a given string */
|
||||||
var csets = new Array(
|
var csets = new Array(
|
||||||
@@ -569,9 +580,9 @@
|
|||||||
}
|
}
|
||||||
if(target == undefined) {
|
if(target == undefined) {
|
||||||
if(method == 'GET') {
|
if(method == 'GET') {
|
||||||
web2py.ajax_page('get', action, [], 'bogus', el); //fixme?
|
web2py.ajax_page('get', action, [], '', el);
|
||||||
} else if(method == 'POST') {
|
} else if(method == 'POST') {
|
||||||
web2py.ajax_page('post', action, [], 'bogus', el); //fixme?
|
web2py.ajax_page('post', action, [], '', el);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(method == 'GET') {
|
if(method == 'GET') {
|
||||||
@@ -689,3 +700,4 @@ web2py_trap_link = jQuery.web2py.trap_link;
|
|||||||
web2py_calc_entropy = jQuery.web2py.calc_entropy;
|
web2py_calc_entropy = jQuery.web2py.calc_entropy;
|
||||||
*/
|
*/
|
||||||
/* compatibility code - end*/
|
/* compatibility code - end*/
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,4 @@ jQuery(function(){
|
|||||||
hoverMenu(); // first page load
|
hoverMenu(); // first page load
|
||||||
jQuery(window).resize(hoverMenu); // on resize event
|
jQuery(window).resize(hoverMenu); // on resize event
|
||||||
jQuery('ul.nav li.dropdown a').click(function(){window.location=jQuery(this).attr('href');});
|
jQuery('ul.nav li.dropdown a').click(function(){window.location=jQuery(this).attr('href');});
|
||||||
// make all buttons bootstrap buttons
|
|
||||||
jQuery('button, form input[type="submit"], form input[type="button"]').addClass('btn');
|
|
||||||
});
|
});
|
||||||
@@ -50,7 +50,7 @@ if request.function == 'manage':
|
|||||||
auth.requires_membership(manager_role)(lambda: None)()
|
auth.requires_membership(manager_role)(lambda: None)()
|
||||||
menu = False
|
menu = False
|
||||||
elif (request.application == 'admin' and not session.authorized) or \
|
elif (request.application == 'admin' and not session.authorized) or \
|
||||||
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
|
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
|
||||||
redirect(URL('admin', 'default', 'index',
|
redirect(URL('admin', 'default', 'index',
|
||||||
vars=dict(send=URL(args=request.args, vars=request.vars))))
|
vars=dict(send=URL(args=request.args, vars=request.vars))))
|
||||||
else:
|
else:
|
||||||
@@ -540,30 +540,30 @@ def table_template(table):
|
|||||||
|
|
||||||
def bg_graph_model():
|
def bg_graph_model():
|
||||||
graph = pgv.AGraph(layout='dot', directed=True, strict=False, rankdir='LR')
|
graph = pgv.AGraph(layout='dot', directed=True, strict=False, rankdir='LR')
|
||||||
|
|
||||||
subgraphs = dict()
|
subgraphs = dict()
|
||||||
for tablename in db.tables:
|
for tablename in db.tables:
|
||||||
if hasattr(db[tablename],'_meta_graphmodel'):
|
if hasattr(db[tablename],'_meta_graphmodel'):
|
||||||
meta_graphmodel = db[tablename]._meta_graphmodel
|
meta_graphmodel = db[tablename]._meta_graphmodel
|
||||||
else:
|
else:
|
||||||
meta_graphmodel = dict(group='Undefined', color='#ECECEC')
|
meta_graphmodel = dict(group='Undefined', color='#ECECEC')
|
||||||
|
|
||||||
group = meta_graphmodel['group'].replace(' ', '')
|
group = meta_graphmodel['group'].replace(' ', '')
|
||||||
if not subgraphs.has_key(group):
|
if not subgraphs.has_key(group):
|
||||||
subgraphs[group] = dict(meta=meta_graphmodel, tables=[])
|
subgraphs[group] = dict(meta=meta_graphmodel, tables=[])
|
||||||
subgraphs[group]['tables'].append(tablename)
|
subgraphs[group]['tables'].append(tablename)
|
||||||
else:
|
else:
|
||||||
subgraphs[group]['tables'].append(tablename)
|
subgraphs[group]['tables'].append(tablename)
|
||||||
|
|
||||||
graph.add_node(tablename, name=tablename, shape='plaintext',
|
graph.add_node(tablename, name=tablename, shape='plaintext',
|
||||||
label=table_template(tablename))
|
label=table_template(tablename))
|
||||||
|
|
||||||
for n, key in enumerate(subgraphs.iterkeys()):
|
for n, key in enumerate(subgraphs.iterkeys()):
|
||||||
graph.subgraph(nbunch=subgraphs[key]['tables'],
|
graph.subgraph(nbunch=subgraphs[key]['tables'],
|
||||||
name='cluster%d' % n,
|
name='cluster%d' % n,
|
||||||
style='filled',
|
style='filled',
|
||||||
color=subgraphs[key]['meta']['color'],
|
color=subgraphs[key]['meta']['color'],
|
||||||
label=subgraphs[key]['meta']['group'])
|
label=subgraphs[key]['meta']['group'])
|
||||||
|
|
||||||
for tablename in db.tables:
|
for tablename in db.tables:
|
||||||
for field in db[tablename]:
|
for field in db[tablename]:
|
||||||
@@ -580,14 +580,14 @@ def bg_graph_model():
|
|||||||
#return graph.draw(format='png', prog='dot')
|
#return graph.draw(format='png', prog='dot')
|
||||||
if not request.args:
|
if not request.args:
|
||||||
return graph.draw(format='png', prog='dot')
|
return graph.draw(format='png', prog='dot')
|
||||||
else:
|
else:
|
||||||
response.headers['Content-Disposition']='attachment;filename=graph.%s'%request.args(0)
|
response.headers['Content-Disposition']='attachment;filename=graph.%s'%request.args(0)
|
||||||
if request.args(0) == 'dot':
|
if request.args(0) == 'dot':
|
||||||
return graph.string()
|
return graph.string()
|
||||||
else:
|
else:
|
||||||
return graph.draw(format=request.args(0), prog='dot')
|
return graph.draw(format=request.args(0), prog='dot')
|
||||||
|
|
||||||
def graph_model():
|
def graph_model():
|
||||||
return dict(databases=databases, pgv=pgv)
|
return dict(databases=databases, pgv=pgv)
|
||||||
|
|
||||||
def manage():
|
def manage():
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ def user():
|
|||||||
http://..../[app]/default/user/profile
|
http://..../[app]/default/user/profile
|
||||||
http://..../[app]/default/user/retrieve_password
|
http://..../[app]/default/user/retrieve_password
|
||||||
http://..../[app]/default/user/change_password
|
http://..../[app]/default/user/change_password
|
||||||
http://..../[app]/default/user/manage_users (requires membership in
|
http://..../[app]/default/user/manage_users (requires membership in
|
||||||
use @auth.requires_login()
|
use @auth.requires_login()
|
||||||
@auth.requires_membership('group name')
|
@auth.requires_membership('group name')
|
||||||
@auth.requires_permission('read','table name',record_id)
|
@auth.requires_permission('read','table name',record_id)
|
||||||
|
|||||||
@@ -179,7 +179,7 @@
|
|||||||
});
|
});
|
||||||
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
||||||
doc.on('click', "input.datetime", function () {
|
doc.on('click', "input.datetime", function () {
|
||||||
var tformat = $(this).data('w2p_datetime_format')
|
var tformat = $(this).data('w2p_datetime_format');
|
||||||
var active = $(this).data('w2p_datetime');
|
var active = $(this).data('w2p_datetime');
|
||||||
var format = (typeof tformat != 'undefined') ? tformat : datetime_format;
|
var format = (typeof tformat != 'undefined') ? tformat : datetime_format;
|
||||||
if(active === undefined) {
|
if(active === undefined) {
|
||||||
@@ -196,7 +196,7 @@
|
|||||||
});
|
});
|
||||||
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
||||||
doc.on('click', "input.date", function () {
|
doc.on('click', "input.date", function () {
|
||||||
var tformat = $(this).data('w2p_date_format')
|
var tformat = $(this).data('w2p_date_format');
|
||||||
var active = $(this).data('w2p_date');
|
var active = $(this).data('w2p_date');
|
||||||
var format = (typeof tformat != 'undefined') ? tformat : date_format;
|
var format = (typeof tformat != 'undefined') ? tformat : date_format;
|
||||||
if(active === undefined) {
|
if(active === undefined) {
|
||||||
@@ -277,6 +277,8 @@
|
|||||||
ajax_page: function (method, action, data, target, element) {
|
ajax_page: function (method, action, data, target, element) {
|
||||||
/* element is a new parameter, but should be put be put in front */
|
/* element is a new parameter, but should be put be put in front */
|
||||||
if(element == undefined) element = $(document);
|
if(element == undefined) element = $(document);
|
||||||
|
/* if target is not there, fill it with something that there isn't in the page*/
|
||||||
|
if(target == undefined || target == '') target = 'w2p_none';
|
||||||
if(web2py.fire(element, 'ajax:before', null, target )) { /*test a usecase, should stop here if returns false */
|
if(web2py.fire(element, 'ajax:before', null, target )) { /*test a usecase, should stop here if returns false */
|
||||||
$.ajax({
|
$.ajax({
|
||||||
'type': method,
|
'type': method,
|
||||||
@@ -303,12 +305,7 @@
|
|||||||
},
|
},
|
||||||
'complete': function (xhr, status) {
|
'complete': function (xhr, status) {
|
||||||
web2py.fire(element, 'ajax:complete', [xhr, status], target);
|
web2py.fire(element, 'ajax:complete', [xhr, status], target);
|
||||||
var html = xhr.responseText;
|
web2py.updatePage(xhr, target); /* Parse and load the html received */
|
||||||
var content = xhr.getResponseHeader('web2py-component-content');
|
|
||||||
var t = $('#' + target);
|
|
||||||
if(content == 'prepend') t.prepend(html);
|
|
||||||
else if(content == 'append') t.append(html);
|
|
||||||
else if(content != 'hide') t.html(html);
|
|
||||||
web2py.trap_form(action, target);
|
web2py.trap_form(action, target);
|
||||||
web2py.trap_link(target);
|
web2py.trap_link(target);
|
||||||
web2py.ajax_init('#' + target);
|
web2py.ajax_init('#' + target);
|
||||||
@@ -378,6 +375,20 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
updatePage: function (xhr, target) {
|
||||||
|
var t = $('#' + target);
|
||||||
|
var html = $.parseHTML(xhr.responseText, document, true);
|
||||||
|
var title_elements = $(html).filter('title').add($(html).find('title'));
|
||||||
|
var title = title_elements.last().text();
|
||||||
|
if (title) {
|
||||||
|
title_elements.remove(); /* Remove any title elements from the response */
|
||||||
|
document.title = $.trim(title); /* Set the new document title */
|
||||||
|
}
|
||||||
|
var content = xhr.getResponseHeader('web2py-component-content');
|
||||||
|
if(content == 'prepend') t.prepend(xhr.responseText);
|
||||||
|
else if(content == 'append') t.append(xhr.responseText);
|
||||||
|
else if(content != 'hide') t.html(html);
|
||||||
|
},
|
||||||
calc_entropy: function (mystring) {
|
calc_entropy: function (mystring) {
|
||||||
/* calculate a simple entropy for a given string */
|
/* calculate a simple entropy for a given string */
|
||||||
var csets = new Array(
|
var csets = new Array(
|
||||||
@@ -569,9 +580,9 @@
|
|||||||
}
|
}
|
||||||
if(target == undefined) {
|
if(target == undefined) {
|
||||||
if(method == 'GET') {
|
if(method == 'GET') {
|
||||||
web2py.ajax_page('get', action, [], 'bogus', el); //fixme?
|
web2py.ajax_page('get', action, [], '', el);
|
||||||
} else if(method == 'POST') {
|
} else if(method == 'POST') {
|
||||||
web2py.ajax_page('post', action, [], 'bogus', el); //fixme?
|
web2py.ajax_page('post', action, [], '', el);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(method == 'GET') {
|
if(method == 'GET') {
|
||||||
@@ -689,3 +700,4 @@ web2py_trap_link = jQuery.web2py.trap_link;
|
|||||||
web2py_calc_entropy = jQuery.web2py.calc_entropy;
|
web2py_calc_entropy = jQuery.web2py.calc_entropy;
|
||||||
*/
|
*/
|
||||||
/* compatibility code - end*/
|
/* compatibility code - end*/
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,4 @@ jQuery(function(){
|
|||||||
hoverMenu(); // first page load
|
hoverMenu(); // first page load
|
||||||
jQuery(window).resize(hoverMenu); // on resize event
|
jQuery(window).resize(hoverMenu); // on resize event
|
||||||
jQuery('ul.nav li.dropdown a').click(function(){window.location=jQuery(this).attr('href');});
|
jQuery('ul.nav li.dropdown a').click(function(){window.location=jQuery(this).attr('href');});
|
||||||
// make all buttons bootstrap buttons
|
|
||||||
jQuery('button, form input[type="submit"], form input[type="button"]').addClass('btn');
|
|
||||||
});
|
});
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
Usage:
|
Usage:
|
||||||
Install py2exe: http://sourceforge.net/projects/py2exe/files/
|
Install py2exe: http://sourceforge.net/projects/py2exe/files/
|
||||||
Copy script to the web2py directory
|
Copy script to the web2py directory
|
||||||
c:\bin\python26\python build_windows_exe.py py2exe
|
c:\bin\python26\python setup_exe.py py2exe
|
||||||
|
|
||||||
Adapted from http://bazaar.launchpad.net/~flavour/sahana-eden/trunk/view/head:/static/scripts/tools/standalone_exe.py
|
Adapted from http://bazaar.launchpad.net/~flavour/sahana-eden/trunk/view/head:/static/scripts/tools/standalone_exe.py
|
||||||
"""
|
"""
|
||||||
@@ -42,18 +42,18 @@ remove_build_files = Config.getboolean("Setup", "remove_build_files")
|
|||||||
|
|
||||||
|
|
||||||
# Python base version
|
# Python base version
|
||||||
python_version = sys.version[:3]
|
python_version = sys.version_info[:3]
|
||||||
|
|
||||||
# List of modules deprecated in python2.6 that are in the above set
|
# List of modules deprecated in python2.6 that are in the above set
|
||||||
py26_deprecated = ['mhlib', 'multifile', 'mimify', 'sets', 'MimeWriter']
|
py26_deprecated = ['mhlib', 'multifile', 'mimify', 'sets', 'MimeWriter']
|
||||||
|
|
||||||
if python_version == '2.6':
|
if python_version > (2,5):
|
||||||
base_modules += ['json', 'multiprocessing']
|
base_modules += ['json', 'multiprocessing', 'ldap']
|
||||||
base_modules = list(set(base_modules).difference(set(py26_deprecated)))
|
base_modules = list(set(base_modules).difference(set(py26_deprecated)))
|
||||||
|
|
||||||
|
|
||||||
#I don't know if this is even necessary
|
#I don't know if this is even necessary
|
||||||
if python_version == '2.6':
|
if python_version > (2,5):
|
||||||
# Python26 compatibility: http://www.py2exe.org/index.cgi/Tutorial#Step52
|
# Python26 compatibility: http://www.py2exe.org/index.cgi/Tutorial#Step52
|
||||||
try:
|
try:
|
||||||
shutil.copytree('C:\Bin\Microsoft.VC90.CRT', 'dist/')
|
shutil.copytree('C:\Bin\Microsoft.VC90.CRT', 'dist/')
|
||||||
@@ -62,8 +62,11 @@ if python_version == '2.6':
|
|||||||
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
console=['web2py.py'],
|
console=[{'script':'web2py.py',
|
||||||
|
'icon_resources': [(0, 'extras/icons/web2py.ico')]
|
||||||
|
}],
|
||||||
windows=[{'script':'web2py.py',
|
windows=[{'script':'web2py.py',
|
||||||
|
'icon_resources': [(1, 'extras/icons/web2py.ico')],
|
||||||
'dest_base':'web2py_no_console' # MUST NOT be just 'web2py' otherwise it overrides the standard web2py.exe
|
'dest_base':'web2py_no_console' # MUST NOT be just 'web2py' otherwise it overrides the standard web2py.exe
|
||||||
}],
|
}],
|
||||||
name="web2py",
|
name="web2py",
|
||||||
@@ -72,14 +75,9 @@ setup(
|
|||||||
author="Massimo DiPierro",
|
author="Massimo DiPierro",
|
||||||
license="LGPL v3",
|
license="LGPL v3",
|
||||||
data_files=[
|
data_files=[
|
||||||
'ABOUT',
|
'ABOUT',
|
||||||
'LICENSE',
|
'LICENSE',
|
||||||
'VERSION',
|
'VERSION'
|
||||||
'splashlogo.gif',
|
|
||||||
'logging.example.conf',
|
|
||||||
'options_std.py',
|
|
||||||
'app.example.yaml',
|
|
||||||
'queue.example.yaml'
|
|
||||||
],
|
],
|
||||||
options={'py2exe': {
|
options={'py2exe': {
|
||||||
'packages': contributed_modules,
|
'packages': contributed_modules,
|
||||||
@@ -126,6 +124,10 @@ else:
|
|||||||
copy_folders('applications/examples', 'applications/examples')
|
copy_folders('applications/examples', 'applications/examples')
|
||||||
print "Only web2py's admin, examples & welcome applications have been added"
|
print "Only web2py's admin, examples & welcome applications have been added"
|
||||||
|
|
||||||
|
copy_folders('extras', 'extras')
|
||||||
|
copy_folders('examples', 'examples')
|
||||||
|
copy_folders('handlers', 'handlers')
|
||||||
|
|
||||||
|
|
||||||
#should we copy project's site-packages into dist/site-packages
|
#should we copy project's site-packages into dist/site-packages
|
||||||
if copy_site_packages:
|
if copy_site_packages:
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,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_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']
|
__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 globals import current
|
||||||
from html import *
|
from html import *
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class MemcacheClient(object):
|
|||||||
value = obj[1] + value
|
value = obj[1] + value
|
||||||
self.client.set(key, (time.time(), value))
|
self.client.set(key, (time.time(), value))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def incr(self, key, value=1):
|
def incr(self, key, value=1):
|
||||||
return self.increment(key, value)
|
return self.increment(key, value)
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
Note: This module is intended as a plugin replacement of pbkdf2.py
|
Note: This module is intended as a plugin replacement of pbkdf2.py
|
||||||
by Armin Ronacher.
|
by Armin Ronacher.
|
||||||
|
|
||||||
Git repository:
|
Git repository:
|
||||||
$ git clone https://github.com/michele-comitini/pbkdf2_ctypes.git
|
$ git clone https://github.com/michele-comitini/pbkdf2_ctypes.git
|
||||||
|
|
||||||
:copyright: Copyright (c) 2013: Michele Comitini <mcm@glisco.it>
|
:copyright: Copyright (c) 2013: Michele Comitini <mcm@glisco.it>
|
||||||
@@ -79,7 +79,7 @@ def openssl_hashlib_to_crypto_map_get(hashfunc):
|
|||||||
crypto_hashfunc.restype = ctypes.c_void_p
|
crypto_hashfunc.restype = ctypes.c_void_p
|
||||||
return crypto_hashfunc()
|
return crypto_hashfunc()
|
||||||
|
|
||||||
|
|
||||||
def openssl_pbkdf2(data, salt, iterations, digest, keylen):
|
def openssl_pbkdf2(data, salt, iterations, digest, keylen):
|
||||||
"""OpenSSL compatibile wrapper
|
"""OpenSSL compatibile wrapper
|
||||||
"""
|
"""
|
||||||
@@ -92,7 +92,7 @@ def openssl_pbkdf2(data, salt, iterations, digest, keylen):
|
|||||||
c_iter = ctypes.c_int(iterations)
|
c_iter = ctypes.c_int(iterations)
|
||||||
c_keylen = ctypes.c_int(keylen)
|
c_keylen = ctypes.c_int(keylen)
|
||||||
c_buff = ctypes.create_string_buffer(keylen)
|
c_buff = ctypes.create_string_buffer(keylen)
|
||||||
|
|
||||||
# PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
|
# PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
|
||||||
# const unsigned char *salt, int saltlen, int iter,
|
# const unsigned char *salt, int saltlen, int iter,
|
||||||
# const EVP_MD *digest,
|
# const EVP_MD *digest,
|
||||||
@@ -102,7 +102,7 @@ def openssl_pbkdf2(data, salt, iterations, digest, keylen):
|
|||||||
ctypes.c_char_p, ctypes.c_int,
|
ctypes.c_char_p, ctypes.c_int,
|
||||||
ctypes.c_int, ctypes.c_void_p,
|
ctypes.c_int, ctypes.c_void_p,
|
||||||
ctypes.c_int, ctypes.c_char_p]
|
ctypes.c_int, ctypes.c_char_p]
|
||||||
|
|
||||||
crypto.PKCS5_PBKDF2_HMAC.restype = ctypes.c_int
|
crypto.PKCS5_PBKDF2_HMAC.restype = ctypes.c_int
|
||||||
err = crypto.PKCS5_PBKDF2_HMAC(c_pass, c_passlen,
|
err = crypto.PKCS5_PBKDF2_HMAC(c_pass, c_passlen,
|
||||||
c_salt, c_saltlen,
|
c_salt, c_saltlen,
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class PDF(object):
|
|||||||
canvas.setLineWidth(4)
|
canvas.setLineWidth(4)
|
||||||
canvas.line(0, -1.25 * cm, 21.7 * cm, -1.25 * cm)
|
canvas.line(0, -1.25 * cm, 21.7 * cm, -1.25 * cm)
|
||||||
canvas.restoreState()
|
canvas.restoreState()
|
||||||
|
|
||||||
canvas.saveState()
|
canvas.saveState()
|
||||||
notes = listify(invoice.get('notes',''))
|
notes = listify(invoice.get('notes',''))
|
||||||
textobject = canvas.beginText(1 * cm, -25 * cm)
|
textobject = canvas.beginText(1 * cm, -25 * cm)
|
||||||
@@ -57,7 +57,7 @@ class PDF(object):
|
|||||||
textobject.textLine('Pag.%s/%s' % (page+1,pages))
|
textobject.textLine('Pag.%s/%s' % (page+1,pages))
|
||||||
canvas.drawText(textobject)
|
canvas.drawText(textobject)
|
||||||
canvas.restoreState()
|
canvas.restoreState()
|
||||||
|
|
||||||
canvas.saveState()
|
canvas.saveState()
|
||||||
business_details = listify(invoice.get('from','FROM:'))
|
business_details = listify(invoice.get('from','FROM:'))
|
||||||
canvas.setFont(self.font_face, 9)
|
canvas.setFont(self.font_face, 9)
|
||||||
@@ -66,13 +66,13 @@ class PDF(object):
|
|||||||
textobject.textLine(line)
|
textobject.textLine(line)
|
||||||
canvas.drawText(textobject)
|
canvas.drawText(textobject)
|
||||||
canvas.restoreState()
|
canvas.restoreState()
|
||||||
|
|
||||||
canvas.saveState()
|
canvas.saveState()
|
||||||
client_info = listify(invoice.get('to','TO:'))
|
client_info = listify(invoice.get('to','TO:'))
|
||||||
textobject = canvas.beginText(1.5 * cm, -2.5 * cm)
|
textobject = canvas.beginText(1.5 * cm, -2.5 * cm)
|
||||||
for line in client_info:
|
for line in client_info:
|
||||||
textobject.textLine(line)
|
textobject.textLine(line)
|
||||||
canvas.drawText(textobject)
|
canvas.drawText(textobject)
|
||||||
canvas.restoreState()
|
canvas.restoreState()
|
||||||
|
|
||||||
textobject = canvas.beginText(1.5 * cm, -6.75 * cm)
|
textobject = canvas.beginText(1.5 * cm, -6.75 * cm)
|
||||||
@@ -86,7 +86,7 @@ class PDF(object):
|
|||||||
data = [invoice_items[0]]
|
data = [invoice_items[0]]
|
||||||
for item in items:
|
for item in items:
|
||||||
data.append([
|
data.append([
|
||||||
self.format_currency(x)
|
self.format_currency(x)
|
||||||
if isinstance(x,float) else x
|
if isinstance(x,float) else x
|
||||||
for x in item])
|
for x in item])
|
||||||
righta = [k for k,v in enumerate(items[0])
|
righta = [k for k,v in enumerate(items[0])
|
||||||
@@ -116,10 +116,10 @@ class PDF(object):
|
|||||||
data = [invoice['totals'][0]]
|
data = [invoice['totals'][0]]
|
||||||
for item in items:
|
for item in items:
|
||||||
data.append([
|
data.append([
|
||||||
self.format_currency(x)
|
self.format_currency(x)
|
||||||
if isinstance(x,float) else x
|
if isinstance(x,float) else x
|
||||||
for x in item])
|
for x in item])
|
||||||
righta = [k for k,v in enumerate(items[0])
|
righta = [k for k,v in enumerate(items[0])
|
||||||
if isinstance(v,(int,float,Decimal))]
|
if isinstance(v,(int,float,Decimal))]
|
||||||
total = self.format_currency(invoice['total'])
|
total = self.format_currency(invoice['total'])
|
||||||
data.append(['']*(len(items[0])-1)+[total])
|
data.append(['']*(len(items[0])-1)+[total])
|
||||||
|
|||||||
@@ -90,13 +90,13 @@ def populate(table, n=None, default=True, compute=False, contents={}):
|
|||||||
can be used in two ways:
|
can be used in two ways:
|
||||||
|
|
||||||
>>> populate(db.tablename, n=100)
|
>>> populate(db.tablename, n=100)
|
||||||
|
|
||||||
or
|
or
|
||||||
|
|
||||||
>>> for k,row in enumerate(populate(db.tablename)): print row
|
>>> for k,row in enumerate(populate(db.tablename)): print row
|
||||||
"""
|
"""
|
||||||
|
|
||||||
generator = populate_generator(table, default=default,
|
generator = populate_generator(table, default=default,
|
||||||
compute=compute, contents=contents)
|
compute=compute, contents=contents)
|
||||||
if n is not None:
|
if n is not None:
|
||||||
for k,record in enumerate(generator):
|
for k,record in enumerate(generator):
|
||||||
@@ -246,8 +246,8 @@ def populate_generator(table, default=True, compute=False, contents={}):
|
|||||||
record[fieldname] = random.choice(LAST_NAMES)
|
record[fieldname] = random.choice(LAST_NAMES)
|
||||||
elif fieldname.find('username')>=0:
|
elif fieldname.find('username')>=0:
|
||||||
record[fieldname] = random.choice(FIRST_NAMES).lower()+str(random.randint(1000,9999))
|
record[fieldname] = random.choice(FIRST_NAMES).lower()+str(random.randint(1000,9999))
|
||||||
else:
|
else:
|
||||||
record[fieldname] = random.choice(FIRST_NAMES)+' '+random.choice(LAST_NAMES)
|
record[fieldname] = random.choice(FIRST_NAMES)+' '+random.choice(LAST_NAMES)
|
||||||
elif fieldname.find('phone')>=0:
|
elif fieldname.find('phone')>=0:
|
||||||
record[fieldname] = '(%s%s%s) %s%s%s-%s%s%s%s' % (
|
record[fieldname] = '(%s%s%s) %s%s%s-%s%s%s%s' % (
|
||||||
random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'))
|
random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'),random.choice('1234567890'))
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ def run(history, statement, env={}):
|
|||||||
for name, val in statement_module.__dict__.items():
|
for name, val in statement_module.__dict__.items():
|
||||||
if name not in old_globals or represent(val) != old_globals[name]:
|
if name not in old_globals or represent(val) != old_globals[name]:
|
||||||
new_globals[name] = val
|
new_globals[name] = val
|
||||||
|
|
||||||
if True in [isinstance(val, tuple(UNPICKLABLE_TYPES))
|
if True in [isinstance(val, tuple(UNPICKLABLE_TYPES))
|
||||||
for val in new_globals.values()]:
|
for val in new_globals.values()]:
|
||||||
# this statement added an unpicklable global. store the statement and
|
# this statement added an unpicklable global. store the statement and
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ class Stripe:
|
|||||||
|
|
||||||
def refund(self, charge_id):
|
def refund(self, charge_id):
|
||||||
params = urllib.urlencode({})
|
params = urllib.urlencode({})
|
||||||
u = urllib.urlopen(self.URL_REFUND % (self.key, charge_id),
|
u = urllib.urlopen(self.URL_REFUND % (self.key, charge_id),
|
||||||
params)
|
params)
|
||||||
return simplejson.loads(u.read())
|
return simplejson.loads(u.read())
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ class WebClient(object):
|
|||||||
else:
|
else:
|
||||||
self.method = 'GET' if method=='auto' else method
|
self.method = 'GET' if method=='auto' else method
|
||||||
data = None
|
data = None
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
self.response = opener.open(self.url, data)
|
self.response = opener.open(self.url, data)
|
||||||
self.time = time.time() - t0
|
self.time = time.time() - t0
|
||||||
except urllib2.HTTPError, error:
|
except urllib2.HTTPError, error:
|
||||||
|
|||||||
+54
-42
@@ -234,12 +234,6 @@ except ImportError:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
simplejson = None
|
simplejson = None
|
||||||
|
|
||||||
try:
|
|
||||||
from gluon import validators
|
|
||||||
have_validators = True
|
|
||||||
except (ImportError, SyntaxError):
|
|
||||||
have_validators = False
|
|
||||||
|
|
||||||
LOGGER = logging.getLogger("web2py.dal")
|
LOGGER = logging.getLogger("web2py.dal")
|
||||||
DEFAULT = lambda:0
|
DEFAULT = lambda:0
|
||||||
|
|
||||||
@@ -316,6 +310,11 @@ if not 'google' in DRIVERS:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
LOGGER.debug('no MySQL driver MySQLDB')
|
LOGGER.debug('no MySQL driver MySQLDB')
|
||||||
|
|
||||||
|
try:
|
||||||
|
import mysql.connector as mysqlconnector
|
||||||
|
DRIVERS.append("MySQL(mysqlconnector)")
|
||||||
|
except ImportError:
|
||||||
|
LOGGER.debug("no driver mysql.connector")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import psycopg2
|
import psycopg2
|
||||||
@@ -1085,7 +1084,7 @@ class BaseAdapter(ConnectionPool):
|
|||||||
elif not key in sql_fields:
|
elif not key in sql_fields:
|
||||||
del sql_fields_current[key]
|
del sql_fields_current[key]
|
||||||
ftype = sql_fields_old[key]['type']
|
ftype = sql_fields_old[key]['type']
|
||||||
if (self.dbengine in ('postgres',) and
|
if (self.dbengine in ('postgres',) and
|
||||||
ftype.startswith('geometry')):
|
ftype.startswith('geometry')):
|
||||||
geotype, parms = ftype[:-1].split('(')
|
geotype, parms = ftype[:-1].split('(')
|
||||||
schema = parms.split(',')[0]
|
schema = parms.split(',')[0]
|
||||||
@@ -1095,7 +1094,7 @@ class BaseAdapter(ConnectionPool):
|
|||||||
elif self.dbengine in ('firebird',):
|
elif self.dbengine in ('firebird',):
|
||||||
query = ['ALTER TABLE %s DROP %s;' % (tablename, key)]
|
query = ['ALTER TABLE %s DROP %s;' % (tablename, key)]
|
||||||
else:
|
else:
|
||||||
query = ['ALTER TABLE %s DROP COLUMN %s;' %
|
query = ['ALTER TABLE %s DROP COLUMN %s;' %
|
||||||
(tablename, key)]
|
(tablename, key)]
|
||||||
metadata_change = True
|
metadata_change = True
|
||||||
elif sql_fields[key]['sql'] != sql_fields_old[key]['sql'] \
|
elif sql_fields[key]['sql'] != sql_fields_old[key]['sql'] \
|
||||||
@@ -1135,9 +1134,9 @@ class BaseAdapter(ConnectionPool):
|
|||||||
self.log('faked!\n', table)
|
self.log('faked!\n', table)
|
||||||
else:
|
else:
|
||||||
self.execute(sub_query)
|
self.execute(sub_query)
|
||||||
# Caveat: mysql, oracle and firebird
|
# Caveat: mysql, oracle and firebird
|
||||||
# do not allow multiple alter table
|
# do not allow multiple alter table
|
||||||
# in one transaction so we must commit
|
# in one transaction so we must commit
|
||||||
# partial transactions and
|
# partial transactions and
|
||||||
# update table._dbt after alter table.
|
# update table._dbt after alter table.
|
||||||
if db._adapter.commit_on_alter_table:
|
if db._adapter.commit_on_alter_table:
|
||||||
@@ -1790,7 +1789,7 @@ class BaseAdapter(ConnectionPool):
|
|||||||
return self.connection.rollback()
|
return self.connection.rollback()
|
||||||
|
|
||||||
def close_connection(self):
|
def close_connection(self):
|
||||||
if self.connection:
|
if self.connection:
|
||||||
r = self.connection.close()
|
r = self.connection.close()
|
||||||
self.connection = None
|
self.connection = None
|
||||||
return r
|
return r
|
||||||
@@ -2156,9 +2155,15 @@ class BaseAdapter(ConnectionPool):
|
|||||||
for row in rowsobj.records:
|
for row in rowsobj.records:
|
||||||
box = row[tablename]
|
box = row[tablename]
|
||||||
for f,v in fields_virtual:
|
for f,v in fields_virtual:
|
||||||
box[f] = v.f(row)
|
try:
|
||||||
|
box[f] = v.f(row)
|
||||||
|
except AttributeError:
|
||||||
|
pass # not enough fields to define virtual field
|
||||||
for f,v in fields_lazy:
|
for f,v in fields_lazy:
|
||||||
box[f] = (v.handler or VirtualCommand)(v.f,row)
|
try:
|
||||||
|
box[f] = (v.handler or VirtualCommand)(v.f,row)
|
||||||
|
except AttributeError:
|
||||||
|
pass # not enough fields to define virtual field
|
||||||
|
|
||||||
### old style virtual fields
|
### old style virtual fields
|
||||||
for item in table.virtualfields:
|
for item in table.virtualfields:
|
||||||
@@ -2445,7 +2450,7 @@ class JDBCSQLiteAdapter(SQLiteAdapter):
|
|||||||
|
|
||||||
|
|
||||||
class MySQLAdapter(BaseAdapter):
|
class MySQLAdapter(BaseAdapter):
|
||||||
drivers = ('MySQLdb','pymysql')
|
drivers = ('MySQLdb','pymysql', 'mysqlconnector')
|
||||||
|
|
||||||
commit_on_alter_table = True
|
commit_on_alter_table = True
|
||||||
support_distributed_transaction = True
|
support_distributed_transaction = True
|
||||||
@@ -4418,7 +4423,7 @@ class GoogleSQLAdapter(UseDatabaseStoredFile,MySQLAdapter):
|
|||||||
|
|
||||||
def find_driver(self,adapter_args,uri=None):
|
def find_driver(self,adapter_args,uri=None):
|
||||||
self.adapter_args = adapter_args
|
self.adapter_args = adapter_args
|
||||||
self.driver = "google"
|
self.driver = "google"
|
||||||
|
|
||||||
class NoSQLAdapter(BaseAdapter):
|
class NoSQLAdapter(BaseAdapter):
|
||||||
can_select_for_update = False
|
can_select_for_update = False
|
||||||
@@ -5372,7 +5377,7 @@ class MongoDBAdapter(NoSQLAdapter):
|
|||||||
d = datetime.date(2000, 1, 1)
|
d = datetime.date(2000, 1, 1)
|
||||||
# mongodb doesn't has a time object and so it must datetime,
|
# mongodb doesn't has a time object and so it must datetime,
|
||||||
# string or integer
|
# string or integer
|
||||||
return datetime.datetime.combine(d, value)
|
return datetime.datetime.combine(d, value)
|
||||||
elif fieldtype == "blob":
|
elif fieldtype == "blob":
|
||||||
from bson import Binary
|
from bson import Binary
|
||||||
if not isinstance(value, Binary):
|
if not isinstance(value, Binary):
|
||||||
@@ -6504,9 +6509,10 @@ class IMAPAdapter(NoSQLAdapter):
|
|||||||
def _insert(self, table, fields):
|
def _insert(self, table, fields):
|
||||||
def add_payload(message, obj):
|
def add_payload(message, obj):
|
||||||
payload = Message()
|
payload = Message()
|
||||||
charset = obj.get("encoding", "utf-8")
|
payload.set_charset(obj.get("encoding", "utf-8"))
|
||||||
payload.set_type(obj.get("mime", None))
|
mime = obj.get("mime", None)
|
||||||
payload.set_charset(charset)
|
if mime:
|
||||||
|
payload.set_type(mime)
|
||||||
if "text" in obj:
|
if "text" in obj:
|
||||||
payload.set_payload(obj["text"])
|
payload.set_payload(obj["text"])
|
||||||
elif "payload" in obj:
|
elif "payload" in obj:
|
||||||
@@ -6544,7 +6550,9 @@ class IMAPAdapter(NoSQLAdapter):
|
|||||||
else:
|
else:
|
||||||
message[item] = ";".join([i for i in
|
message[item] = ";".join([i for i in
|
||||||
value])
|
value])
|
||||||
if not message.is_multipart():
|
if (not message.is_multipart() and
|
||||||
|
(not message.get_content_type().startswith(
|
||||||
|
"multipart"))):
|
||||||
if isinstance(content, basestring):
|
if isinstance(content, basestring):
|
||||||
message.set_payload(content)
|
message.set_payload(content)
|
||||||
elif len(content) > 0:
|
elif len(content) > 0:
|
||||||
@@ -6872,7 +6880,9 @@ def sqlhtml_validators(field):
|
|||||||
fieldtype
|
fieldtype
|
||||||
"""
|
"""
|
||||||
db = field.db
|
db = field.db
|
||||||
if not have_validators:
|
try:
|
||||||
|
from gluon import validators
|
||||||
|
except ImportError:
|
||||||
return []
|
return []
|
||||||
field_type, field_length = field.type, field.length
|
field_type, field_length = field.type, field.length
|
||||||
if isinstance(field_type, SQLCustomType):
|
if isinstance(field_type, SQLCustomType):
|
||||||
@@ -6938,14 +6948,14 @@ def sqlhtml_validators(field):
|
|||||||
refs = reduce(lambda a,b:a&b, [count(ids[i:i+30]) for i in rx])
|
refs = reduce(lambda a,b:a&b, [count(ids[i:i+30]) for i in rx])
|
||||||
else:
|
else:
|
||||||
refs = db(id.belongs(ids)).select(id)
|
refs = db(id.belongs(ids)).select(id)
|
||||||
return (refs and ', '.join(f(r,x.id) for x in refs) or '')
|
return (refs and ', '.join(f(r,x.id) for x in refs) or '')
|
||||||
field.represent = field.represent or list_ref_repr
|
field.represent = field.represent or list_ref_repr
|
||||||
if hasattr(referenced, '_format') and referenced._format:
|
if hasattr(referenced, '_format') and referenced._format:
|
||||||
requires = validators.IS_IN_DB(db,referenced._id,
|
requires = validators.IS_IN_DB(db,referenced._id,
|
||||||
referenced._format,multiple=True)
|
referenced._format,multiple=True)
|
||||||
else:
|
else:
|
||||||
requires = validators.IS_IN_DB(db,referenced._id,
|
requires = validators.IS_IN_DB(db,referenced._id,
|
||||||
multiple=True)
|
multiple=True)
|
||||||
if field.unique:
|
if field.unique:
|
||||||
requires._and = validators.IS_NOT_IN_DB(db,field)
|
requires._and = validators.IS_NOT_IN_DB(db,field)
|
||||||
if not field.notnull:
|
if not field.notnull:
|
||||||
@@ -8349,10 +8359,10 @@ class Table(object):
|
|||||||
self._id = field
|
self._id = field
|
||||||
for field in fields:
|
for field in fields:
|
||||||
if isinstance(field, (FieldMethod, FieldVirtual)):
|
if isinstance(field, (FieldMethod, FieldVirtual)):
|
||||||
virtual_fields.append(field)
|
virtual_fields.append(field)
|
||||||
elif isinstance(field, Field) and not field.name in fieldnames:
|
elif isinstance(field, Field) and not field.name in fieldnames:
|
||||||
if field.db is not None:
|
if field.db is not None:
|
||||||
field = copy.copy(field)
|
field = copy.copy(field)
|
||||||
include_new(field)
|
include_new(field)
|
||||||
elif isinstance(field, dict) and not field['fieldname'] in fieldnames:
|
elif isinstance(field, dict) and not field['fieldname'] in fieldnames:
|
||||||
include_new(Field(**field))
|
include_new(Field(**field))
|
||||||
@@ -8447,8 +8457,10 @@ class Table(object):
|
|||||||
clones.append(field.clone(
|
clones.append(field.clone(
|
||||||
unique=False, type=field.type if nfk else 'bigint'))
|
unique=False, type=field.type if nfk else 'bigint'))
|
||||||
archive_db.define_table(
|
archive_db.define_table(
|
||||||
archive_name, Field(current_record,field_type,
|
archive_name,
|
||||||
label=current_record_label), *clones)
|
Field(current_record,field_type,label=current_record_label),
|
||||||
|
*clones,**dict(format=self._format))
|
||||||
|
|
||||||
self._before_update.append(
|
self._before_update.append(
|
||||||
lambda qset,fs,db=archive_db,an=archive_name,cn=current_record:
|
lambda qset,fs,db=archive_db,an=archive_name,cn=current_record:
|
||||||
archive_record(qset,fs,db[an],cn))
|
archive_record(qset,fs,db[an],cn))
|
||||||
@@ -8914,7 +8926,7 @@ class Table(object):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
raise RuntimeError("Unable to parse line:%s field:%s value:'%s'"
|
raise RuntimeError("Unable to parse line:%s field:%s value:'%s'"
|
||||||
% (lineno+1,field,line[i]))
|
% (lineno+1,field,line[i]))
|
||||||
|
|
||||||
if not (id_map or cid is None or id_offset is None or unique_idx):
|
if not (id_map or cid is None or id_offset is None or unique_idx):
|
||||||
csv_id = long(line[cid])
|
csv_id = long(line[cid])
|
||||||
curr_id = self.insert(**dict(items))
|
curr_id = self.insert(**dict(items))
|
||||||
@@ -9207,13 +9219,13 @@ class Expression(object):
|
|||||||
|
|
||||||
def startswith(self, value):
|
def startswith(self, value):
|
||||||
db = self.db
|
db = self.db
|
||||||
if not self.type in ('string', 'text', 'json'):
|
if not self.type in ('string', 'text', 'json', 'upload'):
|
||||||
raise SyntaxError("startswith used with incompatible field type")
|
raise SyntaxError("startswith used with incompatible field type")
|
||||||
return Query(db, db._adapter.STARTSWITH, self, value)
|
return Query(db, db._adapter.STARTSWITH, self, value)
|
||||||
|
|
||||||
def endswith(self, value):
|
def endswith(self, value):
|
||||||
db = self.db
|
db = self.db
|
||||||
if not self.type in ('string', 'text', 'json'):
|
if not self.type in ('string', 'text', 'json', 'upload'):
|
||||||
raise SyntaxError("endswith used with incompatible field type")
|
raise SyntaxError("endswith used with incompatible field type")
|
||||||
return Query(db, db._adapter.ENDSWITH, self, value)
|
return Query(db, db._adapter.ENDSWITH, self, value)
|
||||||
|
|
||||||
@@ -9231,7 +9243,7 @@ class Expression(object):
|
|||||||
return self.contains('')
|
return self.contains('')
|
||||||
else:
|
else:
|
||||||
return reduce(all and AND or OR,subqueries)
|
return reduce(all and AND or OR,subqueries)
|
||||||
if not self.type in ('string', 'text', 'json') and not self.type.startswith('list:'):
|
if not self.type in ('string', 'text', 'json', 'upload') and not self.type.startswith('list:'):
|
||||||
raise SyntaxError("contains used with incompatible field type")
|
raise SyntaxError("contains used with incompatible field type")
|
||||||
return Query(db, db._adapter.CONTAINS, self, value, case_sensitive=case_sensitive)
|
return Query(db, db._adapter.CONTAINS, self, value, case_sensitive=case_sensitive)
|
||||||
|
|
||||||
@@ -9613,7 +9625,7 @@ class Field(Expression):
|
|||||||
else:
|
else:
|
||||||
filename = name
|
filename = name
|
||||||
# ## if file is in DB
|
# ## if file is in DB
|
||||||
if isinstance(self_uploadfield, (str, Field)):
|
if isinstance(self_uploadfield, (str, Field)):
|
||||||
return dict(path=None,filename=filename)
|
return dict(path=None,filename=filename)
|
||||||
# ## if file is on filesystem
|
# ## if file is on filesystem
|
||||||
if not path:
|
if not path:
|
||||||
@@ -10422,24 +10434,24 @@ class Rows(object):
|
|||||||
one_result = False
|
one_result = False
|
||||||
if 'one_result' in args:
|
if 'one_result' in args:
|
||||||
one_result = args['one_result']
|
one_result = args['one_result']
|
||||||
|
|
||||||
def build_fields_struct(row, fields, num, groups):
|
def build_fields_struct(row, fields, num, groups):
|
||||||
''' helper function:
|
''' helper function:
|
||||||
'''
|
'''
|
||||||
if num > len(fields)-1:
|
if num > len(fields)-1:
|
||||||
if one_result:
|
if one_result:
|
||||||
return row
|
return row
|
||||||
else:
|
else:
|
||||||
return [row]
|
return [row]
|
||||||
|
|
||||||
key = fields[num]
|
key = fields[num]
|
||||||
value = row[key]
|
value = row[key]
|
||||||
|
|
||||||
if value not in groups:
|
if value not in groups:
|
||||||
groups[value] = build_fields_struct(row, fields, num+1, {})
|
groups[value] = build_fields_struct(row, fields, num+1, {})
|
||||||
else:
|
else:
|
||||||
struct = build_fields_struct(row, fields, num+1, groups[ value ])
|
struct = build_fields_struct(row, fields, num+1, groups[ value ])
|
||||||
|
|
||||||
# still have more grouping to do
|
# still have more grouping to do
|
||||||
if type(struct) == type(dict()):
|
if type(struct) == type(dict()):
|
||||||
groups[value].update()
|
groups[value].update()
|
||||||
@@ -10449,22 +10461,22 @@ class Rows(object):
|
|||||||
# no more grouping, first only on
|
# no more grouping, first only on
|
||||||
else:
|
else:
|
||||||
groups[value] = struct
|
groups[value] = struct
|
||||||
|
|
||||||
return groups
|
return groups
|
||||||
|
|
||||||
if len(fields) == 0:
|
if len(fields) == 0:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
# if select returned no results
|
# if select returned no results
|
||||||
if not self.records:
|
if not self.records:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
grouped_row_group = dict()
|
grouped_row_group = dict()
|
||||||
|
|
||||||
# build the struct
|
# build the struct
|
||||||
for row in self:
|
for row in self:
|
||||||
build_fields_struct(row, fields, 0, grouped_row_group)
|
build_fields_struct(row, fields, 0, grouped_row_group)
|
||||||
|
|
||||||
return grouped_row_group
|
return grouped_row_group
|
||||||
|
|
||||||
def render(self, i=None, fields=None):
|
def render(self, i=None, fields=None):
|
||||||
|
|||||||
+81
-39
@@ -211,12 +211,12 @@ class Request(Storage):
|
|||||||
body.seek(0)
|
body.seek(0)
|
||||||
|
|
||||||
# parse POST variables on POST, PUT, BOTH only in post_vars
|
# parse POST variables on POST, PUT, BOTH only in post_vars
|
||||||
if (body and
|
if (body and not is_json
|
||||||
env.request_method in ('POST', 'PUT', 'DELETE', 'BOTH') and
|
and env.request_method in ('POST', 'PUT', 'DELETE', 'BOTH')):
|
||||||
not is_json):
|
query_string = env.pop('QUERY_STRING',None)
|
||||||
query_string = env.pop('QUERY_STRING') if 'QUERY_STRING' in env else None
|
|
||||||
dpost = cgi.FieldStorage(fp=body, environ=env, keep_blank_values=1)
|
dpost = cgi.FieldStorage(fp=body, environ=env, keep_blank_values=1)
|
||||||
post_vars.update(dpost)
|
if len(dpost):
|
||||||
|
post_vars.update(dpost)
|
||||||
if query_string is not None:
|
if query_string is not None:
|
||||||
env['QUERY_STRING'] = query_string
|
env['QUERY_STRING'] = query_string
|
||||||
# The same detection used by FieldStorage to detect multipart POSTs
|
# The same detection used by FieldStorage to detect multipart POSTs
|
||||||
@@ -232,19 +232,13 @@ class Request(Storage):
|
|||||||
if key is None:
|
if key is None:
|
||||||
continue # not sure why cgi.FieldStorage returns None key
|
continue # not sure why cgi.FieldStorage returns None key
|
||||||
dpk = dpost[key]
|
dpk = dpost[key]
|
||||||
# if an element is not a file replace it with its value else leave it alone
|
# if an element is not a file replace it with
|
||||||
if isinstance(dpk, list):
|
# its value else leave it alone
|
||||||
value = []
|
|
||||||
for _dpk in dpk:
|
pvalue = listify([(_dpk if _dpk.filename else _dpk.value)
|
||||||
if not _dpk.filename:
|
for _dpk in dpk]
|
||||||
value.append(_dpk.value)
|
if isinstance(dpk, list) else
|
||||||
else:
|
(dpk if dpk.filename else dpk.value))
|
||||||
value.append(_dpk)
|
|
||||||
elif not dpk.filename:
|
|
||||||
value = dpk.value
|
|
||||||
else:
|
|
||||||
value = dpk
|
|
||||||
pvalue = listify(value)
|
|
||||||
if len(pvalue):
|
if len(pvalue):
|
||||||
post_vars[key] = (len(pvalue) > 1 and pvalue) or pvalue[0]
|
post_vars[key] = (len(pvalue) > 1 and pvalue) or pvalue[0]
|
||||||
|
|
||||||
@@ -333,13 +327,12 @@ class Request(Storage):
|
|||||||
_self.args[-1], _, self.extension = self.args[-1].rpartition('.')
|
_self.args[-1], _, self.extension = self.args[-1].rpartition('.')
|
||||||
current.response.headers['Content-Type'] = \
|
current.response.headers['Content-Type'] = \
|
||||||
contenttype('.' + _self.extension.lower())
|
contenttype('.' + _self.extension.lower())
|
||||||
if not method in ['GET', 'POST', 'DELETE', 'PUT']:
|
|
||||||
raise HTTP(400, "invalid method")
|
|
||||||
rest_action = _action().get(method, None)
|
rest_action = _action().get(method, None)
|
||||||
if not rest_action:
|
if not (rest_action and method==method.upper()
|
||||||
|
and callable(rest_action)):
|
||||||
raise HTTP(400, "method not supported")
|
raise HTTP(400, "method not supported")
|
||||||
try:
|
try:
|
||||||
return rest_action(*_self.args, **_self.vars)
|
return rest_action(*_self.args, **getattr(_self,'vars',{}))
|
||||||
except TypeError, e:
|
except TypeError, e:
|
||||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||||
if len(traceback.extract_tb(exc_traceback)) == 1:
|
if len(traceback.extract_tb(exc_traceback)) == 1:
|
||||||
@@ -742,10 +735,11 @@ class Session(Storage):
|
|||||||
response.session_cookie_compression_level = compression_level
|
response.session_cookie_compression_level = compression_level
|
||||||
|
|
||||||
# check if there is a session_id in cookies
|
# check if there is a session_id in cookies
|
||||||
try:
|
try:
|
||||||
response.session_id = cookies[response.session_id_name].value
|
old_session_id = cookies[response.session_id_name].value
|
||||||
except KeyError:
|
except KeyError:
|
||||||
response.session_id = None
|
old_session_id = None
|
||||||
|
response.session_id = old_session_id
|
||||||
|
|
||||||
# if we are supposed to use cookie based session data
|
# if we are supposed to use cookie based session data
|
||||||
if cookie_key:
|
if cookie_key:
|
||||||
@@ -865,12 +859,30 @@ class Session(Storage):
|
|||||||
else:
|
else:
|
||||||
response.session_id = None
|
response.session_id = None
|
||||||
response.session_new = True
|
response.session_new = True
|
||||||
|
# if there is no session id yet, we'll need to create a
|
||||||
|
# new session
|
||||||
|
else:
|
||||||
|
response.session_new = True
|
||||||
|
|
||||||
|
# set the cookie now if you know the session_id so user can set
|
||||||
|
# cookie attributes in controllers/models
|
||||||
|
# cookie will be reset later
|
||||||
|
# yet cookie may be reset later
|
||||||
|
# Removed comparison between old and new session ids - should send
|
||||||
|
# the cookie all the time
|
||||||
|
if isinstance(response.session_id,str):
|
||||||
|
response.cookies[response.session_id_name] = response.session_id
|
||||||
|
response.cookies[response.session_id_name]['path'] = '/'
|
||||||
|
if cookie_expires:
|
||||||
|
response.cookies[response.session_id_name]['expires'] = \
|
||||||
|
cookie_expires.strftime(FMT)
|
||||||
|
|
||||||
|
session_pickled = cPickle.dumps(self)
|
||||||
|
response.session_hash = hashlib.md5(session_pickled).hexdigest()
|
||||||
|
|
||||||
if self.flash:
|
if self.flash:
|
||||||
(response.flash, self.flash) = (self.flash, None)
|
(response.flash, self.flash) = (self.flash, None)
|
||||||
|
|
||||||
session_pickled = cPickle.dumps(self)
|
|
||||||
response.session_hash = hashlib.md5(session_pickled).hexdigest()
|
|
||||||
|
|
||||||
def renew(self, clear_session=False):
|
def renew(self, clear_session=False):
|
||||||
|
|
||||||
@@ -929,6 +941,30 @@ class Session(Storage):
|
|||||||
else:
|
else:
|
||||||
response.session_new = True
|
response.session_new = True
|
||||||
|
|
||||||
|
def _fixup_before_save(self):
|
||||||
|
response = current.response
|
||||||
|
rcookies = response.cookies
|
||||||
|
if self._forget and response.session_id_name in rcookies:
|
||||||
|
del rcookies[response.session_id_name]
|
||||||
|
elif self._secure and response.session_id_name in rcookies:
|
||||||
|
rcookies[response.session_id_name]['secure'] = True
|
||||||
|
|
||||||
|
def clear_session_cookies(sefl):
|
||||||
|
request = current.request
|
||||||
|
response = current.response
|
||||||
|
session = response.session
|
||||||
|
masterapp = response.session_masterapp
|
||||||
|
cookies = request.cookies
|
||||||
|
rcookies = response.cookies
|
||||||
|
# if not cookie_key, but session_data_name in cookies
|
||||||
|
# expire session_data_name from cookies
|
||||||
|
if response.session_data_name in cookies:
|
||||||
|
rcookies[response.session_data_name] = 'expired'
|
||||||
|
rcookies[response.session_data_name]['path'] = '/'
|
||||||
|
rcookies[response.session_data_name]['expires'] = PAST
|
||||||
|
if response.session_id_name in rcookies:
|
||||||
|
del rcookies[response.session_id_name]
|
||||||
|
|
||||||
def save_session_id_cookie(self):
|
def save_session_id_cookie(self):
|
||||||
request = current.request
|
request = current.request
|
||||||
response = current.response
|
response = current.response
|
||||||
@@ -946,12 +982,11 @@ class Session(Storage):
|
|||||||
if response.session_id:
|
if response.session_id:
|
||||||
rcookies[response.session_id_name] = response.session_id
|
rcookies[response.session_id_name] = response.session_id
|
||||||
rcookies[response.session_id_name]['path'] = '/'
|
rcookies[response.session_id_name]['path'] = '/'
|
||||||
if isinstance(response.session_cookie_expires,datetime.datetime):
|
expires = response.session_cookie_expires
|
||||||
rcookies[response.session_id_name]['expires'] = \
|
if isinstance(expires,datetime.datetime):
|
||||||
response.session_cookie_expires.strftime(FMT)
|
expires = expires.strftime(FMT)
|
||||||
elif isinstance(response.session_cookie_expires,str):
|
if expires:
|
||||||
rcookies[response.session_id_name]['expires'] = \
|
rcookies[response.session_id_name]['expires'] = expires
|
||||||
response.session_cookie_expires
|
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
Storage.clear(self)
|
Storage.clear(self)
|
||||||
@@ -981,6 +1016,7 @@ class Session(Storage):
|
|||||||
|
|
||||||
def _try_store_in_cookie(self, request, response):
|
def _try_store_in_cookie(self, request, response):
|
||||||
if self._forget or self._unchanged(response):
|
if self._forget or self._unchanged(response):
|
||||||
|
# self.clear_session_cookies()
|
||||||
self.save_session_id_cookie()
|
self.save_session_id_cookie()
|
||||||
return False
|
return False
|
||||||
name = response.session_data_name
|
name = response.session_data_name
|
||||||
@@ -988,13 +1024,15 @@ class Session(Storage):
|
|||||||
value = secure_dumps(dict(self),
|
value = secure_dumps(dict(self),
|
||||||
response.session_cookie_key,
|
response.session_cookie_key,
|
||||||
compression_level=compression_level)
|
compression_level=compression_level)
|
||||||
expires = response.session_cookie_expires
|
|
||||||
rcookies = response.cookies
|
rcookies = response.cookies
|
||||||
rcookies.pop(name, None)
|
rcookies.pop(name, None)
|
||||||
rcookies[name] = value
|
rcookies[name] = value
|
||||||
rcookies[name]['path'] = '/'
|
rcookies[name]['path'] = '/'
|
||||||
|
expires = response.session_cookie_expires
|
||||||
|
if isinstance(expires,datetime.datetime):
|
||||||
|
expires = expires.strftime(FMT)
|
||||||
if expires:
|
if expires:
|
||||||
rcookies[name]['expires'] = expires.strftime(FMT)
|
rcookies[name]['expires'] = expires
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _unchanged(self,response):
|
def _unchanged(self,response):
|
||||||
@@ -1006,13 +1044,15 @@ class Session(Storage):
|
|||||||
def _try_store_in_db(self, request, response):
|
def _try_store_in_db(self, request, response):
|
||||||
# don't save if file-based sessions,
|
# don't save if file-based sessions,
|
||||||
# no session id, or session being forgotten
|
# no session id, or session being forgotten
|
||||||
# or no changes to session
|
# or no changes to session (Unless the session is new)
|
||||||
|
if (not response.session_db_table or
|
||||||
if not response.session_db_table or self._forget or self._unchanged(response):
|
self._forget or
|
||||||
|
(self._unchanged(response) and not response.session_new)):
|
||||||
if (not response.session_db_table and
|
if (not response.session_db_table and
|
||||||
global_settings.db_sessions is not True and
|
global_settings.db_sessions is not True and
|
||||||
response.session_masterapp in global_settings.db_sessions):
|
response.session_masterapp in global_settings.db_sessions):
|
||||||
global_settings.db_sessions.remove(response.session_masterapp)
|
global_settings.db_sessions.remove(response.session_masterapp)
|
||||||
|
# self.clear_session_cookies()
|
||||||
self.save_session_id_cookie()
|
self.save_session_id_cookie()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -1050,7 +1090,9 @@ class Session(Storage):
|
|||||||
|
|
||||||
def _try_store_in_file(self, request, response):
|
def _try_store_in_file(self, request, response):
|
||||||
try:
|
try:
|
||||||
if not response.session_id or self._forget or self._unchanged(response):
|
if (not response.session_id or self._forget
|
||||||
|
or self._unchanged(response)):
|
||||||
|
# self.clear_session_cookies()
|
||||||
self.save_session_id_cookie()
|
self.save_session_id_cookie()
|
||||||
return False
|
return False
|
||||||
if response.session_new or not response.session_file:
|
if response.session_new or not response.session_file:
|
||||||
|
|||||||
+1
-1
@@ -1484,7 +1484,7 @@ class A(DIV):
|
|||||||
if not self['_disable_with']:
|
if not self['_disable_with']:
|
||||||
self['_data-w2p_disable_with'] = 'default'
|
self['_data-w2p_disable_with'] = 'default'
|
||||||
if self['callback'] and not self['_id']:
|
if self['callback'] and not self['_id']:
|
||||||
self['_id'] = web2py_uuid()
|
self['_id'] = web2py_uuid()
|
||||||
if self['delete']:
|
if self['delete']:
|
||||||
self['_data-w2p_remove'] = self['delete']
|
self['_data-w2p_remove'] = self['delete']
|
||||||
if self['target']:
|
if self['target']:
|
||||||
|
|||||||
+2
-2
@@ -67,8 +67,8 @@ regex_param = re.compile(r'{(?P<s>.+?)}')
|
|||||||
|
|
||||||
# pattern for a valid accept_language
|
# pattern for a valid accept_language
|
||||||
regex_language = \
|
regex_language = \
|
||||||
re.compile('([a-z]{2}(?:\-[a-z]{2})?(?:\-[a-z]{2})?)(?:[,;]|$)')
|
re.compile('([a-z]{2,3}(?:\-[a-z]{2})?(?:\-[a-z]{2})?)(?:[,;]|$)')
|
||||||
regex_langfile = re.compile('^[a-z]{2}(-[a-z]{2})?\.py$')
|
regex_langfile = re.compile('^[a-z]{2,3}(-[a-z]{2})?\.py$')
|
||||||
regex_backslash = re.compile(r"\\([\\{}%])")
|
regex_backslash = re.compile(r"\\([\\{}%])")
|
||||||
regex_plural = re.compile('%({.+?})')
|
regex_plural = re.compile('%({.+?})')
|
||||||
regex_plural_dict = re.compile('^{(?P<w>[^()[\]][^()[\]]*?)\((?P<n>[^()\[\]]+)\)}$') # %%{word(varname or number)}
|
regex_plural_dict = re.compile('^{(?P<w>[^()[\]][^()[\]]*?)\((?P<n>[^()\[\]]+)\)}$') # %%{word(varname or number)}
|
||||||
|
|||||||
+12
-14
@@ -453,7 +453,7 @@ def wsgibase(environ, responder):
|
|||||||
serve_controller(request, response, session)
|
serve_controller(request, response, session)
|
||||||
|
|
||||||
except HTTP, http_response:
|
except HTTP, http_response:
|
||||||
|
|
||||||
if static_file:
|
if static_file:
|
||||||
return http_response.to(responder, env=env)
|
return http_response.to(responder, env=env)
|
||||||
|
|
||||||
@@ -470,7 +470,7 @@ def wsgibase(environ, responder):
|
|||||||
# ##################################################
|
# ##################################################
|
||||||
# on success, commit database
|
# on success, commit database
|
||||||
# ##################################################
|
# ##################################################
|
||||||
|
|
||||||
if response.do_not_commit is True:
|
if response.do_not_commit is True:
|
||||||
BaseAdapter.close_all_instances(None)
|
BaseAdapter.close_all_instances(None)
|
||||||
elif response.custom_commit:
|
elif response.custom_commit:
|
||||||
@@ -489,7 +489,7 @@ def wsgibase(environ, responder):
|
|||||||
if request.cid:
|
if request.cid:
|
||||||
http_response.headers.setdefault(
|
http_response.headers.setdefault(
|
||||||
'web2py-component-content', 'replace')
|
'web2py-component-content', 'replace')
|
||||||
|
|
||||||
if request.ajax:
|
if request.ajax:
|
||||||
if response.flash:
|
if response.flash:
|
||||||
http_response.headers['web2py-component-flash'] = \
|
http_response.headers['web2py-component-flash'] = \
|
||||||
@@ -498,17 +498,13 @@ def wsgibase(environ, responder):
|
|||||||
if response.js:
|
if response.js:
|
||||||
http_response.headers['web2py-component-command'] = \
|
http_response.headers['web2py-component-command'] = \
|
||||||
urllib2.quote(response.js.replace('\n',''))
|
urllib2.quote(response.js.replace('\n',''))
|
||||||
|
|
||||||
# ##################################################
|
# ##################################################
|
||||||
# store cookies in headers
|
# store cookies in headers
|
||||||
# ##################################################
|
# ##################################################
|
||||||
|
|
||||||
rcookies = response.cookies
|
session._fixup_before_save()
|
||||||
if session._forget and response.session_id_name in rcookies:
|
http_response.cookies2headers(response.cookies)
|
||||||
del rcookies[response.session_id_name]
|
|
||||||
elif session._secure:
|
|
||||||
rcookies[response.session_id_name]['secure'] = True
|
|
||||||
http_response.cookies2headers(rcookies)
|
|
||||||
|
|
||||||
ticket = None
|
ticket = None
|
||||||
|
|
||||||
@@ -612,7 +608,8 @@ def save_password(password, port):
|
|||||||
|
|
||||||
def appfactory(wsgiapp=wsgibase,
|
def appfactory(wsgiapp=wsgibase,
|
||||||
logfilename='httpserver.log',
|
logfilename='httpserver.log',
|
||||||
profiler_dir=None):
|
profiler_dir=None,
|
||||||
|
profilerfilename=None):
|
||||||
"""
|
"""
|
||||||
generates a wsgi application that does logging and profiling and calls
|
generates a wsgi application that does logging and profiling and calls
|
||||||
wsgibase
|
wsgibase
|
||||||
@@ -623,7 +620,8 @@ def appfactory(wsgiapp=wsgibase,
|
|||||||
[, profilerfilename='profiler.log']]])
|
[, profilerfilename='profiler.log']]])
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if profilerfilename is not None:
|
||||||
|
raise BaseException("Deprecated API")
|
||||||
if profiler_dir:
|
if profiler_dir:
|
||||||
profiler_dir = abspath(profiler_dir)
|
profiler_dir = abspath(profiler_dir)
|
||||||
logger.warn('profiler is on. will use dir %s', profiler_dir)
|
logger.warn('profiler is on. will use dir %s', profiler_dir)
|
||||||
@@ -631,14 +629,14 @@ def appfactory(wsgiapp=wsgibase,
|
|||||||
try:
|
try:
|
||||||
os.makedirs(profiler_dir)
|
os.makedirs(profiler_dir)
|
||||||
except:
|
except:
|
||||||
raise BaseException, "Can't create dir %s" % profiler_dir
|
raise BaseException("Can't create dir %s" % profiler_dir)
|
||||||
filepath = pjoin(profiler_dir, 'wtest')
|
filepath = pjoin(profiler_dir, 'wtest')
|
||||||
try:
|
try:
|
||||||
filehandle = open( filepath, 'w' )
|
filehandle = open( filepath, 'w' )
|
||||||
filehandle.close()
|
filehandle.close()
|
||||||
os.unlink(filepath)
|
os.unlink(filepath)
|
||||||
except IOError:
|
except IOError:
|
||||||
raise BaseException, "Unable to write to dir %s" % profiler_dir
|
raise BaseException("Unable to write to dir %s" % profiler_dir)
|
||||||
|
|
||||||
def app_with_logging(environ, responder):
|
def app_with_logging(environ, responder):
|
||||||
"""
|
"""
|
||||||
|
|||||||
+1
-1
@@ -48,7 +48,7 @@ class TicketStorage(Storage):
|
|||||||
self._store_on_disk(request, ticket_id, ticket_data)
|
self._store_on_disk(request, ticket_id, ticket_data)
|
||||||
|
|
||||||
def _store_in_db(self, request, ticket_id, ticket_data):
|
def _store_in_db(self, request, ticket_id, ticket_data):
|
||||||
self.db._adapter.reconnect()
|
self.db._adapter.reconnect()
|
||||||
try:
|
try:
|
||||||
table = self._get_table(self.db, self.tablename, request.application)
|
table = self._get_table(self.db, self.tablename, request.application)
|
||||||
id = table.insert(ticket_id=ticket_id,
|
id = table.insert(ticket_id=ticket_id,
|
||||||
|
|||||||
+6
-6
@@ -244,15 +244,15 @@ def try_rewrite_on_error(http_response, request, environ, ticket=None):
|
|||||||
url = path_info + '?' + query_string
|
url = path_info + '?' + query_string
|
||||||
message = 'You are being redirected <a href="%s">here</a>'
|
message = 'You are being redirected <a href="%s">here</a>'
|
||||||
return HTTP(303, message % url, Location=url), environ
|
return HTTP(303, message % url, Location=url), environ
|
||||||
elif not environ.get('__ROUTES_ONERROR__', False):
|
elif not environ.get('__ROUTES_ONERROR__', False):
|
||||||
# wsgibase will be called recursively with
|
# wsgibase will be called recursively with
|
||||||
# the routes_onerror path.
|
# the routes_onerror path.
|
||||||
environ['__ROUTES_ONERROR__'] = True # limit recursion
|
environ['__ROUTES_ONERROR__'] = True # limit recursion
|
||||||
path_info = '/' + path_info.lstrip('/')
|
path_info = '/' + path_info.lstrip('/')
|
||||||
environ['PATH_INFO'] = path_info
|
environ['PATH_INFO'] = path_info
|
||||||
environ['QUERY_STRING'] = query_string
|
environ['QUERY_STRING'] = query_string
|
||||||
environ['WEB2PY_STATUS_CODE'] = status
|
environ['WEB2PY_STATUS_CODE'] = status
|
||||||
return None, environ
|
return None, environ
|
||||||
# do nothing!
|
# do nothing!
|
||||||
return http_response, environ
|
return http_response, environ
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -137,12 +137,12 @@ def env(
|
|||||||
|
|
||||||
for k, v in extra_request.items():
|
for k, v in extra_request.items():
|
||||||
request[k] = v
|
request[k] = v
|
||||||
|
|
||||||
path_info = '/%s/%s/%s' % (a, c, f)
|
path_info = '/%s/%s/%s' % (a, c, f)
|
||||||
if request.args:
|
if request.args:
|
||||||
path_info = '%s/%s' % (path_info, '/'.join(request.args))
|
path_info = '%s/%s' % (path_info, '/'.join(request.args))
|
||||||
if request.vars:
|
if request.vars:
|
||||||
vars = ['%s=%s' % (k,v) if v else '%s' % k
|
vars = ['%s=%s' % (k,v) if v else '%s' % k
|
||||||
for (k,v) in request.vars.iteritems()]
|
for (k,v) in request.vars.iteritems()]
|
||||||
path_info = '%s?%s' % (path_info, '&'.join(vars))
|
path_info = '%s?%s' % (path_info, '&'.join(vars))
|
||||||
request.env.path_info = path_info
|
request.env.path_info = path_info
|
||||||
@@ -238,7 +238,7 @@ def run(
|
|||||||
pyfile = os.path.join('applications', a, 'controllers', c + '.py')
|
pyfile = os.path.join('applications', a, 'controllers', c + '.py')
|
||||||
pycfile = os.path.join('applications', a, 'compiled',
|
pycfile = os.path.join('applications', a, 'compiled',
|
||||||
"controllers_%s_%s.pyc" % (c, f))
|
"controllers_%s_%s.pyc" % (c, f))
|
||||||
if ((cronjob and os.path.isfile(pycfile))
|
if ((cronjob and os.path.isfile(pycfile))
|
||||||
or not os.path.isfile(pyfile)):
|
or not os.path.isfile(pyfile)):
|
||||||
exec read_pyc(pycfile) in _env
|
exec read_pyc(pycfile) in _env
|
||||||
elif os.path.isfile(pyfile):
|
elif os.path.isfile(pyfile):
|
||||||
@@ -425,7 +425,7 @@ def execute_from_command_line(argv=None):
|
|||||||
parser = optparse.OptionParser(usage=get_usage())
|
parser = optparse.OptionParser(usage=get_usage())
|
||||||
|
|
||||||
parser.add_option('-S', '--shell', dest='shell', metavar='APPNAME',
|
parser.add_option('-S', '--shell', dest='shell', metavar='APPNAME',
|
||||||
help='run web2py in interactive shell ' +
|
help='run web2py in interactive shell ' +
|
||||||
'or IPython(if installed) with specified appname')
|
'or IPython(if installed) with specified appname')
|
||||||
msg = 'run web2py in interactive shell or bpython (if installed) with'
|
msg = 'run web2py in interactive shell or bpython (if installed) with'
|
||||||
msg += ' specified appname (if app does not exist it will be created).'
|
msg += ' specified appname (if app does not exist it will be created).'
|
||||||
|
|||||||
+1
-2
@@ -292,6 +292,7 @@ class ListWidget(StringWidget):
|
|||||||
_class = 'string'
|
_class = 'string'
|
||||||
requires = field.requires if isinstance(
|
requires = field.requires if isinstance(
|
||||||
field.requires, (IS_NOT_EMPTY, IS_LIST_OF)) else None
|
field.requires, (IS_NOT_EMPTY, IS_LIST_OF)) else None
|
||||||
|
if isinstance(value,str): value = [value]
|
||||||
nvalue = value or ['']
|
nvalue = value or ['']
|
||||||
items = [LI(INPUT(_id=_id, _class=_class, _name=_name,
|
items = [LI(INPUT(_id=_id, _class=_class, _name=_name,
|
||||||
value=v, hideerror=k < len(nvalue) - 1,
|
value=v, hideerror=k < len(nvalue) - 1,
|
||||||
@@ -1356,8 +1357,6 @@ class SQLFORM(FORM):
|
|||||||
value = self.record[fieldname]
|
value = self.record[fieldname]
|
||||||
else:
|
else:
|
||||||
value = self.table[fieldname].default
|
value = self.table[fieldname].default
|
||||||
if field.type.startswith('list:') and isinstance(value, str):
|
|
||||||
value = [value]
|
|
||||||
row_id = '%s_%s%s' % (
|
row_id = '%s_%s%s' % (
|
||||||
self.table, fieldname, SQLFORM.ID_ROW_SUFFIX)
|
self.table, fieldname, SQLFORM.ID_ROW_SUFFIX)
|
||||||
widget = field.widget(field, value)
|
widget = field.widget(field, value)
|
||||||
|
|||||||
+1
-1
@@ -434,7 +434,7 @@ class TemplateParser(object):
|
|||||||
# Get the filename; filename looks like ``"template.html"``.
|
# Get the filename; filename looks like ``"template.html"``.
|
||||||
# We need to eval to remove the quotes and get the string type.
|
# We need to eval to remove the quotes and get the string type.
|
||||||
filename = eval(filename, context)
|
filename = eval(filename, context)
|
||||||
|
|
||||||
# Allow empty filename for conditional extend and include directives.
|
# Allow empty filename for conditional extend and include directives.
|
||||||
if not filename:
|
if not filename:
|
||||||
return ''
|
return ''
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class TestRoutes(unittest.TestCase):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
"""
|
"""
|
||||||
# outgoing
|
# outgoing
|
||||||
self.assertEqual(filter_url('http://domain.com/init/default/index',
|
self.assertEqual(filter_url('http://domain.com/init/default/index',
|
||||||
out=True), '/init/default/index')
|
out=True), '/init/default/index')
|
||||||
self.assertEqual(filter_url('http://domain.com/init/default/index/arg1', out=True), '/init/default/index/arg1')
|
self.assertEqual(filter_url('http://domain.com/init/default/index/arg1', out=True), '/init/default/index/arg1')
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ class TestWeb(LiveTest):
|
|||||||
|
|
||||||
# check registration and login were successful
|
# check registration and login were successful
|
||||||
client.get('index')
|
client.get('index')
|
||||||
|
|
||||||
# COMMENTED BECAUSE FAILS BUT WHY?
|
# COMMENTED BECAUSE FAILS BUT WHY?
|
||||||
self.assertTrue('Welcome Homer' in client.text)
|
self.assertTrue('Welcome Homer' in client.text)
|
||||||
|
|
||||||
|
|||||||
+14
-14
@@ -921,7 +921,7 @@ class Auth(object):
|
|||||||
username_case_sensitive=True,
|
username_case_sensitive=True,
|
||||||
update_fields = ['email'],
|
update_fields = ['email'],
|
||||||
ondelete="CASCADE",
|
ondelete="CASCADE",
|
||||||
client_side = True,
|
client_side = True,
|
||||||
renew_session_onlogin=True,
|
renew_session_onlogin=True,
|
||||||
renew_session_onlogout=True,
|
renew_session_onlogout=True,
|
||||||
keep_session_onlogin=True,
|
keep_session_onlogin=True,
|
||||||
@@ -1509,7 +1509,7 @@ class Auth(object):
|
|||||||
self.bar = SPAN(s1, Anr(items[0]['name'],
|
self.bar = SPAN(s1, Anr(items[0]['name'],
|
||||||
_href=items[0]['href']), s3,
|
_href=items[0]['href']), s3,
|
||||||
_class='auth_navbar')
|
_class='auth_navbar')
|
||||||
for item in items:
|
for item in items[1:]:
|
||||||
self.bar.insert(-1, s2)
|
self.bar.insert(-1, s2)
|
||||||
self.bar.insert(-1, Anr(item['name'], _href=item['href']))
|
self.bar.insert(-1, Anr(item['name'], _href=item['href']))
|
||||||
|
|
||||||
@@ -1560,8 +1560,8 @@ class Auth(object):
|
|||||||
current_record.replace('_',' ').title())
|
current_record.replace('_',' ').title())
|
||||||
for table in tables:
|
for table in tables:
|
||||||
fieldnames = table.fields()
|
fieldnames = table.fields()
|
||||||
if ('id' in fieldnames and
|
if ('id' in fieldnames and
|
||||||
'modified_on' in fieldnames and
|
'modified_on' in fieldnames and
|
||||||
not current_record in fieldnames):
|
not current_record in fieldnames):
|
||||||
table._enable_record_versioning(
|
table._enable_record_versioning(
|
||||||
archive_db=archive_db,
|
archive_db=archive_db,
|
||||||
@@ -2167,17 +2167,17 @@ class Auth(object):
|
|||||||
elif 'username' in table_user.fields:
|
elif 'username' in table_user.fields:
|
||||||
username = 'username'
|
username = 'username'
|
||||||
else:
|
else:
|
||||||
username = 'email'
|
username = 'email'
|
||||||
settings = self.settings
|
settings = self.settings
|
||||||
if 'username' in table_user.fields or \
|
if 'username' in table_user.fields or \
|
||||||
not settings.login_email_validate:
|
not settings.login_email_validate:
|
||||||
tmpvalidator = IS_NOT_EMPTY(error_message=self.messages.is_empty)
|
tmpvalidator = IS_NOT_EMPTY(error_message=self.messages.is_empty)
|
||||||
if not settings.username_case_sensitive:
|
if not settings.username_case_sensitive:
|
||||||
tmpvalidator = [IS_LOWER(), tmpvalidator]
|
tmpvalidator = [IS_LOWER(), tmpvalidator]
|
||||||
else:
|
else:
|
||||||
tmpvalidator = IS_EMAIL(error_message=self.messages.invalid_email)
|
tmpvalidator = IS_EMAIL(error_message=self.messages.invalid_email)
|
||||||
if not settings.email_case_sensitive:
|
if not settings.email_case_sensitive:
|
||||||
tmpvalidator = [IS_LOWER(), tmpvalidator]
|
tmpvalidator = [IS_LOWER(), tmpvalidator]
|
||||||
old_requires = table_user[username].requires
|
old_requires = table_user[username].requires
|
||||||
table_user[username].requires = tmpvalidator
|
table_user[username].requires = tmpvalidator
|
||||||
|
|
||||||
@@ -2191,7 +2191,7 @@ class Auth(object):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
### use session for federated login
|
### use session for federated login
|
||||||
snext = self.get_vars_next()
|
snext = self.get_vars_next()
|
||||||
if snext:
|
if snext:
|
||||||
session._auth_next = snext
|
session._auth_next = snext
|
||||||
@@ -2414,9 +2414,9 @@ class Auth(object):
|
|||||||
next = cas.logout_url(next)
|
next = cas.logout_url(next)
|
||||||
|
|
||||||
current.session.auth = None
|
current.session.auth = None
|
||||||
current.session.flash = self.messages.logged_out
|
|
||||||
if self.settings.renew_session_onlogout:
|
if self.settings.renew_session_onlogout:
|
||||||
current.session.renew(clear_session=not self.settings.keep_session_onlogout)
|
current.session.renew(clear_session=not self.settings.keep_session_onlogout)
|
||||||
|
current.session.flash = self.messages.logged_out
|
||||||
if not next is None:
|
if not next is None:
|
||||||
redirect(next)
|
redirect(next)
|
||||||
|
|
||||||
@@ -2515,9 +2515,9 @@ class Auth(object):
|
|||||||
captcha.comment, self.settings.formstyle, 'captcha__row')
|
captcha.comment, self.settings.formstyle, 'captcha__row')
|
||||||
|
|
||||||
table_user.registration_key.default = key = web2py_uuid()
|
table_user.registration_key.default = key = web2py_uuid()
|
||||||
if form.accepts(request, session if self.csrf_prevention else None,
|
if form.accepts(request, session if self.csrf_prevention else None,
|
||||||
formname='register',
|
formname='register',
|
||||||
onvalidation=onvalidation,
|
onvalidation=onvalidation,
|
||||||
hideerror=self.settings.hideerror):
|
hideerror=self.settings.hideerror):
|
||||||
description = self.messages.group_description % form.vars
|
description = self.messages.group_description % form.vars
|
||||||
if self.settings.create_user_groups:
|
if self.settings.create_user_groups:
|
||||||
@@ -5858,7 +5858,7 @@ class Wiki(object):
|
|||||||
class Config(object):
|
class Config(object):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
filename,
|
filename,
|
||||||
section,
|
section,
|
||||||
default_values={}
|
default_values={}
|
||||||
):
|
):
|
||||||
@@ -5879,11 +5879,11 @@ class Config(object):
|
|||||||
def save(self, options):
|
def save(self, options):
|
||||||
for option, value in options:
|
for option, value in options:
|
||||||
self.config.set(self.section, option, value)
|
self.config.set(self.section, option, value)
|
||||||
try:
|
try:
|
||||||
self.config.write(open(self.filename, 'w'))
|
self.config.write(open(self.filename, 'w'))
|
||||||
result = True
|
result = True
|
||||||
except:
|
except:
|
||||||
current.session['settings_%s' % self.section] = dict(self.config.items(self.section))
|
current.session['settings_%s' % self.section] = dict(self.config.items(self.section))
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -310,7 +310,7 @@ def is_loopback_ip_address(ip=None, addrinfo=None):
|
|||||||
if not isinstance(ip, basestring):
|
if not isinstance(ip, basestring):
|
||||||
return False
|
return False
|
||||||
# IPv4 or IPv6-embedded IPv4 or IPv4-compatible IPv6
|
# IPv4 or IPv6-embedded IPv4 or IPv4-compatible IPv6
|
||||||
if ip.count('.') == 3:
|
if ip.count('.') == 3:
|
||||||
return ip.lower().startswith(('127', '::127', '0:0:0:0:0:0:127',
|
return ip.lower().startswith(('127', '::127', '0:0:0:0:0:0:127',
|
||||||
'::ffff:127', '0:0:0:0:0:ffff:127'))
|
'::ffff:127', '0:0:0:0:0:ffff:127'))
|
||||||
return ip == '::1' or ip == '0:0:0:0:0:0:0:1' # IPv6 loopback
|
return ip == '::1' or ip == '0:0:0:0:0:0:0:1' # IPv6 loopback
|
||||||
@@ -322,7 +322,7 @@ def getipaddrinfo(host):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return [addrinfo for addrinfo in socket.getaddrinfo(host, None)
|
return [addrinfo for addrinfo in socket.getaddrinfo(host, None)
|
||||||
if (addrinfo[0] == socket.AF_INET or
|
if (addrinfo[0] == socket.AF_INET or
|
||||||
addrinfo[0] == socket.AF_INET6)
|
addrinfo[0] == socket.AF_INET6)
|
||||||
and isinstance(addrinfo[4][0], basestring)]
|
and isinstance(addrinfo[4][0], basestring)]
|
||||||
except socket.error:
|
except socket.error:
|
||||||
|
|||||||
+39
-2
@@ -42,6 +42,7 @@ __all__ = [
|
|||||||
'IS_DATETIME',
|
'IS_DATETIME',
|
||||||
'IS_DECIMAL_IN_RANGE',
|
'IS_DECIMAL_IN_RANGE',
|
||||||
'IS_EMAIL',
|
'IS_EMAIL',
|
||||||
|
'IS_LIST_OF_EMAILS',
|
||||||
'IS_EMPTY_OR',
|
'IS_EMPTY_OR',
|
||||||
'IS_EXPR',
|
'IS_EXPR',
|
||||||
'IS_FLOAT_IN_RANGE',
|
'IS_FLOAT_IN_RANGE',
|
||||||
@@ -1178,6 +1179,39 @@ class IS_EMAIL(Validator):
|
|||||||
return (value, None)
|
return (value, None)
|
||||||
return (value, translate(self.error_message))
|
return (value, translate(self.error_message))
|
||||||
|
|
||||||
|
class IS_LIST_OF_EMAILS(object):
|
||||||
|
"""
|
||||||
|
use as follows:
|
||||||
|
Field('emails','list:string',
|
||||||
|
widget=SQLFORM.widgets.text.widget,
|
||||||
|
requires=IS_LIST_OF_EMAILS(),
|
||||||
|
represent=lambda v,r: \
|
||||||
|
SPAN(*[A(x,_href='mailto:'+x) for x in (v or [])])
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
split_emails = re.compile('[^,;\s]+')
|
||||||
|
def __init__(self, error_message = 'Invalid emails: %s'):
|
||||||
|
self.error_message = error_message
|
||||||
|
|
||||||
|
def __call__(self, value):
|
||||||
|
bad_emails = []
|
||||||
|
emails = []
|
||||||
|
f = IS_EMAIL()
|
||||||
|
for email in self.split_emails.findall(value):
|
||||||
|
if not email in emails:
|
||||||
|
emails.append(email)
|
||||||
|
error = f(email)[1]
|
||||||
|
if error and not email in bad_emails:
|
||||||
|
bad_emails.append(email)
|
||||||
|
if not bad_emails:
|
||||||
|
return (value, None)
|
||||||
|
else:
|
||||||
|
return (value,
|
||||||
|
translate(self.error_message) % ', '.join(bad_emails))
|
||||||
|
|
||||||
|
def formatter(self,value,row=None):
|
||||||
|
return ', '.join(value or [])
|
||||||
|
|
||||||
|
|
||||||
# URL scheme source:
|
# URL scheme source:
|
||||||
# <http://en.wikipedia.org/wiki/URI_scheme> obtained on 2008-Nov-10
|
# <http://en.wikipedia.org/wiki/URI_scheme> obtained on 2008-Nov-10
|
||||||
@@ -2890,7 +2924,8 @@ class CRYPT(object):
|
|||||||
key=None,
|
key=None,
|
||||||
digest_alg='pbkdf2(1000,20,sha512)',
|
digest_alg='pbkdf2(1000,20,sha512)',
|
||||||
min_length=0,
|
min_length=0,
|
||||||
error_message='too short', salt=True):
|
error_message='too short', salt=True,
|
||||||
|
max_length=1024):
|
||||||
"""
|
"""
|
||||||
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.
|
||||||
@@ -2901,10 +2936,12 @@ class CRYPT(object):
|
|||||||
self.key = key
|
self.key = key
|
||||||
self.digest_alg = digest_alg
|
self.digest_alg = digest_alg
|
||||||
self.min_length = min_length
|
self.min_length = min_length
|
||||||
|
self.max_length = max_length
|
||||||
self.error_message = error_message
|
self.error_message = error_message
|
||||||
self.salt = salt
|
self.salt = salt
|
||||||
|
|
||||||
def __call__(self, value):
|
def __call__(self, value):
|
||||||
|
value = value and value[:self.max_length]
|
||||||
if len(value) < self.min_length:
|
if len(value) < self.min_length:
|
||||||
return ('', translate(self.error_message))
|
return ('', translate(self.error_message))
|
||||||
return (LazyCrypt(self, value), None)
|
return (LazyCrypt(self, value), None)
|
||||||
@@ -3495,7 +3532,7 @@ class IS_IPV6(Validator):
|
|||||||
('2001::8ffa:fe22:b3af', None)
|
('2001::8ffa:fe22:b3af', None)
|
||||||
>>> IS_IPV6(subnets='invalidsubnet')('2001::8ffa:fe22:b3af')
|
>>> IS_IPV6(subnets='invalidsubnet')('2001::8ffa:fe22:b3af')
|
||||||
('2001::8ffa:fe22:b3af', 'invalid subnet provided')
|
('2001::8ffa:fe22:b3af', 'invalid subnet provided')
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|||||||
+2
-2
@@ -176,7 +176,7 @@ class Web2pyCronService(Web2pyService):
|
|||||||
from gluon.settings import global_settings
|
from gluon.settings import global_settings
|
||||||
from gluon.fileutils import abspath
|
from gluon.fileutils import abspath
|
||||||
from os.path import exists, join
|
from os.path import exists, join
|
||||||
|
|
||||||
self.log('web2py Cron service starting')
|
self.log('web2py Cron service starting')
|
||||||
if not self.chdir():
|
if not self.chdir():
|
||||||
return
|
return
|
||||||
@@ -186,7 +186,7 @@ class Web2pyCronService(Web2pyService):
|
|||||||
opt_mod = self._exe_args_
|
opt_mod = self._exe_args_
|
||||||
options = __import__(opt_mod, [], [], '')
|
options = __import__(opt_mod, [], [], '')
|
||||||
logpath = abspath(join(options.folder, "logging.conf"))
|
logpath = abspath(join(options.folder, "logging.conf"))
|
||||||
|
|
||||||
if exists(logpath):
|
if exists(logpath):
|
||||||
logging.config.fileConfig(logpath)
|
logging.config.fileConfig(logpath)
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user