Merge ssh://github.com/web2py/web2py

This commit is contained in:
Michele Comitini
2013-07-18 11:25:58 +02:00
9 changed files with 154 additions and 73 deletions
+1 -1
View File
@@ -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
+83
View File
@@ -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

+39 -31
View File
@@ -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
View File
@@ -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')
-1
View File
@@ -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
View File
@@ -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
+8 -3
View File
@@ -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)
+10 -16
View File
@@ -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):