From 2c81a44fabf65d5d96c3871f8e0e23cbb7051594 Mon Sep 17 00:00:00 2001 From: niphlod Date: Sat, 3 Aug 2013 17:55:50 +0200 Subject: [PATCH 1/7] fixed bug with Mysql. Thanks @Adi for reporting. --- gluon/tools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gluon/tools.py b/gluon/tools.py index 94a814dc..2533a25e 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -5106,7 +5106,7 @@ class Wiki(object): requires=[IS_SLUG(), IS_NOT_IN_DB(db, 'wiki_page.slug')], writable=False), - Field('title', unique=True), + Field('title', length=255, unique=True), Field('body', 'text', notnull=True), Field('tags', 'list:string'), Field('can_read', 'list:string', From 5eacefb581c2c25d62823a67ef0a72f3b5c725df Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 4 Aug 2013 12:53:17 -0500 Subject: [PATCH 2/7] issue 1612:mongodb adapter does raw blob data, thanks Alan --- VERSION | 2 +- gluon/dal.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/VERSION b/VERSION index ca9652d7..92345b21 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.6.0-development+timestamp.2013.08.01.08.22.32 +Version 2.6.0-development+timestamp.2013.08.04.12.52.14 diff --git a/gluon/dal.py b/gluon/dal.py index e1ecc2f6..0739f582 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -5347,6 +5347,9 @@ class MongoDBAdapter(NoSQLAdapter): # mongodb doesn't has a time object and so it must datetime, # string or integer return datetime.datetime.combine(d, value) + elif fieldtype == "blob": + from bson import Binary + return Binary(value) elif (isinstance(fieldtype, basestring) and fieldtype.startswith('list:')): if fieldtype.startswith('list:reference'): From ae567462d36729637e17944f604ab90ede9c8d9b Mon Sep 17 00:00:00 2001 From: niphlod Date: Sun, 4 Aug 2013 20:56:52 +0200 Subject: [PATCH 3/7] fixed issue 1611 (scheduler's migrate should follow Auth's migrate behaviour) --- gluon/scheduler.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/gluon/scheduler.py b/gluon/scheduler.py index 92036210..0fa207e3 100644 --- a/gluon/scheduler.py +++ b/gluon/scheduler.py @@ -454,6 +454,15 @@ class Scheduler(MetaScheduler): self.define_tables(db, migrate=migrate) + def __get_migrate(self, tablename, migrate=True): + if migrate is False: + return False + elif migrate is True: + return True + elif isinstance(migrate, str): + return "%s%s.table" % (migrate , tablename) + return True + def now(self): return self.utc_time and datetime.datetime.utcnow() or datetime.datetime.now() @@ -505,7 +514,8 @@ class Scheduler(MetaScheduler): Field('last_run_time', 'datetime', writable=False, readable=False), Field('assigned_worker_name', default='', writable=False), on_define=self.set_requirements, - migrate=migrate, format='%(task_name)s') + migrate=self.__get_migrate('scheduler_task', migrate), + format='%(task_name)s') db.define_table( 'scheduler_run', @@ -517,7 +527,8 @@ class Scheduler(MetaScheduler): Field('run_result', 'text'), Field('traceback', 'text'), Field('worker_name', default=self.worker_name), - migrate=migrate) + migrate=self.__get_migrate('scheduler_run', migrate) + ) db.define_table( 'scheduler_worker', @@ -526,9 +537,11 @@ class Scheduler(MetaScheduler): Field('last_heartbeat', 'datetime'), Field('status', requires=IS_IN_SET(WORKER_STATUS)), Field('is_ticker', 'boolean', default=False, writable=False), - Field('group_names', 'list:string', default=self.group_names),#FIXME writable=False or give the chance to update dinamically the groups? - migrate=migrate) - if migrate: + Field('group_names', 'list:string', default=self.group_names), + migrate=self.__get_migrate('scheduler_worker', migrate) + ) + + if migrate is not False: db.commit() def loop(self, worker_name=None): From fbf3a20918732acde4744d8415f28db319773081 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 4 Aug 2013 17:01:17 -0500 Subject: [PATCH 4/7] in view/layout, response.files.insert instead of append --- VERSION | 2 +- applications/welcome/views/layout.html | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/VERSION b/VERSION index 92345b21..9cec8518 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.6.0-development+timestamp.2013.08.04.12.52.14 +Version 2.6.0-development+timestamp.2013.08.04.17.00.24 diff --git a/applications/welcome/views/layout.html b/applications/welcome/views/layout.html index dd56bcb9..64e382ea 100644 --- a/applications/welcome/views/layout.html +++ b/applications/welcome/views/layout.html @@ -40,11 +40,11 @@ - {{ - response.files.append(URL('static','css/web2py.css')) - response.files.append(URL('static','css/bootstrap.min.css')) - response.files.append(URL('static','css/bootstrap-responsive.min.css')) - response.files.append(URL('static','css/web2py_bootstrap.css')) + {{ + response.files.insert(0,URL('static','css/web2py.css')) + response.files.insert(1,URL('static','css/bootstrap.min.css')) + response.files.insert(2,URL('static','css/bootstrap-responsive.min.css')) + response.files.insert(3,URL('static','css/web2py_bootstrap.css')) }} {{include 'web2py_ajax.html'}} From 9db6ebf4f6b7880f442822e3808a86688de941b4 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Mon, 5 Aug 2013 02:34:03 -0500 Subject: [PATCH 5/7] new pbkdf2_ctypes.py, works on Mac, thanks Michele --- VERSION | 2 +- gluon/contrib/pbkdf2_ctypes.py | 124 +++++++++++++++++++++------------ 2 files changed, 80 insertions(+), 46 deletions(-) diff --git a/VERSION b/VERSION index 9cec8518..c9d93d1c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.6.0-development+timestamp.2013.08.04.17.00.24 +Version 2.6.0-development+timestamp.2013.08.05.02.33.02 diff --git a/gluon/contrib/pbkdf2_ctypes.py b/gluon/contrib/pbkdf2_ctypes.py index 1e7d8a9d..5bb2e7dc 100644 --- a/gluon/contrib/pbkdf2_ctypes.py +++ b/gluon/contrib/pbkdf2_ctypes.py @@ -34,14 +34,29 @@ def commoncrypto_hashlib_to_crypto_map_get(hashfunc): raise ValueError('Unkwnown digest %s' % hashfunc) return crypto_hashfunc -def commoncrypto_pbkdf2(c_pass, c_passlen, - c_salt, c_saltlen, - c_iter, digest, c_keylen, c_buff): +def commoncrypto_pbkdf2(data, salt, iterations, digest, keylen): """Common Crypto compatibile wrapper """ - c_hashfunc = ctypes.c_int(commoncrypto_hashlib_to_crypto_map_get(digest)) + c_hashfunc = ctypes.c_uint32(commoncrypto_hashlib_to_crypto_map_get(digest)) + c_pass = ctypes.c_char_p(data) + c_passlen = ctypes.c_size_t(len(data)) + c_salt = ctypes.c_char_p(salt) + c_saltlen = ctypes.c_size_t(len(salt)) + c_iter = ctypes.c_uint(iterations) + c_keylen = ctypes.c_size_t(keylen) + c_buff = ctypes.create_string_buffer(keylen) - return 1 - crypto.CCKeyDerivationPBKDF(2, # hardcoded 2-> PBKDF2 + crypto.CCKeyDerivationPBKDF.restype = ctypes.c_int + crypto.CCKeyDerivationPBKDF.argtypes = [ctypes.c_uint32, + ctypes.c_char_p, + ctypes.c_size_t, + ctypes.c_char_p, + ctypes.c_size_t, + ctypes.c_uint32, + ctypes.c_uint, + ctypes.c_char_p, + ctypes.c_size_t] + ret = crypto.CCKeyDerivationPBKDF(2, # hardcoded 2-> PBKDF2 c_pass, c_passlen, c_salt, c_saltlen, c_hashfunc, @@ -49,6 +64,7 @@ def commoncrypto_pbkdf2(c_pass, c_passlen, c_buff, c_keylen) + return (1 - ret, c_buff) def openssl_hashlib_to_crypto_map_get(hashfunc): hashlib_to_crypto_map = {hashlib.md5: crypto.EVP_md5, @@ -64,58 +80,76 @@ def openssl_hashlib_to_crypto_map_get(hashfunc): return crypto_hashfunc() -def openssl_pbkdf2(c_pass, c_passlen, - c_salt, c_saltlen, - c_iter, digest, c_keylen, c_buff): +def openssl_pbkdf2(data, salt, iterations, digest, keylen): """OpenSSL compatibile wrapper """ c_hashfunc = ctypes.c_void_p(openssl_hashlib_to_crypto_map_get(digest)) - return crypto.PKCS5_PBKDF2_HMAC(c_pass, c_passlen, - c_salt, c_saltlen, - c_iter, - c_hashfunc, - c_keylen, - c_buff) - -try: # check that we have proper OpenSSL or Common Crypto on the system. - system = platform.system() - if system == 'Windows': - if platform.architecture()[0] == '64bit': - crypto = ctypes.CDLL(os.path.basename( - ctypes.util.find_library('libeay64'))) - else: - crypto = ctypes.CDLL(os.path.basename( - ctypes.util.find_library('libeay32'))) - _pbkdf2_hmac = openssl_pbkdf2 - crypto.PKCS5_PBKDF2_HMAC # test compatibility - elif system == 'Darwin': # think different(TM)! i.e. break things! - raise ImportError('Not yet available on OS X') - else: - crypto = ctypes.CDLL(os.path.basename( - ctypes.util.find_library('crypto'))) - _pbkdf2_hmac = openssl_pbkdf2 - crypto.PKCS5_PBKDF2_HMAC # test compatibility - -except (OSError, AttributeError), e: - raise ImportError('Cannot find a compatible OpenSSL installation ' - 'on your system') - - -def pkcs5_pbkdf2_hmac(data, salt, iterations=1000, keylen=24, hashfunc=None): c_pass = ctypes.c_char_p(data) c_passlen = ctypes.c_int(len(data)) c_salt = ctypes.c_char_p(salt) c_saltlen = ctypes.c_int(len(salt)) c_iter = ctypes.c_int(iterations) c_keylen = ctypes.c_int(keylen) - c_buff = ctypes.create_string_buffer('\000' * keylen) - err = _pbkdf2_hmac(c_pass, c_passlen, + c_buff = ctypes.create_string_buffer(keylen) + + # PKCS5_PBKDF2_HMAC(const char *pass, int passlen, + # const unsigned char *salt, int saltlen, int iter, + # const EVP_MD *digest, + # int keylen, unsigned char *out); + + crypto.PKCS5_PBKDF2_HMAC.argtypes = [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_char_p] + + crypto.PKCS5_PBKDF2_HMAC.restype = ctypes.c_int + err = crypto.PKCS5_PBKDF2_HMAC(c_pass, c_passlen, c_salt, c_saltlen, c_iter, - hashfunc, + c_hashfunc, c_keylen, c_buff) + return (err, c_buff) + +try: # check that we have proper OpenSSL or Common Crypto on the system. + system = platform.system() + if system == 'Windows': + if platform.architecture()[0] == '64bit': + libname = ctypes.util.find_library('libeay64') + if not libname: + raise OSError('Library not found') + crypto = ctypes.CDLL(os.path.basename(libname)) + else: + libname = ctypes.util.find_library('libeay32') + if not libname: + raise OSError('Library not found') + + crypto = ctypes.CDLL(os.path.basename(libname)) + _pbkdf2_hmac = openssl_pbkdf2 + crypto.PKCS5_PBKDF2_HMAC # test compatibility + elif system == 'Darwin': # think different(TM)! i.e. break things! + libname = ctypes.util.find_library('System') + if not libname: + raise OSError('Library not found') + + crypto = ctypes.CDLL(os.path.basename(libname)) + _pbkdf2_hmac = commoncrypto_pbkdf2 + else: + libname = ctypes.util.find_library('crypto') + if not libname: + raise OSError('not found') + crypto = ctypes.CDLL(os.path.basename(libname)) + _pbkdf2_hmac = openssl_pbkdf2 + crypto.PKCS5_PBKDF2_HMAC # test compatibility + +except (OSError, AttributeError), e: + raise ImportError('Cannot find a compatible cryptographic library ' + 'on your system') + + +def pkcs5_pbkdf2_hmac(data, salt, iterations=1000, keylen=24, hashfunc=None): + err, c_buff = _pbkdf2_hmac(data, salt, iterations, hashfunc, keylen) if err == 0: raise ValueError('wrong parameters') @@ -135,8 +169,8 @@ if __name__ == '__main__': crypto.SSLeay_version.restype = ctypes.c_char_p print crypto.SSLeay_version(0) except: - print "Not using OpenSSL" + pass for h in [hashlib.sha1, hashlib.sha224, hashlib.sha256, hashlib.sha384, hashlib.sha512]: - pkcs5_pbkdf2_hmac('secret' * 11, 'salt', hashfunc=h) + print pkcs5_pbkdf2_hmac('secret' * 11, 'salt', hashfunc=h).encode('hex') From ee102fbfe8a432e8220c818dd08be3922ad4a913 Mon Sep 17 00:00:00 2001 From: szimszon Date: Mon, 5 Aug 2013 13:14:52 +0200 Subject: [PATCH 6/7] disable_with message should be translatable --- applications/welcome/static/js/web2py.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/applications/welcome/static/js/web2py.js b/applications/welcome/static/js/web2py.js index 507be9f5..d96e685d 100644 --- a/applications/welcome/static/js/web2py.js +++ b/applications/welcome/static/js/web2py.js @@ -211,12 +211,13 @@ }, trap_form: function (action, target) { + var disable_with_message = (typeof w2p_ajax_disable_with_message != 'undefined') ? w2p_ajax_disable_with_message : "Working..."; $('#' + target + ' form').each(function (i) { var form = $(this); form.attr('data-w2p_target', target); if(!form.hasClass('no_trap')) { //should be there by default ? - form.find('input[type=submit]').attr('data-w2p_disable_with', 'Working...'); + form.find('input[type=submit]').attr('data-w2p_disable_with', disable_with_message); form.submit(function (e) { web2py.hide_flash(); web2py.ajax_page('post', action, form.serialize(), target, form); @@ -431,11 +432,12 @@ disableElement: function (el) { el.addClass('disabled'); var method = el.prop('type') == 'submit' ? 'val' : 'html'; + var disable_with_message = (typeof w2p_ajax_disable_with_message != 'undefined') ? w2p_ajax_disable_with_message : "Working..."; // store enabled state el.data('w2p:enable-with', el[method]()); /* little addition by default*/ if((el.data('w2p_disable_with') == 'default') || (el.data('w2p_disable_with') === undefined)) { - el.data('w2p_disable_with', 'Working...'); + el.data('w2p_disable_with', disable_with_message); } // set to disabled state el[method](el.data('w2p_disable_with')); From 58d832889994a11f0794eabcad47b92d5d26e4d7 Mon Sep 17 00:00:00 2001 From: szimszon Date: Mon, 5 Aug 2013 13:16:29 +0200 Subject: [PATCH 7/7] disable_with message should be translatable --- applications/welcome/views/web2py_ajax.html | 1 + 1 file changed, 1 insertion(+) diff --git a/applications/welcome/views/web2py_ajax.html b/applications/welcome/views/web2py_ajax.html index 52709edc..5d7195b0 100644 --- a/applications/welcome/views/web2py_ajax.html +++ b/applications/welcome/views/web2py_ajax.html @@ -1,6 +1,7 @@