Merge ssh://github.com/web2py/web2py
This commit is contained in:
@@ -1 +1 @@
|
|||||||
Version 2.6.0-development+timestamp.2013.07.17.07.36.50
|
Version 2.6.0-development+timestamp.2013.07.17.17.18.40
|
||||||
|
|||||||
@@ -327,6 +327,89 @@ font-style: italic;
|
|||||||
color: #ccc;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*=============================================================
|
||||||
|
EDIT PAGE SLIDING FILES MENU
|
||||||
|
==============================================================*/
|
||||||
|
@media (max-width: 979px) {
|
||||||
|
body.edit div#header {position:relative; z-index: 1030 !important;}
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor_area, #edit_placeholder {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editor_area {
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#files {
|
||||||
|
width: auto;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
position: fixed;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
z-index: 1029;
|
||||||
|
border-right: 3px solid #000;
|
||||||
|
/* animation (it doesn't work in IE<10) */
|
||||||
|
-moz-transition: all 0.4s;
|
||||||
|
-webkit-transition: all 0.4s;
|
||||||
|
-o-transition: all 0.4s;
|
||||||
|
transition: all 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#files:hover, #files:focus {
|
||||||
|
left: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#files, .files-toggle {
|
||||||
|
background: #1b1b1b;
|
||||||
|
opacity: 0.98;
|
||||||
|
}
|
||||||
|
|
||||||
|
.files-toggle {
|
||||||
|
width: 18px;
|
||||||
|
height: 86px;
|
||||||
|
border-radius: 0px 4px 4px 0px;
|
||||||
|
color: #999;
|
||||||
|
position: absolute;
|
||||||
|
top: 60px;
|
||||||
|
right: -18px;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
width: 18px;
|
||||||
|
height: 70px;
|
||||||
|
background: url(../images/files_toggle.png) no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.files-menu {
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filelist {
|
||||||
|
position: relative;
|
||||||
|
top: 60px;
|
||||||
|
padding-bottom: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filelist li {
|
||||||
|
padding-right: 8px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#filelist li>a {
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
/*=============================================================
|
/*=============================================================
|
||||||
MEDIA QUERIES
|
MEDIA QUERIES
|
||||||
==============================================================*/
|
==============================================================*/
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -121,7 +121,7 @@ jQuery(document).on('click', 'a.font_button', function (e) {
|
|||||||
case 'decr': new_incr = -2; break;
|
case 'decr': new_incr = -2; break;
|
||||||
case 'default': new_incr = 0; break;
|
case 'default': new_incr = 0; break;
|
||||||
}
|
}
|
||||||
jQuery('textarea[name="data"]') .each(function(id, ta) {
|
jQuery('textarea[name="data"]').each(function(id, ta) {
|
||||||
editor = jQuery(ta).data('editor');
|
editor = jQuery(ta).data('editor');
|
||||||
set_font(editor, new_incr);
|
set_font(editor, new_incr);
|
||||||
});
|
});
|
||||||
@@ -163,9 +163,6 @@ jQuery(document).on('click', 'a.font_button', function (e) {
|
|||||||
|
|
||||||
<div class='row-fluid'>
|
<div class='row-fluid'>
|
||||||
<div class="right controls btn-toolbar pull-right">
|
<div class="right controls btn-toolbar pull-right">
|
||||||
<div class="btn-group">
|
|
||||||
<a class="button btn" onclick="jQuery('#files').toggle(); return false" href="#">Files toggle</a>
|
|
||||||
</div>
|
|
||||||
<div class="dropdown btn-group pull-left">
|
<div class="dropdown btn-group pull-left">
|
||||||
<a class="dropdown-toggle button btn" data-target="themes" data-toggle="dropdown" href="#" >Theme: <span id="themeName" style="color: #E8953C">Web2py</span> <span class="caret"></span></a>
|
<a class="dropdown-toggle button btn" data-target="themes" data-toggle="dropdown" href="#" >Theme: <span id="themeName" style="color: #E8953C">Web2py</span> <span class="caret"></span></a>
|
||||||
<ul class="dropdown-menu" role="menu" id="themes">
|
<ul class="dropdown-menu" role="menu" id="themes">
|
||||||
@@ -189,40 +186,51 @@ jQuery(document).on('click', 'a.font_button', function (e) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="editor_area" class="row-fluid">
|
<div id="editor_area" class="row-fluid">
|
||||||
<div id="files">
|
<div id="files">
|
||||||
<ul class="nav nav-list span2 well" rel="pagebookmark" id="filelist">
|
<div class="files-toggle"><span class="arrow"></span></div>
|
||||||
<li><input type="text" placeholder="{{=T('Rapid Search')}}" class="input-block-level typeahead-tw search-query"></li>
|
<div class="files-menu">
|
||||||
{{dirs=[{'name':'models', 'reg':'.*\.py$'},
|
<ul class="nav nav-list" rel="pagebookmark" id="filelist">
|
||||||
{'name':'controllers', 'reg':'.*\.py$'},
|
<li><input type="text" placeholder="{{=T('Rapid Search')}}" class="input-block-level typeahead-tw search-query"></li>
|
||||||
{'name':'views', 'reg':'[\w/\-]+(\.\w+)+$'},
|
{{dirs=[{'name':'models', 'reg':'.*\.py$'},
|
||||||
{'name':'modules', 'reg':'.*\.py$'},
|
{'name':'controllers', 'reg':'.*\.py$'},
|
||||||
{'name':'private', 'reg': '[^\.#].*'}]}}
|
{'name':'views', 'reg':'[\w/\-]+(\.\w+)+$'},
|
||||||
{{auto_complete_list=[]}}
|
{'name':'modules', 'reg':'.*\.py$'},
|
||||||
{{for dir in dirs:}}
|
{'name':'private', 'reg': '[^\.#].*'}]}}
|
||||||
<li class="nav-header component" onclick="collapse('{{="%s_files" % dir['name']}}');">{{=dir['name']}}</li>
|
{{auto_complete_list=[]}}
|
||||||
<li id="{{="%s_files" % dir['name']}}">
|
{{for dir in dirs:}}
|
||||||
<ul class="nav nav-list small-font">
|
<li class="nav-header component" onclick="collapse('{{="%s_files" % dir['name']}}');">{{=dir['name']}}</li>
|
||||||
{{for f in listfiles(app, dir['name'], regexp=dir['reg'] ):}}
|
<li id="{{="%s_files" % dir['name']}}">
|
||||||
{{id="%s__" % dir['name'] + f.replace('.','__')}}
|
<ul class="nav nav-list small-font">
|
||||||
{{current_file = request.args(len(request.args) - 1)}}
|
{{for f in listfiles(app, dir['name'], regexp=dir['reg'] ):}}
|
||||||
<li class="{{#='active' if current_file==f else ''}}" style="overflow:hidden">
|
{{id="%s__" % dir['name'] + f.replace('.','__')}}
|
||||||
{{a_tag=editfile(dir['name'], f, dict(id=id))}}
|
{{current_file = request.args(len(request.args) - 1)}}
|
||||||
{{=a_tag}}
|
<li class="{{#='active' if current_file==f else ''}}" style="overflow:hidden">
|
||||||
{{auto_complete_list.append({'value':f, 'tokens':f.split('/'), 'a_tag':a_tag})}}
|
{{a_tag=editfile(dir['name'], f, dict(id=id))}}
|
||||||
</li>
|
{{=a_tag}}
|
||||||
{{pass}}
|
{{auto_complete_list.append({'value':f, 'tokens':f.split('/'), 'a_tag':a_tag})}}
|
||||||
</ul>
|
</li>
|
||||||
</li>
|
{{pass}}
|
||||||
{{pass}}
|
</ul>
|
||||||
</ul>
|
</li>
|
||||||
|
{{pass}}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="span10" id="edit_placeholder">
|
<div class="span12" id="edit_placeholder">
|
||||||
<ul class="nav nav-tabs " id="filesTab">
|
<ul class="nav nav-tabs " id="filesTab">
|
||||||
</ul>
|
</ul>
|
||||||
<div id="myTabContent" class="tab-content">
|
<div id="myTabContent" class="tab-content">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<script>
|
||||||
|
jQuery(document).ready(function() {
|
||||||
|
var filesMenu = jQuery('#files');
|
||||||
|
var ow = filesMenu.outerWidth();
|
||||||
|
filesMenu.width(ow);
|
||||||
|
setTimeout( function(){jQuery('#files').css('left', '-'+ow+'px');}, 1000);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
<!-- Typeahead scripts here so the page load faster -->
|
<!-- Typeahead scripts here so the page load faster -->
|
||||||
<script src="{{=URL('static/js', 'typeahead.min.js')}}"></script>
|
<script src="{{=URL('static/js', 'typeahead.min.js')}}"></script>
|
||||||
<script src="{{=URL('static/js', 'hogan-2.0.0.js')}}"></script>
|
<script src="{{=URL('static/js', 'hogan-2.0.0.js')}}"></script>
|
||||||
|
|||||||
+6
-14
@@ -40,19 +40,12 @@
|
|||||||
:copyright: (c) Copyright 2011 by Armin Ronacher.
|
:copyright: (c) Copyright 2011 by Armin Ronacher.
|
||||||
:license: BSD, see LICENSE for more details.
|
:license: BSD, see LICENSE for more details.
|
||||||
"""
|
"""
|
||||||
#import hmac
|
import hmac
|
||||||
#import hashlib
|
|
||||||
try:
|
try:
|
||||||
# Use PyCrypto (if available).
|
from hashlib import sha1
|
||||||
from Crypto.Hash import HMAC as hmac, SHA as sha1
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# PyCrypto not available. Use the Python standard library.
|
# hashlib not available. Use the old sha module.
|
||||||
import hmac
|
import sha as sha1
|
||||||
try:
|
|
||||||
from hashlib import sha1
|
|
||||||
except ImportError:
|
|
||||||
# hashlib not available. Use the old sha module.
|
|
||||||
import sha as sha1
|
|
||||||
|
|
||||||
from struct import Struct
|
from struct import Struct
|
||||||
from operator import xor
|
from operator import xor
|
||||||
@@ -121,9 +114,8 @@ def test():
|
|||||||
check('pass\x00word', 'sa\x00lt', 4096, 16,
|
check('pass\x00word', 'sa\x00lt', 4096, 16,
|
||||||
'56fa6aa75548099dcc37d7f03425e0c3')
|
'56fa6aa75548099dcc37d7f03425e0c3')
|
||||||
# This one is from the RFC but it just takes for ages
|
# This one is from the RFC but it just takes for ages
|
||||||
##check('password', 'salt', 16777216, 20,
|
check('password', 'salt', 16777216, 20,
|
||||||
## 'eefe3d61cd4da4e4e9945b3d6ba2158c2634e984')
|
'eefe3d61cd4da4e4e9945b3d6ba2158c2634e984')
|
||||||
|
|
||||||
# From Crypt-PBKDF2
|
# From Crypt-PBKDF2
|
||||||
check('password', 'ATHENA.MIT.EDUraeburn', 1, 16,
|
check('password', 'ATHENA.MIT.EDUraeburn', 1, 16,
|
||||||
'cdedb5281bb2f801565a1122b2563515')
|
'cdedb5281bb2f801565a1122b2563515')
|
||||||
|
|||||||
@@ -143,7 +143,6 @@ class MockTable(object):
|
|||||||
release_lock(self.r_server, key_lock, newid)
|
release_lock(self.r_server, key_lock, newid)
|
||||||
return newid
|
return newid
|
||||||
|
|
||||||
|
|
||||||
class MockQuery(object):
|
class MockQuery(object):
|
||||||
"""a fake Query object that supports querying by id
|
"""a fake Query object that supports querying by id
|
||||||
and listing all keys. No other operation is supported
|
and listing all keys. No other operation is supported
|
||||||
|
|||||||
+3
-3
@@ -498,7 +498,6 @@ class Session(Storage):
|
|||||||
masterapp=None,
|
masterapp=None,
|
||||||
clear_session=False
|
clear_session=False
|
||||||
):
|
):
|
||||||
|
|
||||||
if request is None:
|
if request is None:
|
||||||
request = current.request
|
request = current.request
|
||||||
if response is None:
|
if response is None:
|
||||||
@@ -576,13 +575,14 @@ class Session(Storage):
|
|||||||
if record_id == '0':
|
if record_id == '0':
|
||||||
raise Exception('record_id == 0')
|
raise Exception('record_id == 0')
|
||||||
# Select from database
|
# Select from database
|
||||||
row = db(table.id == record_id).select().first()
|
row = db(table.id == record_id).select()
|
||||||
|
row = row and row[0] or None
|
||||||
# Make sure the session data exists in the database
|
# Make sure the session data exists in the database
|
||||||
if not row or row.unique_key != unique_key:
|
if not row or row.unique_key != unique_key:
|
||||||
raise Exception('No record')
|
raise Exception('No record')
|
||||||
|
|
||||||
unique_key = web2py_uuid()
|
unique_key = web2py_uuid()
|
||||||
row.update_record(unique_key=unique_key)
|
db(table.id == record_id).update(unique_key=unique_key)
|
||||||
response.session_id = '%s:%s' % (record_id, unique_key)
|
response.session_id = '%s:%s' % (record_id, unique_key)
|
||||||
response.session_db_table = table
|
response.session_db_table = table
|
||||||
response.session_db_record_id = record_id
|
response.session_db_record_id = record_id
|
||||||
|
|||||||
+12
-7
@@ -1794,7 +1794,7 @@ class Auth(object):
|
|||||||
guess = keys.get('email', 'anonymous').split('@')[0]
|
guess = keys.get('email', 'anonymous').split('@')[0]
|
||||||
keys['first_name'] = keys.get('username', guess)
|
keys['first_name'] = keys.get('username', guess)
|
||||||
user_id = table_user.insert(**table_user._filter_fields(keys))
|
user_id = table_user.insert(**table_user._filter_fields(keys))
|
||||||
user = table_user[user_id]
|
user = table_user[user_id]
|
||||||
print user
|
print user
|
||||||
if self.settings.create_user_groups:
|
if self.settings.create_user_groups:
|
||||||
group_id = self.add_group(
|
group_id = self.add_group(
|
||||||
@@ -1856,11 +1856,14 @@ class Auth(object):
|
|||||||
delattr(user,'password')
|
delattr(user,'password')
|
||||||
else:
|
else:
|
||||||
user = Row(user)
|
user = Row(user)
|
||||||
for key,value in user.items():
|
for key, value in user.items():
|
||||||
if callable(value) or key=='password':
|
if callable(value) or key=='password':
|
||||||
delattr(user,key)
|
delattr(user,key)
|
||||||
|
sessdb = current.response.session_db_table and current.response.session_db_table._db or None
|
||||||
current.session.renew(
|
current.session.renew(
|
||||||
clear_session=not self.settings.keep_session_onlogin, db=self.db)
|
clear_session=not self.settings.keep_session_onlogin,
|
||||||
|
db=sessdb
|
||||||
|
)
|
||||||
current.session.auth = Storage(
|
current.session.auth = Storage(
|
||||||
user = user,
|
user = user,
|
||||||
last_visit=current.request.now,
|
last_visit=current.request.now,
|
||||||
@@ -2247,8 +2250,10 @@ class Auth(object):
|
|||||||
|
|
||||||
current.session.auth = None
|
current.session.auth = None
|
||||||
current.session.flash = self.messages.logged_out
|
current.session.flash = self.messages.logged_out
|
||||||
|
sessdb = current.response.session_db_table and current.response.session_db_table._db or None
|
||||||
current.session.renew(
|
current.session.renew(
|
||||||
clear_session=not self.settings.keep_session_onlogout, db=self.db)
|
clear_session=not self.settings.keep_session_onlogout,
|
||||||
|
db=sessdb)
|
||||||
if not next is None:
|
if not next is None:
|
||||||
redirect(next)
|
redirect(next)
|
||||||
|
|
||||||
@@ -4913,7 +4918,7 @@ class Expose(object):
|
|||||||
def __init__(self, base=None, basename=None, extensions=None, allow_download=True):
|
def __init__(self, base=None, basename=None, extensions=None, allow_download=True):
|
||||||
"""
|
"""
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
def static():
|
def static():
|
||||||
return dict(files=Expose())
|
return dict(files=Expose())
|
||||||
|
|
||||||
@@ -4995,7 +5000,7 @@ class Expose(object):
|
|||||||
return ''
|
return ''
|
||||||
|
|
||||||
def xml(self):
|
def xml(self):
|
||||||
return DIV(
|
return DIV(
|
||||||
H2(self.breadcrumbs(self.basename)),
|
H2(self.breadcrumbs(self.basename)),
|
||||||
self.paragraph or '',
|
self.paragraph or '',
|
||||||
self.table_folders(),
|
self.table_folders(),
|
||||||
@@ -5154,7 +5159,7 @@ class Wiki(object):
|
|||||||
db.wiki_tag.insert(name=tag, wiki_page=page.id)
|
db.wiki_tag.insert(name=tag, wiki_page=page.id)
|
||||||
db.wiki_page._after_insert.append(update_tags_insert)
|
db.wiki_page._after_insert.append(update_tags_insert)
|
||||||
db.wiki_page._after_update.append(update_tags_update)
|
db.wiki_page._after_update.append(update_tags_update)
|
||||||
|
|
||||||
if (auth.user and
|
if (auth.user and
|
||||||
check_credentials(current.request, gae_login=False) and
|
check_credentials(current.request, gae_login=False) and
|
||||||
not 'wiki_editor' in auth.user_groups.values()):
|
not 'wiki_editor' in auth.user_groups.values()):
|
||||||
|
|||||||
+10
-16
@@ -11,8 +11,8 @@ This file specifically includes utilities for security.
|
|||||||
|
|
||||||
import threading
|
import threading
|
||||||
import struct
|
import struct
|
||||||
import hashlib
|
#import hashlib
|
||||||
import hmac
|
#import hmac
|
||||||
import uuid
|
import uuid
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
@@ -23,6 +23,7 @@ import logging
|
|||||||
import socket
|
import socket
|
||||||
import base64
|
import base64
|
||||||
import zlib
|
import zlib
|
||||||
|
from types import ModuleType
|
||||||
|
|
||||||
_struct_2_long_long = struct.Struct('=QQ')
|
_struct_2_long_long = struct.Struct('=QQ')
|
||||||
|
|
||||||
@@ -33,21 +34,15 @@ if python_version == 2:
|
|||||||
else:
|
else:
|
||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
try:
|
from hashlib import md5, sha1, sha224, sha256, sha384, sha512
|
||||||
from Crypto.Hash import MD5 as md5, \
|
|
||||||
SHA as sha1, \
|
|
||||||
SHA224 as sha224, \
|
|
||||||
SHA256 as sha256, \
|
|
||||||
SHA384 as sha384, \
|
|
||||||
SHA512 as sha512
|
|
||||||
except ImportError:
|
|
||||||
from hashlib import md5, sha1, sha224, sha256, sha384, sha512
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import contrib.aes as AES
|
import contrib.aes as AES
|
||||||
|
|
||||||
|
import hmac
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from contrib.pbkdf2 import pbkdf2_hex
|
from contrib.pbkdf2 import pbkdf2_hex
|
||||||
HAVE_PBKDF2 = True
|
HAVE_PBKDF2 = True
|
||||||
@@ -80,8 +75,7 @@ def compare(a, b):
|
|||||||
|
|
||||||
def md5_hash(text):
|
def md5_hash(text):
|
||||||
""" Generate a md5 hash with the given text """
|
""" Generate a md5 hash with the given text """
|
||||||
return md5.new(text).hexdigest()
|
return md5(text).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def simple_hash(text, key='', salt='', digest_alg='md5'):
|
def simple_hash(text, key='', salt='', digest_alg='md5'):
|
||||||
"""
|
"""
|
||||||
@@ -100,7 +94,7 @@ def simple_hash(text, key='', salt='', digest_alg='md5'):
|
|||||||
digest_alg = get_digest(digest_alg)
|
digest_alg = get_digest(digest_alg)
|
||||||
h = hmac.new(key + salt, text, digest_alg)
|
h = hmac.new(key + salt, text, digest_alg)
|
||||||
else: # compatible with third party systems
|
else: # compatible with third party systems
|
||||||
h = hashlib.new(digest_alg)
|
h = get_digest(digest_alg)()
|
||||||
h.update(text + salt)
|
h.update(text + salt)
|
||||||
return h.hexdigest()
|
return h.hexdigest()
|
||||||
|
|
||||||
@@ -143,7 +137,7 @@ def pad(s, n=32, padchar=' '):
|
|||||||
|
|
||||||
def secure_dumps(data, encryption_key, hash_key=None, compression_level=None):
|
def secure_dumps(data, encryption_key, hash_key=None, compression_level=None):
|
||||||
if not hash_key:
|
if not hash_key:
|
||||||
hash_key = hashlib.sha1(encryption_key).hexdigest()
|
hash_key = sha1(encryption_key).hexdigest()
|
||||||
dump = pickle.dumps(data)
|
dump = pickle.dumps(data)
|
||||||
if compression_level:
|
if compression_level:
|
||||||
dump = zlib.compress(dump, compression_level)
|
dump = zlib.compress(dump, compression_level)
|
||||||
@@ -158,7 +152,7 @@ def secure_loads(data, encryption_key, hash_key=None, compression_level=None):
|
|||||||
if not ':' in data:
|
if not ':' in data:
|
||||||
return None
|
return None
|
||||||
if not hash_key:
|
if not hash_key:
|
||||||
hash_key = hashlib.sha1(encryption_key).hexdigest()
|
hash_key = sha1(encryption_key).hexdigest()
|
||||||
signature, encrypted_data = data.split(':', 1)
|
signature, encrypted_data = data.split(':', 1)
|
||||||
actual_signature = hmac.new(hash_key, encrypted_data).hexdigest()
|
actual_signature = hmac.new(hash_key, encrypted_data).hexdigest()
|
||||||
if not compare(signature, actual_signature):
|
if not compare(signature, actual_signature):
|
||||||
|
|||||||
Reference in New Issue
Block a user