From e5f9358cf93803bba8ebfe4cb7bf72ce9791f1cd Mon Sep 17 00:00:00 2001 From: Michele Comitini Date: Wed, 29 Aug 2012 14:24:14 +0200 Subject: [PATCH] commit merge --- CHANGELOG | 3 + Makefile | 2 +- VERSION | 2 +- applications/admin/controllers/appadmin.py | 2 + applications/admin/controllers/default.py | 10 +- applications/admin/languages/default.py | 122 ++++ .../admin/static/images/sidebar_bullet.png | Bin 718 -> 0 bytes .../admin/static/js/jquery.timeentry.js | 571 --------------- applications/admin/views/appadmin.html | 47 +- applications/admin/views/default/ticket.html | 8 +- applications/examples/controllers/appadmin.py | 2 + applications/examples/static/images/gluon.png | Bin 58169 -> 0 bytes .../examples/static/images/logo3Tones.png | Bin 149438 -> 0 bytes .../examples/static/images/netdow1.png | Bin 3883 -> 0 bytes .../examples/static/images/netdow2.png | Bin 3888 -> 0 bytes .../examples/static/images/netdow3.png | Bin 714 -> 0 bytes .../examples/static/images/tablet.png | Bin 51003 -> 0 bytes .../examples/static/images/tipDownloads.png | Bin 5783 -> 0 bytes .../examples/static/images/tipDownloads2.png | Bin 6085 -> 0 bytes .../static/images/web2py_logo_light.png | Bin 7786 -> 0 bytes applications/examples/static/js/common.js | 116 ---- .../examples/static/js/jquery-1.5-min.js | 16 - .../examples/static/js/jquery.prettyPhoto.js | 69 -- .../powered_by/web2py_sticker_3d8799.png | Bin 548 -> 0 bytes .../powered_by/web2py_sticker_3d9960.png | Bin 545 -> 0 bytes .../powered_by/web2py_sticker_463d99.png | Bin 555 -> 0 bytes .../powered_by/web2py_sticker_73993d.png | Bin 547 -> 0 bytes .../powered_by/web2py_sticker_993d3d.png | Bin 545 -> 0 bytes .../powered_by/web2py_sticker_993d98.png | Bin 536 -> 0 bytes .../powered_by/web2py_sticker_996f3d.png | Bin 544 -> 0 bytes .../powered_by/web2py_sticker_99963d.png | Bin 550 -> 0 bytes .../examples/static/web2py_logo_light.png | Bin 7786 -> 0 bytes applications/examples/views/appadmin.html | 47 +- applications/welcome/controllers/appadmin.py | 2 + applications/welcome/languages/cs.py | 14 +- applications/welcome/languages/default.py | 11 + applications/welcome/languages/es.py | 14 +- applications/welcome/languages/fr-ca.py | 14 +- applications/welcome/languages/fr.py | 14 +- applications/welcome/languages/hi.py | 14 +- applications/welcome/languages/hu.py | 14 +- applications/welcome/languages/it.py | 93 ++- applications/welcome/languages/nl.py | 14 +- applications/welcome/languages/pl.py | 14 +- applications/welcome/languages/pt-br.py | 14 +- applications/welcome/languages/pt.py | 14 +- applications/welcome/languages/ro.py | 14 +- applications/welcome/languages/ru.py | 12 +- applications/welcome/languages/sk.py | 14 +- applications/welcome/languages/uk.py | 14 +- applications/welcome/languages/zh.py | 14 +- .../welcome/static/images/arrows-ffffff.png | Bin 244 -> 0 bytes .../static/images/css3buttons_backgrounds.png | Bin 1367 -> 0 bytes .../static/images/css3buttons_icons.png | Bin 3322 -> 0 bytes .../welcome/static/images/poweredby.png | Bin 4150 -> 0 bytes applications/welcome/static/images/shadow.png | Bin 1698 -> 0 bytes .../static/images/ui-icons_222222_256x240.png | Bin 4369 -> 0 bytes applications/welcome/views/appadmin.html | 47 +- gluon/cache.py | 2 +- gluon/compileapp.py | 81 +-- gluon/globals.py | 109 +-- gluon/html.py | 72 +- gluon/http.py | 40 +- gluon/languages.py | 640 ++++++++--------- gluon/main.py | 200 +++--- gluon/portalocker.py | 14 +- gluon/restricted.py | 23 +- gluon/rewrite.py | 117 ++-- gluon/rocket.py | 5 +- gluon/settings.py | 15 +- gluon/sqlhtml.py | 6 +- gluon/template.py | 189 ++--- gluon/tests/test_dal.py | 31 + gluon/tests/test_languages.py | 34 + gluon/tools.py | 656 +++++++++--------- 75 files changed, 1546 insertions(+), 2066 deletions(-) delete mode 100644 applications/admin/static/images/sidebar_bullet.png delete mode 100644 applications/admin/static/js/jquery.timeentry.js delete mode 100644 applications/examples/static/images/gluon.png delete mode 100644 applications/examples/static/images/logo3Tones.png delete mode 100644 applications/examples/static/images/netdow1.png delete mode 100644 applications/examples/static/images/netdow2.png delete mode 100644 applications/examples/static/images/netdow3.png delete mode 100644 applications/examples/static/images/tablet.png delete mode 100644 applications/examples/static/images/tipDownloads.png delete mode 100644 applications/examples/static/images/tipDownloads2.png delete mode 100644 applications/examples/static/images/web2py_logo_light.png delete mode 100644 applications/examples/static/js/common.js delete mode 100644 applications/examples/static/js/jquery-1.5-min.js delete mode 100644 applications/examples/static/js/jquery.prettyPhoto.js delete mode 100644 applications/examples/static/powered_by/web2py_sticker_3d8799.png delete mode 100644 applications/examples/static/powered_by/web2py_sticker_3d9960.png delete mode 100644 applications/examples/static/powered_by/web2py_sticker_463d99.png delete mode 100644 applications/examples/static/powered_by/web2py_sticker_73993d.png delete mode 100644 applications/examples/static/powered_by/web2py_sticker_993d3d.png delete mode 100644 applications/examples/static/powered_by/web2py_sticker_993d98.png delete mode 100644 applications/examples/static/powered_by/web2py_sticker_996f3d.png delete mode 100644 applications/examples/static/powered_by/web2py_sticker_99963d.png delete mode 100644 applications/examples/static/web2py_logo_light.png delete mode 100644 applications/welcome/static/images/arrows-ffffff.png delete mode 100644 applications/welcome/static/images/css3buttons_backgrounds.png delete mode 100644 applications/welcome/static/images/css3buttons_icons.png delete mode 100644 applications/welcome/static/images/poweredby.png delete mode 100644 applications/welcome/static/images/shadow.png delete mode 100644 applications/welcome/static/images/ui-icons_222222_256x240.png diff --git a/CHANGELOG b/CHANGELOG index 993ebe19..bd6fb9cd 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,9 @@ ### DAL Improvements - Support for DAL(lazy_tables=True) and db.define_table(on_define=lambda table:), thanks Jonathan +- db(...).select(cacheable=True) make select 30% faster +- db(...).select(cache=(cache.ram,3600)) now caches parsed data 100x faster +- db(...).count(cache=(cache.ram,3600)) now supported - MongoDB support in DAL (experimental), thanks Mark Breedveld - geodal and spatialite, thanks Denes and Fran (experimental) - db.mytable._before_insert, _after_insert, _before_update, _after_update, _before_delete. _after_delete (list of callbacks) diff --git a/Makefile b/Makefile index 864d37ec..4eace126 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ update: wget -O gluon/contrib/simplejsonrpc.py http://rad2py.googlecode.com/hg/ide2py/simplejsonrpc.py echo "remember that pymysql was tweaked" src: - echo 'Version 2.00.0 ('`date +%Y-%m-%d\ %H:%M:%S`') dev' > VERSION + echo 'Version 2.00.1 ('`date +%Y-%m-%d\ %H:%M:%S`') rc4' > VERSION ### rm -f all junk files make clean ### clean up baisc apps diff --git a/VERSION b/VERSION index 3fd1bc7d..7b48a4bd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-08-26 00:00:11) dev +Version 2.00.1 (2012-08-28 22:14:54) rc4 diff --git a/applications/admin/controllers/appadmin.py b/applications/admin/controllers/appadmin.py index 126200b9..fa264bae 100644 --- a/applications/admin/controllers/appadmin.py +++ b/applications/admin/controllers/appadmin.py @@ -11,6 +11,8 @@ import copy import gluon.contenttype import gluon.fileutils +response.subtitle = 'Database Administration (appadmin)' + # ## critical --- make a copy of the environment global_env = copy.copy(globals()) diff --git a/applications/admin/controllers/default.py b/applications/admin/controllers/default.py index 4f685ba0..1fb8cf9e 100644 --- a/applications/admin/controllers/default.py +++ b/applications/admin/controllers/default.py @@ -23,9 +23,9 @@ except ImportError: GIT_MISSING = 'requires python-git module, but not installed or incompatible version' from gluon.languages import (regex_language, read_possible_languages, - read_possible_plurals, lang_sampling, + lang_sampling, read_dict, write_dict, read_plural_dict, - write_plural_dict) + write_plural_dict, PLURAL_RULES) if DEMO_MODE and request.function in ['change_password','pack','pack_plugin','upgrade_web2py','uninstall','cleanup','compile_app','remove_compiled_app','delete','delete_plugin','create_file','upload_file','update_languages','reload_routes','git_push','git_pull']: @@ -949,8 +949,8 @@ def design(): # get only existed files languages = sorted(all_languages) - plural_rules={} - all_plurals=read_possible_plurals() + plural_rules = {} + all_plurals = PLURAL_RULES for langfile,lang in all_languages.iteritems(): lang=lang.strip() match_language = regex_language.match(lang) @@ -961,7 +961,7 @@ def design(): plang = lang_sampling(match_language, all_plurals.keys()) if plang: plural=all_plurals[plang] - plural_rules[langfile]=(plural[0],plang,plural[1],plural[3]) + plural_rules[langfile]=(plural[0],plang,plural[4],plural[3]) else: plural_rules[langfile]=(0,lang,'plural_rules-%s.py'%lang,'') diff --git a/applications/admin/languages/default.py b/applications/admin/languages/default.py index 94b0828c..a9bd0be9 100644 --- a/applications/admin/languages/default.py +++ b/applications/admin/languages/default.py @@ -4,5 +4,127 @@ '!langname!': 'English (US)', '%Y-%m-%d': '%m-%d-%Y', '%Y-%m-%d %H:%M:%S': '%m-%d-%Y %H:%M:%S', +'(requires internet access)': '(requires internet access)', +'(something like "it-it")': '(something like "it-it")', +'About': 'About', +'Additional code for your application': 'Additional code for your application', +'Admin language': 'Admin language', +'administrative interface': 'administrative interface', +'Administrator Password:': 'Administrator Password:', +'and rename it:': 'and rename it:', +'Application name:': 'Application name:', +'are not used yet': 'are not used yet', +'Are you sure you want to delete this object?': 'Are you sure you want to delete this object?', +'arguments': 'arguments', 'back': '<Px#32;bRa{vGh*8l(w*8xH(n|J^K00(qQO+^RV3kC`?8XIDOIsgCyU`a$lR4C7V zlFv#TQ5eO)xqs$Q633wprW&WNI)NfW5XNp@_yE#ZDEJIMfzKcmT)8anx{TXekbp=9 zn?Od4Q%PE9CYiaDJNMq{A~v*}{uYPtgL5{Aqm^X|f8d-aNs{Mzp638ynx<)*wr%UW zzVML66-Ci_Jbrk17>~zM6aj$aIQ4pcZEdYyuRD(OPaq7#(P(sWaq;;0Sd`N#{tf`O z;Tx*e8jZ%z&JJU2b#)a0w6ZLdBng7x?CdNne$Kp4uiC#5#sHwC{Ly`3+`g~Sm;3ws z8yg$8Z6hH>9LJqbC(1%&@5J@fs%6)#<(jozwQSc2DXfeUA1h> ztQpkOiLtUZ;wlM(pePEWlo|{Mr5z%SF(!oQIyEci(!7j9aEuAUxU|E;V4##j7-P=4 zloI}nl#+9fF-DY9*LCB&ic(TaAq3||p5>D)pYS3Vf=elslJQ-|bzMp+qLg}`m&PKx zX>u`}6^!N6lqD%kSU#N~pC(LGPmQPX^r!3C$37e(t z316MMtyatTeM+fTmZcEl{{H^p;GiU_|6#o3-64blKq)!7ef{-gT@%&g -1; - }, - - /* Reconfigure the settings for a time entry field. - @param input (element) input field to change - @param options (object) new settings to add or - (string) an individual setting name - @param value (any) the individual setting's value - */ - _changeTimeEntry: function(input, options, value) { - var inst = jQuery.data(input, PROP_NAME); - if (inst) { - if (typeof options == 'string') { - var name = options; - options = {}; - options[name] = value; - } - var currentTime = this._extractTime(inst); - extendRemove(inst.options, options || {}); - if (currentTime) - this._setTime(inst, new Date(0, 0, 0, - currentTime[0], currentTime[1], currentTime[2])); - } - jQuery.data(input, PROP_NAME, inst); - }, - - /* Remove the time entry functionality from an input. - @param input (element) input field to affect - */ - _destroyTimeEntry: function(input) { - jQueryinput = jQuery(input); - if (!jQueryinput.hasClass(this.markerClassName)) return; - jQueryinput.removeClass(this.markerClassName).unbind('.timeEntry'); - this._disabledInputs = jQuery.map(this._disabledInputs, function(value) { return (value == input ? null : value); }); // Delete entry - jQueryinput.parent().replaceWith(jQueryinput); - jQuery.removeData(input, PROP_NAME); - }, - - /* Initialise the current time for a time entry input field. - @param input (element) input field to update - @param time (Date) the new time (year/month/day ignored) or null for now - */ - _setTimeTimeEntry: function(input, time) { - var inst = jQuery.data(input, PROP_NAME); - if (inst) this._setTime(inst, time ? (typeof time == 'object' ? new Date(time.getTime()) : time) : null); - }, - - /* Retrieve the current time for a time entry input field. - @param input (element) input field to examine - @return (Date) current time (year/month/day zero) or null if none - */ - _getTimeTimeEntry: function(input) { - var inst = jQuery.data(input, PROP_NAME); - var currentTime = (inst ? this._extractTime(inst) : null); - return (!currentTime ? null : new Date(0, 0, 0, currentTime[0], currentTime[1], currentTime[2])); - }, - - /* Retrieve the millisecond offset for the current time. - @param input (element) input field to examine - @return (number) the time as milliseconds offset or zero if none - */ - _getOffsetTimeEntry: function(input) { - var inst = jQuery.data(input, PROP_NAME); - var currentTime = (inst ? this._extractTime(inst) : null); - return (!currentTime ? 0 : (currentTime[0] * 3600 + currentTime[1] * 60 + currentTime[2]) * 1000); - }, - - /* Initialise time entry. - @param target (element) the input field or (event) the focus event - */ - _doFocus: function(target) { - var input = (target.nodeName && target.nodeName.toLowerCase() == 'input' ? target : this); - if (jQuery.timeEntry._lastInput == input || jQuery.timeEntry._isDisabledTimeEntry(input)) { - jQuery.timeEntry._focussed = false; - return; - } - var inst = jQuery.data(input, PROP_NAME); - jQuery.timeEntry._focussed = true; - jQuery.timeEntry._lastInput = input; - jQuery.timeEntry._blurredInput = null; - jQuery.data(input, PROP_NAME, inst); - jQuery.timeEntry._parseTime(inst); - setTimeout(function() { jQuery.timeEntry._showField(inst); }, 10); - }, - - /* Note that the field has been exited. - @param event (event) the blur event - */ - _doBlur: function(event) { - jQuery.timeEntry._blurredInput = jQuery.timeEntry._lastInput; - jQuery.timeEntry._lastInput = null; - }, - - /* Select appropriate field portion on click, if already in the field. - @param event (event) the click event - */ - _doClick: function(event) { - var input = event.target; - var inst = jQuery.data(input, PROP_NAME); - if (!jQuery.timeEntry._focussed) { - var fieldSize = 3; - inst._field = 0; - if (input.selectionStart != null) { // Use input select range - for (var field = 0; field <= Math.max(1, inst._secondField, inst._ampmField); field++) { - var end = (field != inst._ampmField ? (field * fieldSize) + 2 : (inst._ampmField * fieldSize) + 2); - inst._field = field; - if (input.selectionStart < end) break; - } - } else if (input.createTextRange) { // Check against bounding boxes - var src = jQuery(event.srcElement); - var range = input.createTextRange(); - var convert = function(value) { - return {thin: 2, medium: 4, thick: 6}[value] || value; - }; - var offsetX = event.clientX + document.documentElement.scrollLeft - - (src.offset().left + parseInt(convert(src.css('border-left-width')), 10)) - - range.offsetLeft; // Position - left edge - alignment - for (var field = 0; field <= Math.max(1, inst._secondField, inst._ampmField); field++) { - var end = (field != inst._ampmField ? (field * fieldSize) + 2 : (inst._ampmField * fieldSize) + 2); - range.collapse(); - range.moveEnd('character', end); - inst._field = field; - if (offsetX < range.boundingWidth) break; // And compare - } - } - } - jQuery.data(input, PROP_NAME, inst); - jQuery.timeEntry._showField(inst); - jQuery.timeEntry._focussed = false; - }, - - /* Handle keystrokes in the field. - @param event (event) the keydown event - @return (boolean) true to continue, false to stop processing - */ - _doKeyDown: function(event) { - if (event.keyCode >= 48) return true; - var inst = jQuery.data(event.target, PROP_NAME); - - switch (event.keyCode) { - case 9: - var its = jQuery(':input'); - its.eq(its.index(this)+(event.shiftKey?-1:+1)).focus(); - break; - case 37: jQuery.timeEntry._changeField(inst, -1, false); break; // Previous field on left - case 38: jQuery.timeEntry._adjustField(inst, -1); break; // Increment time field on down - case 16: if(!event.shiftKey) jQuery.timeEntry._changeField(inst, +1, false); break; // Next field on right - case 39: jQuery.timeEntry._changeField(inst, +1, false); break; // Next field on right - case 40: jQuery.timeEntry._adjustField(inst, +1); break; // Decrement time field on up - case 32: case 46: jQuery.timeEntry._setValue(inst, ''); break; // Clear time on delete - } - return false; - }, - - /* Disallow unwanted characters. - @param event (event) the keypress event - @return (boolean) true to continue, false to stop processing - */ - _doKeyPress: function(event) { - var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode); - if (chr < ' ') return true; - var inst = jQuery.data(event.target, PROP_NAME); - jQuery.timeEntry._handleKeyPress(inst, chr); - return false; - }, - - /* Get a setting value, defaulting if necessary. - @param inst (object) the instance settings - @param name (string) the setting name - @return (any) the setting value - */ - _get: function(inst, name) { - return (inst.options[name] != null ? inst.options[name] : jQuery.timeEntry._defaults[name]); - }, - - /* Extract the time value from the input field, or default to now. - @param inst (object) the instance settings - */ - _parseTime: function(inst) { - var currentTime = this._extractTime(inst); - var showSeconds = this._get(inst, 'showSeconds'); - if (currentTime) { - inst._selectedHour = currentTime[0]; - inst._selectedMinute = currentTime[1]; - inst._selectedSecond = currentTime[2]; - } - else { - var now = this._constrainTime(inst); - inst._selectedHour = now[0]; - inst._selectedMinute = now[1]; - inst._selectedSecond = (showSeconds ? now[2] : 0); - } - inst._secondField = (showSeconds ? 2 : -1); - inst._ampmField = (this._get(inst, 'show24Hours') ? -1 : (showSeconds ? 3 : 2)); - inst._lastChr = ''; - inst._field = Math.max(0, Math.min(Math.max(1, inst._secondField, inst._ampmField), 0)); - if (inst.input.val() != '') this._showTime(inst); - }, - - /* Extract the time value from a string as an array of values, or default to null. - @param inst (object) the instance settings - @param value (string) the time value to parse - @return (number[3]) the time components (hours, minutes, seconds) - or null if no value - */ - _extractTime: function(inst, value) { - value = value || inst.input.val(); - var currentTime = value.split(':'); - var ampmNames = this._get(inst, 'ampmNames'); - var show24Hours = this._get(inst, 'show24Hours'); - if (currentTime.length >= 2) { - var isAM = !show24Hours && (value.indexOf(ampmNames[0]) > -1); - var isPM = !show24Hours && (value.indexOf(ampmNames[1]) > -1); - var hour = parseInt(currentTime[0], 10); - hour = (isNaN(hour) ? 0 : hour); - hour = ((isAM || isPM) && hour == 12 ? 0 : hour) + (isPM ? 12 : 0); - var minute = parseInt(currentTime[1], 10); - minute = (isNaN(minute) ? 0 : minute); - var second = (currentTime.length >= 3 ? - parseInt(currentTime[2], 10) : 0); - second = (isNaN(second) || !this._get(inst, 'showSeconds') ? 0 : second); - return this._constrainTime(inst, [hour, minute, second]); - } - return null; - }, - - /* Constrain the given/current time to the time steps. - @param inst (object) the instance settings - @param fields (number[3]) the current time components (hours, minutes, seconds) - @return (number[3]) the constrained time components (hours, minutes, seconds) - */ - _constrainTime: function(inst, fields) { - var specified = (fields != null); - if (!specified) { - var now = this._determineTime(inst, this._get(inst, 'defaultTime')) || new Date(); - fields = [now.getHours(), now.getMinutes(), now.getSeconds()]; - } - return fields; - }, - - /* Set the selected time into the input field. - @param inst (object) the instance settings - */ - _showTime: function(inst) { - var show24Hours = this._get(inst, 'show24Hours'); - var currentTime = (this._formatNumber(show24Hours ? inst._selectedHour : - ((inst._selectedHour + 11) % 12) + 1) + ':' + - this._formatNumber(inst._selectedMinute) + - (this._get(inst, 'showSeconds') ? ':' + - this._formatNumber(inst._selectedSecond) : '') + - (show24Hours ? '' : this._get(inst, 'ampmNames')[(inst._selectedHour < 12 ? 0 : 1)])); - this._setValue(inst, currentTime); - this._showField(inst); - }, - - /* Highlight the current time field. - @param inst (object) the instance settings - */ - _showField: function(inst) { - var input = inst.input[0]; - if (inst.input.is(':hidden') || jQuery.timeEntry._lastInput != input) return; - var fieldSize = 3; - var start = (inst._field == inst._ampmField ? (inst._ampmField * fieldSize) - 1 : (inst._field * fieldSize)); - var end = start + (inst._field == inst._ampmField ? 2 : 2); - if (input.setSelectionRange) { // Mozilla - input.setSelectionRange(start, end); - } - else if (input.createTextRange) { // IE - var range = input.createTextRange(); - range.moveStart('character', start); - range.moveEnd('character', end - inst.input.val().length); - range.select(); - } - if (!input.disabled) input.focus(); - }, - - /* Ensure displayed single number has a leading zero. - @param value (number) current value - @return (string) number with at least two digits - */ - _formatNumber: function(value) { - return (value < 10 ? '0' : '') + value; - }, - - /* Update the input field and notify listeners. - @param inst (object) the instance settings - @param value (string) the new value - */ - _setValue: function(inst, value) { - if (value != inst.input.val()) inst.input.val(value).trigger('change'); - }, - - /* Move to previous/next field, or out of field altogether if appropriate. - @param inst (object) the instance settings - @param offset (number) the direction of change (-1, +1) - @param moveOut (boolean) true if can move out of the field - @return (boolean) true if exitting the field, false if not - */ - _changeField: function(inst, offset, moveOut) { - var atFirstLast = (inst.input.val() == '' || inst._field == (offset == -1 ? 0 : Math.max(1, inst._secondField, inst._ampmField))); - if (!atFirstLast) inst._field += offset; - this._showField(inst); - inst._lastChr = ''; - jQuery.data(inst.input[0], PROP_NAME, inst); - return (atFirstLast && moveOut); - }, - - /* Update the current field in the direction indicated. - @param inst (object) the instance settings - @param offset (number) the amount to change by - */ - _adjustField: function(inst, offset) { - if (inst.input.val() == '') offset = 0; - this._setTime(inst, new Date(0, 0, 0, - inst._selectedHour + (inst._field == 0 ? offset : 0) + - (inst._field == inst._ampmField ? offset * 12 : 0), - inst._selectedMinute + (inst._field == 1 ? offset : 0), - inst._selectedSecond + (inst._field == inst._secondField ? offset : 0))); - }, - - /* Check against minimum/maximum and display time. - @param inst (object) the instance settings - @param time (Date) an actual time or - (number) offset in seconds from now or - (string) units and periods of offsets from now - */ - _setTime: function(inst, time) { - time = this._determineTime(inst, time); - var fields = this._constrainTime(inst, time ? - [time.getHours(), time.getMinutes(), time.getSeconds()] : null); - time = new Date(0, 0, 0, fields[0], fields[1], fields[2]); - // Normalise to base date - var time = this._normaliseTime(time); - var minTime = this._normaliseTime(this._determineTime(inst, this._get(inst, 'minTime'))); - var maxTime = this._normaliseTime(this._determineTime(inst, this._get(inst, 'maxTime'))); - // Ensure it is within the bounds set - time = (minTime && time < minTime ? minTime : - (maxTime && time > maxTime ? maxTime : time)); - inst._selectedHour = time.getHours(); - inst._selectedMinute = time.getMinutes(); - inst._selectedSecond = time.getSeconds(); - this._showTime(inst); - jQuery.data(inst.input[0], PROP_NAME, inst); - }, - - /* Normalise time object to a common date. - @param time (Date) the original time - @return (Date) the normalised time - */ - _normaliseTime: function(time) { - if (!time) return null; - time.setFullYear(1900); - time.setMonth(0); - time.setDate(0); - return time; - }, - - /* A time may be specified as an exact value or a relative one. - @param inst (object) the instance settings - @param setting (Date) an actual time or - (number) offset in seconds from now or - (string) units and periods of offsets from now - @return (Date) the calculated time - */ - _determineTime: function(inst, setting) { - var offsetNumeric = function(offset) { // E.g. +300, -2 - var time = new Date(); - time.setTime(time.getTime() + offset * 1000); - return time; - }; - var offsetString = function(offset) { // E.g. '+2m', '-4h', '+3h +30m' or '12:34:56PM' - var fields = jQuery.timeEntry._extractTime(inst, offset); // Actual time? - var time = new Date(); - var hour = (fields ? fields[0] : time.getHours()); - var minute = (fields ? fields[1] : time.getMinutes()); - var second = (fields ? fields[2] : time.getSeconds()); - if (!fields) { - var pattern = /([+-]?[0-9]+)\s*(s|S|m|M|h|H)?/g; - var matches = pattern.exec(offset); - while (matches) { - switch (matches[2] || 's') { - case 's' : case 'S' : second += parseInt(matches[1], 10); break; - case 'm' : case 'M' : minute += parseInt(matches[1], 10); break; - case 'h' : case 'H' : hour += parseInt(matches[1], 10); break; - } - matches = pattern.exec(offset); - } - } - time = new Date(0, 0, 10, hour, minute, second, 0); - if (/^!/.test(offset)) { // No wrapping - if (time.getDate() > 10) - time = new Date(0, 0, 10, 23, 59, 59); - else if (time.getDate() < 10) - time = new Date(0, 0, 10, 0, 0, 0); - } - return time; - }; - return (setting ? (typeof setting == 'string' ? offsetString(setting) : - (typeof setting == 'number' ? offsetNumeric(setting) : setting)) : null); - }, - - /* Update time based on keystroke entered. - @param inst (object) the instance settings - @param chr (ch) the new character - */ - _handleKeyPress: function(inst, chr) { - if (chr == ':') this._changeField(inst, +1, false); - else if (chr >= '0' && chr <= '9') { // Allow direct entry of time - var key = parseInt(chr, 10); - var value = parseInt(inst._lastChr + chr, 10); - var show24Hours = this._get(inst, 'show24Hours'); - var hour = (inst._field != 0 ? inst._selectedHour : - (show24Hours ? (value < 24 ? value : key) : - (value >= 1 && value <= 12 ? value : - (key > 0 ? key : inst._selectedHour)) % 12 + - (inst._selectedHour >= 12 ? 12 : 0))); - var minute = (inst._field != 1 ? inst._selectedMinute : - (value < 60 ? value : key)); - var second = (inst._field != inst._secondField ? inst._selectedSecond : - (value < 60 ? value : key)); - var fields = this._constrainTime(inst, [hour, minute, second]); - this._setTime(inst, new Date(0, 0, 0, fields[0], fields[1], fields[2])); - inst._lastChr = chr; - } - else if (!this._get(inst, 'show24Hours')) { // Set am/pm based on first char of names - chr = chr.toLowerCase(); - var ampmNames = this._get(inst, 'ampmNames'); - if ((chr == ampmNames[0].substring(0, 1).toLowerCase() && inst._selectedHour >= 12) || - (chr == ampmNames[1].substring(0, 1).toLowerCase() && inst._selectedHour < 12)) { - var saveField = inst._field; - inst._field = inst._ampmField; - this._adjustField(inst, +1); - inst._field = saveField; - this._showField(inst); - } - } - } - }); - - /* jQuery extend now ignores nulls! - @param target (object) the object to update - @param props (object) the new settings - @return (object) the updated object - */ - function extendRemove(target, props) { - jQuery.extend(target, props); - for (var name in props) if (props[name] == null) target[name] = null; - return target; - } - - // Commands that don't return a jQuery object - var getters = ['getOffset', 'getTime', 'isDisabled']; - - /* Attach the time entry functionality to a jQuery selection. - @param command (string) the command to run (optional, default 'attach') - @param options (object) the new settings to use for these countdown instances (optional) - @return (jQuery) for chaining further calls - */ - jQuery.fn.timeEntry = function(options) { - var otherArgs = Array.prototype.slice.call(arguments, 1); - if (typeof options == 'string' && jQuery.inArray(options, getters) > -1) { - return jQuery.timeEntry['_' + options + 'TimeEntry'].apply(jQuery.timeEntry, [this[0]].concat(otherArgs)); - } - return this.each(function() { - var nodeName = this.nodeName.toLowerCase(); - if (nodeName == 'input') { - if (typeof options == 'string') - jQuery.timeEntry['_' + options + 'TimeEntry'].apply(jQuery.timeEntry, [this].concat(otherArgs)); - else { - // Check for settings on the control itself - var inlineSettings = (jQuery.fn.metadata ? jQuery(this).metadata() : {}); - jQuery.timeEntry._connectTimeEntry(this, jQuery.extend(inlineSettings, options)); - } - } - }); - }; - - /* Initialise the time entry functionality. */ - jQuery.timeEntry = new TimeEntry(); // Singleton instance - -})(jQuery); - diff --git a/applications/admin/views/appadmin.html b/applications/admin/views/appadmin.html index 1d967c2f..541a18bb 100644 --- a/applications/admin/views/appadmin.html +++ b/applications/admin/views/appadmin.html @@ -10,8 +10,9 @@ //--> {{if request.function=='index':}} -

{{=T("Available databases and tables")}}

+

{{=T("Available Databases and Tables")}}

{{if not databases:}}{{=T("No databases in this application")}}{{pass}} + {{for db in sorted(databases):}} {{for table in databases[db].tables:}} {{qry='%s.%s.id>0'%(db,table)}} @@ -28,20 +29,24 @@ {{qry=''}} {{pass}} {{pass}} -

- {{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}} -

- [ {{=A(str(T('insert new'))+' '+table,_href=URL('insert',args=[db,table]))}} ] -

+ + + + {{pass}} +
+ {{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}} + + {{=A(str(T('New Record')),_href=URL('insert',args=[db,table]),_class="btn")}} +
{{pass}} {{elif request.function=='select':}} -

{{=XML(str(T("database %s select"))%A(request.args[0],_href=URL('index'))) }} +

{{=XML(str(T("Database %s select"))%A(request.args[0],_href=URL('index'))) }}

- {{if table:}} - [ {{=A(str(T('insert new %s'))%table,_href=URL('insert',args=[request.args[0],table]))}} ]

-

{{=T("Rows in table")}}


+ {{if table:}} + {{=A(str(T('New Record')),_href=URL('insert',args=[request.args[0],table]),_class="btn")}}

+

{{=T("Rows in Table")}}


{{else:}}

{{=T("Rows selected")}}


{{pass}} @@ -51,8 +56,8 @@ {{=T('"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN')}}



{{=T("%s selected", nrows)}}

- {{if start>0:}}[ {{=A(T('previous 100 rows'),_href=URL('select',args=request.args[0],vars=dict(start=start-100)))}} ]{{pass}} - {{if stop0:}}{{=A(T('previous 100 rows'),_href=URL('select',args=request.args[0],vars=dict(start=start-100)),_class="btn")}}{{pass}} + {{if stop {{linkto=URL('update',args=request.args[0])}} @@ -61,35 +66,35 @@ {{pass}}

{{=T("Import/Export")}}


- [ {{=T("export as csv file")}} ] + {{=T("export as csv file")}} {{=formcsv or ''}} {{elif request.function=='insert':}} -

{{=T("database")}} {{=A(request.args[0],_href=URL('index'))}} +

{{=T("Database")}} {{=A(request.args[0],_href=URL('index'))}} {{if hasattr(table,'_primarykey'):}} {{fieldname=table._primarykey[0]}} {{dbname=request.args[0]}} {{tablename=request.args[1]}} {{cond = table[fieldname].type in ['string','text'] and '!=""' or '>0'}} - {{=T("table")}} {{=A(tablename,_href=URL('select',args=dbname,vars=dict(query='%s.%s.%s%s'%(dbname,tablename,fieldname,cond))))}} + {{=T("Table")}} {{=A(tablename,_href=URL('select',args=dbname,vars=dict(query='%s.%s.%s%s'%(dbname,tablename,fieldname,cond))))}} {{else:}} - {{=T("table")}} {{=A(request.args[1],_href=URL('select',args=request.args[0],vars=dict(query='%s.%s.id>0'%tuple(request.args[:2]))))}} + {{=T("Table")}} {{=A(request.args[1],_href=URL('select',args=request.args[0],vars=dict(query='%s.%s.id>0'%tuple(request.args[:2]))))}} {{pass}}

{{=T("New Record")}}


{{=form}} {{elif request.function=='update':}} -

{{=T("database")}} {{=A(request.args[0],_href=URL('index'))}} +

{{=T("Database")}} {{=A(request.args[0],_href=URL('index'))}} {{if hasattr(table,'_primarykey'):}} {{fieldname=request.vars.keys()[0]}} {{dbname=request.args[0]}} {{tablename=request.args[1]}} {{cond = table[fieldname].type in ['string','text'] and '!=""' or '>0'}} - {{=T("table")}} {{=A(tablename,_href=URL('select',args=dbname,vars=dict(query='%s.%s.%s%s'%(dbname,tablename,fieldname,cond))))}} - {{=T("record")}} {{=A('%s=%s'%request.vars.items()[0],_href=URL('update',args=request.args[:2],vars=request.vars))}} + {{=T("Table")}} {{=A(tablename,_href=URL('select',args=dbname,vars=dict(query='%s.%s.%s%s'%(dbname,tablename,fieldname,cond))))}} + {{=T("Record")}} {{=A('%s=%s'%request.vars.items()[0],_href=URL('update',args=request.args[:2],vars=request.vars))}} {{else:}} - {{=T("table")}} {{=A(request.args[1],_href=URL('select',args=request.args[0],vars=dict(query='%s.%s.id>0'%tuple(request.args[:2]))))}} - {{=T("record id")}} {{=A(request.args[2],_href=URL('update',args=request.args[:3]))}} + {{=T("Table")}} {{=A(request.args[1],_href=URL('select',args=request.args[0],vars=dict(query='%s.%s.id>0'%tuple(request.args[:2]))))}} + {{=T("Record id")}} {{=A(request.args[2],_href=URL('update',args=request.args[:3]))}} {{pass}}

{{=T("Edit current record")}}



{{=form}} diff --git a/applications/admin/views/default/ticket.html b/applications/admin/views/default/ticket.html index 026b00bd..233305e6 100644 --- a/applications/admin/views/default/ticket.html +++ b/applications/admin/views/default/ticket.html @@ -13,12 +13,16 @@ web2py™ {{=myversion}} + {{if snapshot:}} Python {{=snapshot.get('pyver','')}} + {{pass}} + +{{if traceback or code or layer:}}

{{=T('Traceback')}}

{{=traceback}} @@ -130,4 +134,6 @@

In file: {{=layer}}

{{=CODE(code.replace('\r',''),language='python',link='/examples/global/vars/')}}
- +{{else:}} +

{{=T('Ticket Missing')}}

+{{pass}} diff --git a/applications/examples/controllers/appadmin.py b/applications/examples/controllers/appadmin.py index 126200b9..fa264bae 100644 --- a/applications/examples/controllers/appadmin.py +++ b/applications/examples/controllers/appadmin.py @@ -11,6 +11,8 @@ import copy import gluon.contenttype import gluon.fileutils +response.subtitle = 'Database Administration (appadmin)' + # ## critical --- make a copy of the environment global_env = copy.copy(globals()) diff --git a/applications/examples/static/images/gluon.png b/applications/examples/static/images/gluon.png deleted file mode 100644 index 923fd182d915648d3e5262dae3b1df5eeb978d00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58169 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

A 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 diff --git a/applications/examples/static/images/netdow1.png b/applications/examples/static/images/netdow1.png deleted file mode 100644 index 6e9710eea0aca59f0eae8571635a5187c17837ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3883 zcmV+`57h99P)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000D5NkleR6u^J8yXwlgSl7ZD-8E>09NLNo%0@^ay+kO51_~CWrB$qT z6Jr}nAcrJPTf7u{DUw_YCZ?rbf+k`-jX9;%3$zU1#S{53cEI zch>wlc*%qBFyFlI&F_2feeZiCSeC_pii3TYmjL??-~t#O9eq(d{lEvnAwUKG0ImTK zD=nIsnAie%0eKq;1%ttNPMkP_&*!61C~)`g-R?Vg?wns+Tl*6DdQT5Lh13BekS>|~ zrmCvy;@H?2ZEbC=uCAge3W6Ze+1bg_qer=Z{rXqoaJUJ$46Hm4z!yNMrl#glb#*ms zYila-6R=QMS9fuIe4LGq4U);^jz#%=p3Tio`uqFw`~9KYw{Kg(nP&x<=;-J;Gcq!Q z+wBIxG)-}Kc6RvY&6}&2E?pv*%klW}c9sv-AA$@G!D0lgs6{lm&st#zsU@L{(K*R#x_mohXWkqR52{7ybr1o+b%h4u|9X z(9jUcWRmsu^&KxINy6!LVi?9#C6A&g_+26GiqZn4_6os=M~)mJo6VBVX3HAY zb)DC)OalT4#Yqe9UpZD*Kby@G2n0|RB?$bw7r>i=Kmb)$(RJN^Yqf3=g#Vr`%U0hs zP20k^8{jSA)oeD4Rly(t9&u~;+YqL`zF`<>ng;L*paZ{^12_qU`uh4#b$55Ow6s(i zpxy(Hk`R~{g+igMYC4@}aBz@FByw_UYN{5f1%BQQ5bEpeJLUKLnV+BEJG&Y@;B*u{ zV1Z%pflMYtCX?a7fddQ-3>=@FoMbn^dx1dURBLN1%gf8Q-@K8kW^%O#s-4j21lLZ0 zV+#goCIheJ`KV>{f9n&81T8Hs96o&bcr+Rv0)E&A2=(;zkWQy<-3V~*4KKBl$kkPI z3!=)g6$T5?P0&n+>fy6y7m}1KYeSZ0g25osXf#v`@VeLQMUte7aZjaEeA?n?qsGf* z!BqsH2w*Yf(i!t+NG6iDHdIxmxw#qOU}*?UP1DeIy>j9KiTE;S4>}?5W0I<(2P{6e zbWXchi2w7DN`0nfJxNxp6ksNqOup;!c*y7Td*)x_L5xs`lbqq_7s1K<7@ToRBx14B zGhbHRZa1YJvC*Xt!7k0VLa zt>U%5qYg~W&CLnx>+7Met}bL*u6QE0D_k@h-Kwz;`}Wf1a?#Y(L?jX+91h>w-u-TX z1>kZd64_J~<@5ITc03*rLTSB!PRZqROixb}kH^0UCV-gTU9bY2OQlkOrc$W^pzRsj tHd{vl3E)TIM%jks<&Virfc=zz2LNp{LD7(j^XmWr002ovPDHLkV1ia|O3MHM diff --git a/applications/examples/static/images/netdow2.png b/applications/examples/static/images/netdow2.png deleted file mode 100644 index de078ebfd22e35e41fa2174889c8539f89d78a31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3888 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

-P`G=i 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 diff --git a/applications/examples/static/images/tipDownloads.png b/applications/examples/static/images/tipDownloads.png deleted file mode 100644 index 38d12e1eb7c03e82e0b0b3a0dab5710469239a59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5783 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 J8^E?v{{yn=;IaS! diff --git a/applications/examples/static/images/tipDownloads2.png b/applications/examples/static/images/tipDownloads2.png deleted file mode 100644 index 2d21d43bdbfbe63ca5de5ce3c11e3132a26487da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6085 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 DUci2b diff --git a/applications/examples/static/images/web2py_logo_light.png b/applications/examples/static/images/web2py_logo_light.png deleted file mode 100644 index cf41af38fadc95547c9d170ffbeffe2fcfede0d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7786 zcmcI}by!qe+xO5dEg@aP5JMwFH`1lF$iNViPS7BT64IRmN=r%$NGKrPT@HFE>6C_d zJm6b94AR#{H z3ViI2gXwVL$`4HlF)e`5J_7Shr{8cKwk8Ny6g2W;ozCS+^x z0f7qnxOoC(6?{Bx?OdP;HVD+w*g25H2ZI{>>6zI1 zx!6hDb129Y%ld#Z%x+MGEt`*p=#Z1XFK+>%)GUEIQKvzGiOLNQ3HDzfE_=P0%ntP`GXut@Q^m8 zl;%-WX)oDB!xYa#?C->Ql3}xn%yu%t(a$@+F3)1I)^NEXx5xaCb@m324-R{(a+`~b z9lad9A5+B!J+hWr=-Ha7LZ6-n^_;dowr~*|fd1ql{@^-;HL7UFmjZH+X&X?p#$USC z_r01GvvhE48Fvzw3b%bwI;Nti7gAH6Z6k2^vATBQD$3NV`h&~X3Y9^e(9lTB0HeuU zwvy!jG#P_j7z5%~e?{!{X8l{ydMgiUr>V0~ ztSDrf&`35iOO+54l?~YY#_t_?5$00mPqXh(rahDmZBk4cSX(c}*a0#)-$30SOjvAr zKdY!>Ma)^a2n-NQ#>Fl^pLnOjx>$`o%xId2bs9ZmFvI#Z(6J?urgVy(6o*Ex->{LQ z^Xr3-)Y1H;65SBnwfVBji_3fDOrK`FP?=%Ac#q!t&Y=fV2j2RJ^lHf8Hsu*@rqxgH z;Y*&vVx}1d73O343N3ED_*MA2r&_$*Pp3ew-zScC5A&2!IH@6Dq09B!HxSe18d9C2 zx@p!;ub0!A!lX)kuvE2o1|{oo>6x1HW+5(>UwVaKoD)^ zEUt&`2q-oJUWU3v-q`0~%v)>%4tFO5+@wwUQg9ZK0&gkYq}c!h9R#u+dov~x{Q?}E zrL-wq>_jt9nOA{NdFRWW8p&UcbrwoBU!w;|B6Fa|h}>XaRTiv?I!k%KhFwYX+aH`o znRIggBJ&=b&)cr$pPyBp`nTOaju4$w>e%1saU2;&*`V7UPaA<*joDbKpGM0rf(%H$ zc&fQrYjDJ2jfcG}q&Zj4Nmz`J?Prv`n9WDOfL$E#`LwkQlK3c5cy>>&aC$VaPVHGE zP{ti1Pw_qZ3u|KMfw@lnE&#W}e3*`ca9{_Mi|Wp*+CtdsU1NGtB#`4XcWA!i&`c^C z=SuMh7fx(TaC=mcj3U|dSpTN;p^or~S<)_M5rP1sv)YYY`=&CJyry=hG#Pxgry2$~DQCj!R+Aa{Hi&lvY9 zgkunk>UF*;M&`NZ*`TGUKT9E^(8uy0Q z#5y83g7)ygY07Bgv*Y*noqEjga(09#4BMz(EGP!*E+C%}2T<@*HfAX&AGc%O(oA(@ zW%@2lF3*Hio0zu)WC4RX>!K_rSy!a{KkoEY0(PYuMA@ksX#HwGoHs^oK#4!FDZr@XOSS-O8PXZ+@GDO{Y5xwU@D`ZD*s^t84wK z-I=v{$(dLVA$WPi8e4<}71P1k$wpe|LGdy(X1u#gZAahXM@Q{PlklFsNsD`h_wVz+ zUOzvda2#Qt6%jdc&7Wf;aNvwuwpi{^m((Nhr4uF&xXVk;$FzXl3I7<#qnTL&F7R8{o=h^QBvdOGp(5s7tL5V(O{N({-;oTl5Vgham6PA1IZ` z`ty5sOd^#h^HWa73GO0wYo{h`ADMl><&gwRPwJLg-va-r5kmUiD%+A zV{TAl*HIgh;eFSvG`XKY#i+?+{&ArRPdL?T$w?Aw_$c#wo;6kiG5)_18Y}tAHp8mPyA!zH4oI&qfTt7vjzXBlXlng2Vfyg z)A5}B@u~AK_ROASnO9C|_xvSts!LClD(6Uoc*4``v zcjpf_YBVEh5xSe)3rN2=kLatd@5cpi`itEGakRBlyE#%)2(hn0;|VaYxMJ5CUy7fz z4>OeOzA$uI2{X3c+ZgA0OZ1ehe(CO0I#1vucd5~9r!>1hf9A+dOBJd*9vH3*xo1g9 zHeQ!x6?ebRKw}7qbJ;3-*lm3C{s||eb5@0B$JV9jurIA=@~pXc!g4aYFvlfzVfXTj zQwg$&heM{cMQE> zA|V{F(%v@ibviXOapwa{P3$&W7n6SC*)r3jIUK(mzdZ7D!<+MYfFOiM0|)C+bR6G2 zUp@HKq?+pcL5_~CMo#WMvT-GMf*Xpn!bxeht^x%jlZfkKvc9+}t5cN-(c$Ewe9of? zhG$@;XmoBeg>x2OL4`wngIIqf>u5$h7WNw{oV|iabD_LfXo8!>2g39mYaiPgF@byz z*f}7NZ@cteVHN=NCTB!ti z0Gwq|JSAx9r#IV<^GiBB2vm&Xd?le1bQ*B$k92h&o3$a4239ECag=bOvZ64*lpV_=?=`k~VBz(e5uWgky6F9g^m` z#&HJAXe9G!zC4%R02Uq+Eg)mZ<>z-4!?qc^Zs%1U1vAxZP_e-8YydGB9@U9-7H?zH z&-utt7|bYs9t%Ng1~uAeNWgFfHyRa!`&QJKz&qoScg++wbiy;01YU`6ge6Ea@$hh! zTe6&8%t+?uWcXUspv*=V$Jp!@0uRH|094ZP@yVS>;1R)z<6G9jwTYw{jiSy+@2m%nr}2@=VjH({>X^x4@?v)a#^W!I455kln?`+_kIX^ z=dAg4P(%RNqoZ$D`KvoC1KE-00&oF2X|a1bce%HKDLogda6jLxpRSs)*t6QfR7VWJ zyIC`=A9qXkE`=b@=>cr^aR{DZ$oxRvBhb(MCo9glqbQ!uCj?h4R9KQoHZs`-WDw3- z)*a|#9Pei!_DAXn{YKSrt^h_vcwa1JS4AgvXbi2a4m-HZ#gvr{*ZgB9KEMV%UrR0` z7-N$LZT?1qN=s$nssU>{baI0lwzdnFJn$LV*(6i^@E4ZI~)|>5`4^M~0fUQV>c4(Y|D@d~v4i*XMyo4A_Xx#-zli;#(@Xn3 z^yMz$9M4)%feIsaZF)LCQqI$DGvFSUI`#8JN6K(9l)_vbg-;TX11F?#Ph)VPjwxz0 z{ciV#IX|lkBP9glsqj`NBL3|}E#ovWb6B3J!#kLOGDb#4o#h}&=&U+m>nS+{QW7vFnQYf&+EH`%B-p<`B{T7RNqHu!N_fe7IX zp&u$Yc*>KS1595=`$WfHVE=5i!Mn+v?#NAW3~5P_4`i(VsHZklLHwW>U~LZxB2o%6 z`o$qzBMs3?f9T{Gqkcaj&4zQhb&>3fsG=#UEI#3La+bI?I^IwtCRm6+U6^n#I@p2o zC!x^w>u>P7^)N|gS^HO)#CgGM5dltx$ujb?o9LsI{MQ-2m(1^`_Y@C}<+Q2n9}D#u zRGSHsk>}==L@Ts9uE!Qv&Vr?PUbk(1tOp8LC1*x$dgf4!hMHR|VS7K~B5bs8iOmqi zzP{hnL$P|R1?Dd;roc}PPfu|^r(JgJ!(Zg%lK2qKoA$?8o3H(akv?(0vDvxgyiz0W z_fu|jt|G<I9umLmyF&hN$}HyhRpu(EnIK6`)XwDZq4%?5WtkIb^??NrN)@ps?fK zHdht}w}@_X-H3UrOoMaR^_jKzH~LrKFYBkxQly9w(v8t>wxF zQeyonMl>X^)t!CL2G3?^;l|V{cE*GFa}Q*{bC#{GOcQsNSpP0PW@tJq_5@G zjA}LIn`wbOoe?&oL+^>e$D|RErqBnep4db=^bLkpTKF4)X07+K%xWU&Wbot{j>xM@ zsnHvlz8bAH`)9o9Smt+2pIaFjY)NIhHO%OK@}krg9nILCi71m?h_C`s(+sO+Seoo) z&98W)z}M$+HeyFU!(2U@k|0&~9npm6uJmUTg_Bpa20z8TWj$|O7>CvtS_FA%aM`t# zoPB(r2e@v}_4S`syCqTg@LM)y^Os)1j4w~rYt6kEGqKXKOi}4jNH3ZNCwkO9K7b@c z%j*t9Ml9!BnW*%n#-t%zSC+n$U^(BsUm7v&Z zX1abt{++?ze&NlTyfgd>Ey?TL_S>!7!1~s@<0NT*86?9icH)xgIMi&5%X+@Q*Up8W z??kVTqJf)umV`I7a81iUoGT#W; z(y+Bieg*r%s8Sw;J+^4dN$oTN(b1mZ8;7KZ?#}96b38|88V(jZ6F)?)Fb`8$uC;1 zZJ$=aN18p_Lg=TkKnI3!z`J%bKXIAxm6k6XZDj}IGLg0oKD{!Q91flIQ9TBOYmuRH zEXoX7u^0A?2yIOpcZ#fnTEtuL6Ckq^o$l#5)sF4Vb+40&V)pXEx#qNW z-OD>&Rrg{x5hN9y>|I5L;o|BSZR&}&SPuCY^ufQt3j9st-KFfy(OW~j3Zb(%eRZ7{ z0jl}J&2bI15t1OX$X@}Wrdm)s zFjcapJ%A_a`@TfPb;}7w&O{!j@XOu-qp`g(n>{T4KNzwtV%|Z@Tq^3-U51dCznELk zM^7}$$Y$P8FNzsrFYxvN$MwESSvsCvQ022n|8%5hc5yCSInEJ3or<1cdWxpQP#3(c)y|Wj0a;LY3`6ol>mL zH=kEiO7rXG-zS4Z(p$r*Weh~U==z$&4daClm^8CabisOwR2T1lAi?f{>}>2hp`XN< zloBxSg#wM|Tzv~ocQ<~24IjI~uPB11-ffEdr8vaG)zrjakLKzcl9iy&{x}O0;q(Ia zncp3eyOq@)ak;nplI`ijN>?rVbUaONL(+87YB+P)yy=hbfbZwn)3U7~dex+h> zYVXYgDD3lQN~t#Jat5Wm2_2r=sS9`d2|2ot z2|{Ae0%y~ED90`FNQuDM{@Hd1Ou4HsSXgQOenwhOOhq1j!B{_y$+c^kElY)l74U1n zd?os40cenCC>^M%SMFP7CfnP18_ckYo0F6}P4^+mQ7(v3p7`-^+m z_8BI|&)`dkR%j)9;6rNU%U>r_N;=xL1{-PO3&L+RncVI#OHZ-F9R46rGj<@_u8YYR&!W+%dWQVF_G zcK&TujrzJVR!w#?IWxcJ6XBaeP|+_P_K!v%X|0MiY{@F}bMxmuulSxX;arFdeJPZw z8z5Ejb^s{FP%plfgbqhMt3hOlSVtKZ z(!hTyr}p71mLP@pKdp$DK5Fl%HH2V;tyhcy3wSLrs*Eo@ijNYB)Jbnaeahy7<8WMa z*`h3gcu_&jcA7_vUa`|err9x0GF1f}UrO~Qn|w92O-$bIRD zOdG;QtIy!?S(MbP-C^0Y`r@3tu7ev>aaJ_OWP^vREW28*f}m6Ec3EVF`L3 zPNr}|(;d@b=q2WVUTJ?`84e~KV1mq;+&hsFC$RSsoJ_2V}!ke z0LNP~L|bjgq2E!&HNt?EDAk10GbK_X{%LQK!;W&=x0$bm6vB@vb&ZQo?Bc?@p80sl zE7Is>u-{qKq1F!$eD}uI{H)2UvI!Zms6ykY>e3O#$mUP^kF0yS&X|Pf>N}!@8NG=ZH8Dt{LYA0?X(Fc4m0^icGD^k z8Zpp3Crf0aYgE17yto+7h2V@%=K+JT%Q6)$syf3_uVKMEs=N_RYC&qa6p$y=moM>R dM(~!v`ZfQ&QsD6>=9doOp_-m*rSj94{{%time%'}); - } - - - // init contact form validation and AJAX handling - if ($("#contactform").length > 0) { - $("#contactform").validate({ rules: { name: "required", - email: { required: true, email: true }, - message: "required"}, - messages: { name: "This field is required.", - email: { required: "This field is required.", - email: "Please enter a valied email address."}, - message: "This field is required."}, - submitHandler: function(form) { $(form).ajaxSubmit({dataType: 'json', success: contactFormResponse}); } - }); - } -}); - -// handle newsletter subscribe AJAX response -function newsletterResponse(response) { - if (response.responseStatus == 'err') { - if (response.responseMsg == 'ajax') { - alert('Error - this script can only be invoked via an AJAX call.'); - } else if (response.responseMsg == 'fileopen') { - alert('Error opening $emailsFile. Please refer to documentation for help.'); - } else if (response.responseMsg == 'email') { - alert('Please enter a valid email address.'); - } else if (response.responseMsg == 'duplicate') { - alert('You are already subscribed to our newsletter.'); - } else if (response.responseMsg == 'filewrite') { - alert('Error writing to $emailsFile. Please refer to documentation for help.'); - } else { - alert('Undocumented error. Please refresh the page and try again.'); - } - } else if (response.responseStatus == 'ok') { - alert('Thank you for subscribing to our newsletter! We will not abuse your address.'); - } else { - alert('Undocumented error. Please refresh the page and try again.'); - } -} // newsletterResponse - -// handle contact form AJAX response -function contactFormResponse(response) { - if (response.responseStatus == 'err') { - if (response.responseMsg == 'ajax') { - alert('Error - this script can only be invoked via an AJAX call.'); - } else if (response.responseMsg == 'notsent') { - alert('We are having some mail server issues. Please refresh the page or try again later.'); - } else { - alert('Undocumented error. Please refresh the page and try again.'); - } - } else if (response.responseStatus == 'ok') { - alert('Thank you for contacting us! We\'ll get back to you ASAP.'); - } else { - alert('Undocumented error. Please refresh the page and try again.'); - } -} // contactFormResponse diff --git a/applications/examples/static/js/jquery-1.5-min.js b/applications/examples/static/js/jquery-1.5-min.js deleted file mode 100644 index 761a1e95..00000000 --- a/applications/examples/static/js/jquery-1.5-min.js +++ /dev/null @@ -1,16 +0,0 @@ -/*! - * jQuery JavaScript Library v1.5.1 - * http://jquery.com/ - * - * Copyright 2011, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2011, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Wed Feb 23 13:55:29 2011 -0500 - */ -(function(a,b){function cg(a){return d.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cd(a){if(!bZ[a]){var b=d("<"+a+">").appendTo("body"),c=b.css("display");b.remove();if(c==="none"||c==="")c="block";bZ[a]=c}return bZ[a]}function cc(a,b){var c={};d.each(cb.concat.apply([],cb.slice(0,b)),function(){c[this]=a});return c}function bY(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function bX(){try{return new a.XMLHttpRequest}catch(b){}}function bW(){d(a).unload(function(){for(var a in bU)bU[a](0,1)})}function bQ(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var e=a.dataTypes,f={},g,h,i=e.length,j,k=e[0],l,m,n,o,p;for(g=1;g=0===c})}function N(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function F(a,b){return(a&&a!=="*"?a+".":"")+b.replace(r,"`").replace(s,"&")}function E(a){var b,c,e,f,g,h,i,j,k,l,m,n,o,q=[],r=[],s=d._data(this,"events");if(a.liveFired!==this&&s&&s.live&&!a.target.disabled&&(!a.button||a.type!=="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var t=s.live.slice(0);for(i=0;ic)break;a.currentTarget=f.elem,a.data=f.handleObj.data,a.handleObj=f.handleObj,o=f.handleObj.origHandler.apply(f.elem,arguments);if(o===!1||a.isPropagationStopped()){c=f.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function C(a,c,e){var f=d.extend({},e[0]);f.type=a,f.originalEvent={},f.liveFired=b,d.event.handle.call(c,f),f.isDefaultPrevented()&&e[0].preventDefault()}function w(){return!0}function v(){return!1}function g(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function f(a,c,f){if(f===b&&a.nodeType===1){f=a.getAttribute("data-"+c);if(typeof f==="string"){try{f=f==="true"?!0:f==="false"?!1:f==="null"?null:d.isNaN(f)?e.test(f)?d.parseJSON(f):f:parseFloat(f)}catch(g){}d.data(a,c,f)}else f=b}return f}var c=a.document,d=function(){function I(){if(!d.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(I,1);return}d.ready()}}var d=function(a,b){return new d.fn.init(a,b,g)},e=a.jQuery,f=a.$,g,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,i=/\S/,j=/^\s+/,k=/\s+$/,l=/\d/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=navigator.userAgent,w,x=!1,y,z="then done fail isResolved isRejected promise".split(" "),A,B=Object.prototype.toString,C=Object.prototype.hasOwnProperty,D=Array.prototype.push,E=Array.prototype.slice,F=String.prototype.trim,G=Array.prototype.indexOf,H={};d.fn=d.prototype={constructor:d,init:function(a,e,f){var g,i,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!e&&c.body){this.context=c,this[0]=c.body,this.selector="body",this.length=1;return this}if(typeof a==="string"){g=h.exec(a);if(!g||!g[1]&&e)return!e||e.jquery?(e||f).find(a):this.constructor(e).find(a);if(g[1]){e=e instanceof d?e[0]:e,k=e?e.ownerDocument||e:c,j=m.exec(a),j?d.isPlainObject(e)?(a=[c.createElement(j[1])],d.fn.attr.call(a,e,!0)):a=[k.createElement(j[1])]:(j=d.buildFragment([g[1]],[k]),a=(j.cacheable?d.clone(j.fragment):j.fragment).childNodes);return d.merge(this,a)}i=c.getElementById(g[2]);if(i&&i.parentNode){if(i.id!==g[2])return f.find(a);this.length=1,this[0]=i}this.context=c,this.selector=a;return this}if(d.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return d.makeArray(a,this)},selector:"",jquery:"1.5.1",length:0,size:function(){return this.length},toArray:function(){return E.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var e=this.constructor();d.isArray(a)?D.apply(e,a):d.merge(e,a),e.prevObject=this,e.context=this.context,b==="find"?e.selector=this.selector+(this.selector?" ":"")+c:b&&(e.selector=this.selector+"."+b+"("+c+")");return e},each:function(a,b){return d.each(this,a,b)},ready:function(a){d.bindReady(),y.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(E.apply(this,arguments),"slice",E.call(arguments).join(","))},map:function(a){return this.pushStack(d.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:D,sort:[].sort,splice:[].splice},d.fn.init.prototype=d.fn,d.extend=d.fn.extend=function(){var a,c,e,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i==="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!=="object"&&!d.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;y.resolveWith(c,[d]),d.fn.trigger&&d(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!x){x=!0;if(c.readyState==="complete")return setTimeout(d.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",A,!1),a.addEventListener("load",d.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",A),a.attachEvent("onload",d.ready);var b=!1;try{b=a.frameElement==null}catch(e){}c.documentElement.doScroll&&b&&I()}}},isFunction:function(a){return d.type(a)==="function"},isArray:Array.isArray||function(a){return d.type(a)==="array"},isWindow:function(a){return a&&typeof a==="object"&&"setInterval"in a},isNaN:function(a){return a==null||!l.test(a)||isNaN(a)},type:function(a){return a==null?String(a):H[B.call(a)]||"object"},isPlainObject:function(a){if(!a||d.type(a)!=="object"||a.nodeType||d.isWindow(a))return!1;if(a.constructor&&!C.call(a,"constructor")&&!C.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a){}return c===b||C.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!=="string"||!b)return null;b=d.trim(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return a.JSON&&a.JSON.parse?a.JSON.parse(b):(new Function("return "+b))();d.error("Invalid JSON: "+b)},parseXML:function(b,c,e){a.DOMParser?(e=new DOMParser,c=e.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),e=c.documentElement,(!e||!e.nodeName||e.nodeName==="parsererror")&&d.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(a){if(a&&i.test(a)){var b=c.head||c.getElementsByTagName("head")[0]||c.documentElement,e=c.createElement("script");d.support.scriptEval()?e.appendChild(c.createTextNode(a)):e.text=a,b.insertBefore(e,b.firstChild),b.removeChild(e)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,e){var f,g=0,h=a.length,i=h===b||d.isFunction(a);if(e){if(i){for(f in a)if(c.apply(a[f],e)===!1)break}else for(;g1){var f=E.call(arguments,0),g=b,h=function(a){return function(b){f[a]=arguments.length>1?E.call(arguments,0):b,--g||c.resolveWith(e,f)}};while(b--)a=f[b],a&&d.isFunction(a.promise)?a.promise().then(h(b),c.reject):--g;g||c.resolveWith(e,f)}else c!==a&&c.resolve(a);return e},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}d.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.subclass=this.subclass,a.fn.init=function b(b,c){c&&c instanceof d&&!(c instanceof a)&&(c=a(c));return d.fn.init.call(this,b,c,e)},a.fn.init.prototype=a.fn;var e=a(c);return a},browser:{}}),y=d._Deferred(),d.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){H["[object "+b+"]"]=b.toLowerCase()}),w=d.uaMatch(v),w.browser&&(d.browser[w.browser]=!0,d.browser.version=w.version),d.browser.webkit&&(d.browser.safari=!0),G&&(d.inArray=function(a,b){return G.call(b,a)}),i.test(" ")&&(j=/^[\s\xA0]+/,k=/[\s\xA0]+$/),g=d(c),c.addEventListener?A=function(){c.removeEventListener("DOMContentLoaded",A,!1),d.ready()}:c.attachEvent&&(A=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",A),d.ready())});return d}();(function(){d.support={};var b=c.createElement("div");b.style.display="none",b.innerHTML="
    a";var e=b.getElementsByTagName("*"),f=b.getElementsByTagName("a")[0],g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=b.getElementsByTagName("input")[0];if(e&&e.length&&f){d.support={leadingWhitespace:b.firstChild.nodeType===3,tbody:!b.getElementsByTagName("tbody").length,htmlSerialize:!!b.getElementsByTagName("link").length,style:/red/.test(f.getAttribute("style")),hrefNormalized:f.getAttribute("href")==="/a",opacity:/^0.55$/.test(f.style.opacity),cssFloat:!!f.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,deleteExpando:!0,optDisabled:!1,checkClone:!1,noCloneEvent:!0,noCloneChecked:!0,boxModel:null,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableHiddenOffsets:!0},i.checked=!0,d.support.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,d.support.optDisabled=!h.disabled;var j=null;d.support.scriptEval=function(){if(j===null){var b=c.documentElement,e=c.createElement("script"),f="script"+d.now();try{e.appendChild(c.createTextNode("window."+f+"=1;"))}catch(g){}b.insertBefore(e,b.firstChild),a[f]?(j=!0,delete a[f]):j=!1,b.removeChild(e),b=e=f=null}return j};try{delete b.test}catch(k){d.support.deleteExpando=!1}!b.addEventListener&&b.attachEvent&&b.fireEvent&&(b.attachEvent("onclick",function l(){d.support.noCloneEvent=!1,b.detachEvent("onclick",l)}),b.cloneNode(!0).fireEvent("onclick")),b=c.createElement("div"),b.innerHTML="";var m=c.createDocumentFragment();m.appendChild(b.firstChild),d.support.checkClone=m.cloneNode(!0).cloneNode(!0).lastChild.checked,d(function(){var a=c.createElement("div"),b=c.getElementsByTagName("body")[0];if(b){a.style.width=a.style.paddingLeft="1px",b.appendChild(a),d.boxModel=d.support.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,d.support.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="
    ",d.support.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="
    t
    ";var e=a.getElementsByTagName("td");d.support.reliableHiddenOffsets=e[0].offsetHeight===0,e[0].style.display="",e[1].style.display="none",d.support.reliableHiddenOffsets=d.support.reliableHiddenOffsets&&e[0].offsetHeight===0,a.innerHTML="",b.removeChild(a).style.display="none",a=e=null}});var n=function(a){var b=c.createElement("div");a="on"+a;if(!b.attachEvent)return!0;var d=a in b;d||(b.setAttribute(a,"return;"),d=typeof b[a]==="function"),b=null;return d};d.support.submitBubbles=n("submit"),d.support.changeBubbles=n("change"),b=e=f=null}})();var e=/^(?:\{.*\}|\[.*\])$/;d.extend({cache:{},uuid:0,expando:"jQuery"+(d.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?d.cache[a[d.expando]]:a[d.expando];return!!a&&!g(a)},data:function(a,c,e,f){if(d.acceptData(a)){var g=d.expando,h=typeof c==="string",i,j=a.nodeType,k=j?d.cache:a,l=j?a[d.expando]:a[d.expando]&&d.expando;if((!l||f&&l&&!k[l][g])&&h&&e===b)return;l||(j?a[d.expando]=l=++d.uuid:l=d.expando),k[l]||(k[l]={},j||(k[l].toJSON=d.noop));if(typeof c==="object"||typeof c==="function")f?k[l][g]=d.extend(k[l][g],c):k[l]=d.extend(k[l],c);i=k[l],f&&(i[g]||(i[g]={}),i=i[g]),e!==b&&(i[c]=e);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[c]:i}},removeData:function(b,c,e){if(d.acceptData(b)){var f=d.expando,h=b.nodeType,i=h?d.cache:b,j=h?b[d.expando]:d.expando;if(!i[j])return;if(c){var k=e?i[j][f]:i[j];if(k){delete k[c];if(!g(k))return}}if(e){delete i[j][f];if(!g(i[j]))return}var l=i[j][f];d.support.deleteExpando||i!=a?delete i[j]:i[j]=null,l?(i[j]={},h||(i[j].toJSON=d.noop),i[j][f]=l):h&&(d.support.deleteExpando?delete b[d.expando]:b.removeAttribute?b.removeAttribute(d.expando):b[d.expando]=null)}},_data:function(a,b,c){return d.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=d.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),d.fn.extend({data:function(a,c){var e=null;if(typeof a==="undefined"){if(this.length){e=d.data(this[0]);if(this[0].nodeType===1){var g=this[0].attributes,h;for(var i=0,j=g.length;i-1)return!0;return!1},val:function(a){if(!arguments.length){var c=this[0];if(c){if(d.nodeName(c,"option")){var e=c.attributes.value;return!e||e.specified?c.value:c.text}if(d.nodeName(c,"select")){var f=c.selectedIndex,g=[],h=c.options,i=c.type==="select-one";if(f<0)return null;for(var k=i?f:0,l=i?f+1:h.length;k=0;else if(d.nodeName(this,"select")){var f=d.makeArray(e);d("option",this).each(function(){this.selected=d.inArray(d(this).val(),f)>=0}),f.length||(this.selectedIndex=-1)}else this.value=e}})}}),d.extend({attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,e,f){if(!a||a.nodeType===3||a.nodeType===8||a.nodeType===2)return b;if(f&&c in d.attrFn)return d(a)[c](e);var g=a.nodeType!==1||!d.isXMLDoc(a),h=e!==b;c=g&&d.props[c]||c;if(a.nodeType===1){var i=k.test(c);if(c==="selected"&&!d.support.optSelected){var j=a.parentNode;j&&(j.selectedIndex,j.parentNode&&j.parentNode.selectedIndex)}if((c in a||a[c]!==b)&&g&&!i){h&&(c==="type"&&l.test(a.nodeName)&&a.parentNode&&d.error("type property can't be changed"),e===null?a.nodeType===1&&a.removeAttribute(c):a[c]=e);if(d.nodeName(a,"form")&&a.getAttributeNode(c))return a.getAttributeNode(c).nodeValue;if(c==="tabIndex"){var o=a.getAttributeNode("tabIndex");return o&&o.specified?o.value:m.test(a.nodeName)||n.test(a.nodeName)&&a.href?0:b}return a[c]}if(!d.support.style&&g&&c==="style"){h&&(a.style.cssText=""+e);return a.style.cssText}h&&a.setAttribute(c,""+e);if(!a.attributes[c]&&(a.hasAttribute&&!a.hasAttribute(c)))return b;var p=!d.support.hrefNormalized&&g&&i?a.getAttribute(c,2):a.getAttribute(c);return p===null?b:p}h&&(a[c]=e);return a[c]}});var p=/\.(.*)$/,q=/^(?:textarea|input|select)$/i,r=/\./g,s=/ /g,t=/[^\w\s.|`]/g,u=function(a){return a.replace(t,"\\$&")};d.event={add:function(c,e,f,g){if(c.nodeType!==3&&c.nodeType!==8){try{d.isWindow(c)&&(c!==a&&!c.frameElement)&&(c=a)}catch(h){}if(f===!1)f=v;else if(!f)return;var i,j;f.handler&&(i=f,f=i.handler),f.guid||(f.guid=d.guid++);var k=d._data(c);if(!k)return;var l=k.events,m=k.handle;l||(k.events=l={}),m||(k.handle=m=function(){return typeof d!=="undefined"&&!d.event.triggered?d.event.handle.apply(m.elem,arguments):b}),m.elem=c,e=e.split(" ");var n,o=0,p;while(n=e[o++]){j=i?d.extend({},i):{handler:f,data:g},n.indexOf(".")>-1?(p=n.split("."),n=p.shift(),j.namespace=p.slice(0).sort().join(".")):(p=[],j.namespace=""),j.type=n,j.guid||(j.guid=f.guid);var q=l[n],r=d.event.special[n]||{};if(!q){q=l[n]=[];if(!r.setup||r.setup.call(c,g,p,m)===!1)c.addEventListener?c.addEventListener(n,m,!1):c.attachEvent&&c.attachEvent("on"+n,m)}r.add&&(r.add.call(c,j),j.handler.guid||(j.handler.guid=f.guid)),q.push(j),d.event.global[n]=!0}c=null}},global:{},remove:function(a,c,e,f){if(a.nodeType!==3&&a.nodeType!==8){e===!1&&(e=v);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=d.hasData(a)&&d._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(e=c.handler,c=c.type);if(!c||typeof c==="string"&&c.charAt(0)==="."){c=c||"";for(h in t)d.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+d.map(m.slice(0).sort(),u).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!e){for(j=0;j=0&&(a.type=f=f.slice(0,-1),a.exclusive=!0),e||(a.stopPropagation(),d.event.global[f]&&d.each(d.cache,function(){var b=d.expando,e=this[b];e&&e.events&&e.events[f]&&d.event.trigger(a,c,e.handle.elem)}));if(!e||e.nodeType===3||e.nodeType===8)return b;a.result=b,a.target=e,c=d.makeArray(c),c.unshift(a)}a.currentTarget=e;var h=d._data(e,"handle");h&&h.apply(e,c);var i=e.parentNode||e.ownerDocument;try{e&&e.nodeName&&d.noData[e.nodeName.toLowerCase()]||e["on"+f]&&e["on"+f].apply(e,c)===!1&&(a.result=!1,a.preventDefault())}catch(j){}if(!a.isPropagationStopped()&&i)d.event.trigger(a,c,i,!0);else if(!a.isDefaultPrevented()){var k,l=a.target,m=f.replace(p,""),n=d.nodeName(l,"a")&&m==="click",o=d.event.special[m]||{};if((!o._default||o._default.call(e,a)===!1)&&!n&&!(l&&l.nodeName&&d.noData[l.nodeName.toLowerCase()])){try{l[m]&&(k=l["on"+m],k&&(l["on"+m]=null),d.event.triggered=!0,l[m]())}catch(q){}k&&(l["on"+m]=k),d.event.triggered=!1}}},handle:function(c){var e,f,g,h,i,j=[],k=d.makeArray(arguments);c=k[0]=d.event.fix(c||a.event),c.currentTarget=this,e=c.type.indexOf(".")<0&&!c.exclusive,e||(g=c.type.split("."),c.type=g.shift(),j=g.slice(0).sort(),h=new RegExp("(^|\\.)"+j.join("\\.(?:.*\\.)?")+"(\\.|$)")),c.namespace=c.namespace||j.join("."),i=d._data(this,"events"),f=(i||{})[c.type];if(i&&f){f=f.slice(0);for(var l=0,m=f.length;l-1?d.map(a.options,function(a){return a.selected}).join("-"):"":a.nodeName.toLowerCase()==="select"&&(c=a.selectedIndex);return c},B=function B(a){var c=a.target,e,f;if(q.test(c.nodeName)&&!c.readOnly){e=d._data(c,"_change_data"),f=A(c),(a.type!=="focusout"||c.type!=="radio")&&d._data(c,"_change_data",f);if(e===b||f===e)return;if(e!=null||f)a.type="change",a.liveFired=b,d.event.trigger(a,arguments[1],c)}};d.event.special.change={filters:{focusout:B,beforedeactivate:B,click:function(a){var b=a.target,c=b.type;(c==="radio"||c==="checkbox"||b.nodeName.toLowerCase()==="select")&&B.call(this,a)},keydown:function(a){var b=a.target,c=b.type;(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&B.call(this,a)},beforeactivate:function(a){var b=a.target;d._data(b,"_change_data",A(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in z)d.event.add(this,c+".specialChange",z[c]);return q.test(this.nodeName)},teardown:function(a){d.event.remove(this,".specialChange");return q.test(this.nodeName)}},z=d.event.special.change.filters,z.focus=z.beforeactivate}c.addEventListener&&d.each({focus:"focusin",blur:"focusout"},function(a,b){function c(a){a=d.event.fix(a),a.type=b;return d.event.handle.call(this,a)}d.event.special[b]={setup:function(){this.addEventListener(a,c,!0)},teardown:function(){this.removeEventListener(a,c,!0)}}}),d.each(["bind","one"],function(a,c){d.fn[c]=function(a,e,f){if(typeof a==="object"){for(var g in a)this[c](g,e,a[g],f);return this}if(d.isFunction(e)||e===!1)f=e,e=b;var h=c==="one"?d.proxy(f,function(a){d(this).unbind(a,h);return f.apply(this,arguments)}):f;if(a==="unload"&&c!=="one")this.one(a,e,f);else for(var i=0,j=this.length;i0?this.bind(b,a,c):this.trigger(b)},d.attrFn&&(d.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,e,g){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!=="string")return e;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(f.call(n)==="[object Array]")if(u)if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&e.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&e.push(j[t]);else e.push.apply(e,n);else p(n,e);o&&(k(o,h,e,g),k.uniqueSort(e));return e};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e":function(a,b){var c,d=typeof b==="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){return"text"===a.getAttribute("type")},radio:function(a){return"radio"===a.type},checkbox:function(a){return"checkbox"===a.type},file:function(a){return"file"===a.type},password:function(a){return"password"===a.type},submit:function(a){return"submit"===a.type},image:function(a){return"image"===a.type},reset:function(a){return"reset"===a.type},button:function(a){return"button"===a.type||a.nodeName.toLowerCase()==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(f.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length==="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!=="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!=="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!=="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!=="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

    ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector,d=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(e){d=!0}b&&(k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(d||!l.match.PSEUDO.test(c)&&!/!=/.test(c))return b.call(a,c)}catch(e){}return k(c,null,null,[a]).length>0})}(),function(){var a=c.createElement("div");a.innerHTML="
    ";if(a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!=="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g0)for(var g=c;g0},closest:function(a,b){var c=[],e,f,g=this[0];if(d.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(e=0,f=a.length;e-1:d(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=L.test(a)?d(a,b||this.context):null;for(e=0,f=this.length;e-1:d.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b)break}}c=c.length>1?d.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a==="string")return d.inArray(this[0],a?d(a):this.parent().children());return d.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a==="string"?d(a,b):d.makeArray(a),e=d.merge(this.get(),c);return this.pushStack(N(c[0])||N(e[0])?e:d.unique(e))},andSelf:function(){return this.add(this.prevObject)}}),d.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return d.dir(a,"parentNode")},parentsUntil:function(a,b,c){return d.dir(a,"parentNode",c)},next:function(a){return d.nth(a,2,"nextSibling")},prev:function(a){return d.nth(a,2,"previousSibling")},nextAll:function(a){return d.dir(a,"nextSibling")},prevAll:function(a){return d.dir(a,"previousSibling")},nextUntil:function(a,b,c){return d.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return d.dir(a,"previousSibling",c)},siblings:function(a){return d.sibling(a.parentNode.firstChild,a)},children:function(a){return d.sibling(a.firstChild)},contents:function(a){return d.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:d.makeArray(a.childNodes)}},function(a,b){d.fn[a]=function(c,e){var f=d.map(this,b,c),g=K.call(arguments);G.test(a)||(e=c),e&&typeof e==="string"&&(f=d.filter(e,f)),f=this.length>1&&!M[a]?d.unique(f):f,(this.length>1||I.test(e))&&H.test(a)&&(f=f.reverse());return this.pushStack(f,a,g.join(","))}}),d.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?d.find.matchesSelector(b[0],a)?[b[0]]:[]:d.find.matches(a,b)},dir:function(a,c,e){var f=[],g=a[c];while(g&&g.nodeType!==9&&(e===b||g.nodeType!==1||!d(g).is(e)))g.nodeType===1&&f.push(g),g=g[c];return f},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var P=/ jQuery\d+="(?:\d+|null)"/g,Q=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,S=/<([\w:]+)/,T=/",""],legend:[1,"
    ","
    "],thead:[1,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],col:[2,"","
    "],area:[1,"",""],_default:[0,"",""]};X.optgroup=X.option,X.tbody=X.tfoot=X.colgroup=X.caption=X.thead,X.th=X.td,d.support.htmlSerialize||(X._default=[1,"div
    ","
    "]),d.fn.extend({text:function(a){if(d.isFunction(a))return this.each(function(b){var c=d(this);c.text(a.call(this,b,c.text()))});if(typeof a!=="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return d.text(this)},wrapAll:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapAll(a.call(this,b))});if(this[0]){var b=d(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapInner(a.call(this,b))});return this.each(function(){var b=d(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){d(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){d.nodeName(this,"body")||d(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=d(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,d(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,e;(e=this[c])!=null;c++)if(!a||d.filter(a,[e]).length)!b&&e.nodeType===1&&(d.cleanData(e.getElementsByTagName("*")),d.cleanData([e])),e.parentNode&&e.parentNode.removeChild(e);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&d.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return d.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(P,""):null;if(typeof a!=="string"||V.test(a)||!d.support.leadingWhitespace&&Q.test(a)||X[(S.exec(a)||["",""])[1].toLowerCase()])d.isFunction(a)?this.each(function(b){var c=d(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);else{a=a.replace(R,"<$1>");try{for(var c=0,e=this.length;c1&&l0?this.clone(!0):this).get();d(f[h])[b](j),e=e.concat(j)}return this.pushStack(e,a,f.selector)}}),d.extend({clone:function(a,b,c){var e=a.cloneNode(!0),f,g,h;if((!d.support.noCloneEvent||!d.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!d.isXMLDoc(a)){$(a,e),f=_(a),g=_(e);for(h=0;f[h];++h)$(f[h],g[h])}if(b){Z(a,e);if(c){f=_(a),g=_(e);for(h=0;f[h];++h)Z(f[h],g[h])}}return e},clean:function(a,b,e,f){b=b||c,typeof b.createElement==="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var g=[];for(var h=0,i;(i=a[h])!=null;h++){typeof i==="number"&&(i+="");if(!i)continue;if(typeof i!=="string"||U.test(i)){if(typeof i==="string"){i=i.replace(R,"<$1>");var j=(S.exec(i)||["",""])[1].toLowerCase(),k=X[j]||X._default,l=k[0],m=b.createElement("div");m.innerHTML=k[1]+i+k[2];while(l--)m=m.lastChild;if(!d.support.tbody){var n=T.test(i),o=j==="table"&&!n?m.firstChild&&m.firstChild.childNodes:k[1]===""&&!n?m.childNodes:[];for(var p=o.length-1;p>=0;--p)d.nodeName(o[p],"tbody")&&!o[p].childNodes.length&&o[p].parentNode.removeChild(o[p])}!d.support.leadingWhitespace&&Q.test(i)&&m.insertBefore(b.createTextNode(Q.exec(i)[0]),m.firstChild),i=m.childNodes}}else i=b.createTextNode(i);i.nodeType?g.push(i):g=d.merge(g,i)}if(e)for(h=0;g[h];h++)!f||!d.nodeName(g[h],"script")||g[h].type&&g[h].type.toLowerCase()!=="text/javascript"?(g[h].nodeType===1&&g.splice.apply(g,[h+1,0].concat(d.makeArray(g[h].getElementsByTagName("script")))),e.appendChild(g[h])):f.push(g[h].parentNode?g[h].parentNode.removeChild(g[h]):g[h]);return g},cleanData:function(a){var b,c,e=d.cache,f=d.expando,g=d.event.special,h=d.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&d.noData[j.nodeName.toLowerCase()])continue;c=j[d.expando];if(c){b=e[c]&&e[c][f];if(b&&b.events){for(var k in b.events)g[k]?d.event.remove(j,k):d.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[d.expando]:j.removeAttribute&&j.removeAttribute(d.expando),delete e[c]}}}});var bb=/alpha\([^)]*\)/i,bc=/opacity=([^)]*)/,bd=/-([a-z])/ig,be=/([A-Z])/g,bf=/^-?\d+(?:px)?$/i,bg=/^-?\d/,bh={position:"absolute",visibility:"hidden",display:"block"},bi=["Left","Right"],bj=["Top","Bottom"],bk,bl,bm,bn=function(a,b){return b.toUpperCase()};d.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return d.access(this,a,c,!0,function(a,c,e){return e!==b?d.style(a,c,e):d.css(a,c)})},d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bk(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{zIndex:!0,fontWeight:!0,opacity:!0,zoom:!0,lineHeight:!0},cssProps:{"float":d.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,e,f){if(a&&a.nodeType!==3&&a.nodeType!==8&&a.style){var g,h=d.camelCase(c),i=a.style,j=d.cssHooks[h];c=d.cssProps[h]||h;if(e===b){if(j&&"get"in j&&(g=j.get(a,!1,f))!==b)return g;return i[c]}if(typeof e==="number"&&isNaN(e)||e==null)return;typeof e==="number"&&!d.cssNumber[h]&&(e+="px");if(!j||!("set"in j)||(e=j.set(a,e))!==b)try{i[c]=e}catch(k){}}},css:function(a,c,e){var f,g=d.camelCase(c),h=d.cssHooks[g];c=d.cssProps[g]||g;if(h&&"get"in h&&(f=h.get(a,!0,e))!==b)return f;if(bk)return bk(a,c,g)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]},camelCase:function(a){return a.replace(bd,bn)}}),d.curCSS=d.css,d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,c,e){var f;if(c){a.offsetWidth!==0?f=bo(a,b,e):d.swap(a,bh,function(){f=bo(a,b,e)});if(f<=0){f=bk(a,b,b),f==="0px"&&bm&&(f=bm(a,b,b));if(f!=null)return f===""||f==="auto"?"0px":f}if(f<0||f==null){f=a.style[b];return f===""||f==="auto"?"0px":f}return typeof f==="string"?f:f+"px"}},set:function(a,b){if(!bf.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),d.support.opacity||(d.cssHooks.opacity={get:function(a,b){return bc.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style;c.zoom=1;var e=d.isNaN(b)?"":"alpha(opacity="+b*100+")",f=c.filter||"";c.filter=bb.test(f)?f.replace(bb,e):c.filter+" "+e}}),c.defaultView&&c.defaultView.getComputedStyle&&(bl=function(a,c,e){var f,g,h;e=e.replace(be,"-$1").toLowerCase();if(!(g=a.ownerDocument.defaultView))return b;if(h=g.getComputedStyle(a,null))f=h.getPropertyValue(e),f===""&&!d.contains(a.ownerDocument.documentElement,a)&&(f=d.style(a,e));return f}),c.documentElement.currentStyle&&(bm=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bf.test(d)&&bg.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bk=bl||bm,d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!d.support.reliableHiddenOffsets&&(a.style.display||d.css(a,"display"))==="none"},d.expr.filters.visible=function(a){return!d.expr.filters.hidden(a)});var bp=/%20/g,bq=/\[\]$/,br=/\r?\n/g,bs=/#.*$/,bt=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bu=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bv=/(?:^file|^widget|\-extension):$/,bw=/^(?:GET|HEAD)$/,bx=/^\/\//,by=/\?/,bz=/)<[^<]*)*<\/script>/gi,bA=/^(?:select|textarea)/i,bB=/\s+/,bC=/([?&])_=[^&]*/,bD=/(^|\-)([a-z])/g,bE=function(a,b,c){return b+c.toUpperCase()},bF=/^([\w\+\.\-]+:)\/\/([^\/?#:]*)(?::(\d+))?/,bG=d.fn.load,bH={},bI={},bJ,bK;try{bJ=c.location.href}catch(bL){bJ=c.createElement("a"),bJ.href="",bJ=bJ.href}bK=bF.exec(bJ.toLowerCase()),d.fn.extend({load:function(a,c,e){if(typeof a!=="string"&&bG)return bG.apply(this,arguments);if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var g=a.slice(f,a.length);a=a.slice(0,f)}var h="GET";c&&(d.isFunction(c)?(e=c,c=b):typeof c==="object"&&(c=d.param(c,d.ajaxSettings.traditional),h="POST"));var i=this;d.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?d("
    ").append(c.replace(bz,"")).find(g):c)),e&&i.each(e,[c,b,a])}});return this},serialize:function(){return d.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?d.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bA.test(this.nodeName)||bu.test(this.type))}).map(function(a,b){var c=d(this).val();return c==null?null:d.isArray(c)?d.map(c,function(a,c){return{name:b.name,value:a.replace(br,"\r\n")}}):{name:b.name,value:c.replace(br,"\r\n")}}).get()}}),d.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){d.fn[b]=function(a){return this.bind(b,a)}}),d.each(["get","post"],function(a,c){d[c]=function(a,e,f,g){d.isFunction(e)&&(g=g||f,f=e,e=b);return d.ajax({type:c,url:a,data:e,success:f,dataType:g})}}),d.extend({getScript:function(a,c){return d.get(a,b,c,"script")},getJSON:function(a,b,c){return d.get(a,b,c,"json")},ajaxSetup:function(a,b){b?d.extend(!0,a,d.ajaxSettings,b):(b=a,a=d.extend(!0,d.ajaxSettings,b));for(var c in {context:1,url:1})c in b?a[c]=b[c]:c in d.ajaxSettings&&(a[c]=d.ajaxSettings[c]);return a},ajaxSettings:{url:bJ,isLocal:bv.test(bK[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":d.parseJSON,"text xml":d.parseXML}},ajaxPrefilter:bM(bH),ajaxTransport:bM(bI),ajax:function(a,c){function v(a,c,l,n){if(r!==2){r=2,p&&clearTimeout(p),o=b,m=n||"",u.readyState=a?4:0;var q,t,v,w=l?bP(e,u,l):b,x,y;if(a>=200&&a<300||a===304){if(e.ifModified){if(x=u.getResponseHeader("Last-Modified"))d.lastModified[k]=x;if(y=u.getResponseHeader("Etag"))d.etag[k]=y}if(a===304)c="notmodified",q=!0;else try{t=bQ(e,w),c="success",q=!0}catch(z){c="parsererror",v=z}}else{v=c;if(!c||a)c="error",a<0&&(a=0)}u.status=a,u.statusText=c,q?h.resolveWith(f,[t,c,u]):h.rejectWith(f,[u,c,v]),u.statusCode(j),j=b,s&&g.trigger("ajax"+(q?"Success":"Error"),[u,e,q?t:v]),i.resolveWith(f,[u,c]),s&&(g.trigger("ajaxComplete",[u,e]),--d.active||d.event.trigger("ajaxStop"))}}typeof a==="object"&&(c=a,a=b),c=c||{};var e=d.ajaxSetup({},c),f=e.context||e,g=f!==e&&(f.nodeType||f instanceof d)?d(f):d.event,h=d.Deferred(),i=d._Deferred(),j=e.statusCode||{},k,l={},m,n,o,p,q,r=0,s,t,u={readyState:0,setRequestHeader:function(a,b){r||(l[a.toLowerCase().replace(bD,bE)]=b);return this},getAllResponseHeaders:function(){return r===2?m:null},getResponseHeader:function(a){var c;if(r===2){if(!n){n={};while(c=bt.exec(m))n[c[1].toLowerCase()]=c[2]}c=n[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){r||(e.mimeType=a);return this},abort:function(a){a=a||"abort",o&&o.abort(a),v(0,a);return this}};h.promise(u),u.success=u.done,u.error=u.fail,u.complete=i.done,u.statusCode=function(a){if(a){var b;if(r<2)for(b in a)j[b]=[j[b],a[b]];else b=a[u.status],u.then(b,b)}return this},e.url=((a||e.url)+"").replace(bs,"").replace(bx,bK[1]+"//"),e.dataTypes=d.trim(e.dataType||"*").toLowerCase().split(bB),e.crossDomain||(q=bF.exec(e.url.toLowerCase()),e.crossDomain=q&&(q[1]!=bK[1]||q[2]!=bK[2]||(q[3]||(q[1]==="http:"?80:443))!=(bK[3]||(bK[1]==="http:"?80:443)))),e.data&&e.processData&&typeof e.data!=="string"&&(e.data=d.param(e.data,e.traditional)),bN(bH,e,c,u);if(r===2)return!1;s=e.global,e.type=e.type.toUpperCase(),e.hasContent=!bw.test(e.type),s&&d.active++===0&&d.event.trigger("ajaxStart");if(!e.hasContent){e.data&&(e.url+=(by.test(e.url)?"&":"?")+e.data),k=e.url;if(e.cache===!1){var w=d.now(),x=e.url.replace(bC,"$1_="+w);e.url=x+(x===e.url?(by.test(e.url)?"&":"?")+"_="+w:"")}}if(e.data&&e.hasContent&&e.contentType!==!1||c.contentType)l["Content-Type"]=e.contentType;e.ifModified&&(k=k||e.url,d.lastModified[k]&&(l["If-Modified-Since"]=d.lastModified[k]),d.etag[k]&&(l["If-None-Match"]=d.etag[k])),l.Accept=e.dataTypes[0]&&e.accepts[e.dataTypes[0]]?e.accepts[e.dataTypes[0]]+(e.dataTypes[0]!=="*"?", */*; q=0.01":""):e.accepts["*"];for(t in e.headers)u.setRequestHeader(t,e.headers[t]);if(e.beforeSend&&(e.beforeSend.call(f,u,e)===!1||r===2)){u.abort();return!1}for(t in {success:1,error:1,complete:1})u[t](e[t]);o=bN(bI,e,c,u);if(o){u.readyState=1,s&&g.trigger("ajaxSend",[u,e]),e.async&&e.timeout>0&&(p=setTimeout(function(){u.abort("timeout")},e.timeout));try{r=1,o.send(l,v)}catch(y){status<2?v(-1,y):d.error(y)}}else v(-1,"No Transport");return u},param:function(a,c){var e=[],f=function(a,b){b=d.isFunction(b)?b():b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=d.ajaxSettings.traditional);if(d.isArray(a)||a.jquery&&!d.isPlainObject(a))d.each(a,function(){f(this.name,this.value)});else for(var g in a)bO(g,a[g],c,f);return e.join("&").replace(bp,"+")}}),d.extend({active:0,lastModified:{},etag:{}});var bR=d.now(),bS=/(\=)\?(&|$)|()\?\?()/i;d.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return d.expando+"_"+bR++}}),d.ajaxPrefilter("json jsonp",function(b,c,e){var f=typeof b.data==="string";if(b.dataTypes[0]==="jsonp"||c.jsonpCallback||c.jsonp!=null||b.jsonp!==!1&&(bS.test(b.url)||f&&bS.test(b.data))){var g,h=b.jsonpCallback=d.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2",m=function(){a[h]=i,g&&d.isFunction(i)&&a[h](g[0])};b.jsonp!==!1&&(j=j.replace(bS,l),b.url===j&&(f&&(k=k.replace(bS,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},e.then(m,m),b.converters["script json"]=function(){g||d.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),d.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){d.globalEval(a);return a}}}),d.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),d.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var bT=d.now(),bU,bV;d.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&bX()||bY()}:bX,bV=d.ajaxSettings.xhr(),d.support.ajax=!!bV,d.support.cors=bV&&"withCredentials"in bV,bV=b,d.support.ajax&&d.ajaxTransport(function(a){if(!a.crossDomain||d.support.cors){var c;return{send:function(e,f){var g=a.xhr(),h,i;a.username?g.open(a.type,a.url,a.async,a.username,a.password):g.open(a.type,a.url,a.async);if(a.xhrFields)for(i in a.xhrFields)g[i]=a.xhrFields[i];a.mimeType&&g.overrideMimeType&&g.overrideMimeType(a.mimeType),(!a.crossDomain||a.hasContent)&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(i in e)g.setRequestHeader(i,e[i])}catch(j){}g.send(a.hasContent&&a.data||null),c=function(e,i){var j,k,l,m,n;try{if(c&&(i||g.readyState===4)){c=b,h&&(g.onreadystatechange=d.noop,delete bU[h]);if(i)g.readyState!==4&&g.abort();else{j=g.status,l=g.getAllResponseHeaders(),m={},n=g.responseXML,n&&n.documentElement&&(m.xml=n),m.text=g.responseText;try{k=g.statusText}catch(o){k=""}j||!a.isLocal||a.crossDomain?j===1223&&(j=204):j=m.text?200:404}}}catch(p){i||f(-1,p)}m&&f(j,k,m,l)},a.async&&g.readyState!==4?(bU||(bU={},bW()),h=bT++,g.onreadystatechange=bU[h]=c):c()},abort:function(){c&&c(0,1)}}}});var bZ={},b$=/^(?:toggle|show|hide)$/,b_=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,ca,cb=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];d.fn.extend({show:function(a,b,c){var e,f;if(a||a===0)return this.animate(cc("show",3),a,b,c);for(var g=0,h=this.length;g=0;a--)c[a].elem===this&&(b&&c[a](!0),c.splice(a,1))}),b||this.dequeue();return this}}),d.each({slideDown:cc("show",1),slideUp:cc("hide",1),slideToggle:cc("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){d.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),d.extend({speed:function(a,b,c){var e=a&&typeof a==="object"?d.extend({},a):{complete:c||!c&&b||d.isFunction(a)&&a,duration:a,easing:c&&b||b&&!d.isFunction(b)&&b};e.duration=d.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in d.fx.speeds?d.fx.speeds[e.duration]:d.fx.speeds._default,e.old=e.complete,e.complete=function(){e.queue!==!1&&d(this).dequeue(),d.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig||(b.orig={})}}),d.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(d.fx.step[this.prop]||d.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=d.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function g(a){return e.step(a)}var e=this,f=d.fx;this.startTime=d.now(),this.start=a,this.end=b,this.unit=c||this.unit||(d.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,g.elem=this.elem,g()&&d.timers.push(g)&&!ca&&(ca=setInterval(f.tick,f.interval))},show:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),d(this.elem).show()},hide:function(){this.options.orig[this.prop]=d.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=d.now(),c=!0;if(a||b>=this.options.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),this.options.curAnim[this.prop]=!0;for(var e in this.options.curAnim)this.options.curAnim[e]!==!0&&(c=!1);if(c){if(this.options.overflow!=null&&!d.support.shrinkWrapBlocks){var f=this.elem,g=this.options;d.each(["","X","Y"],function(a,b){f.style["overflow"+b]=g.overflow[a]})}this.options.hide&&d(this.elem).hide();if(this.options.hide||this.options.show)for(var h in this.options.curAnim)d.style(this.elem,h,this.options.orig[h]);this.options.complete.call(this.elem)}return!1}var i=b-this.startTime;this.state=i/this.options.duration;var j=this.options.specialEasing&&this.options.specialEasing[this.prop],k=this.options.easing||(d.easing.swing?"swing":"linear");this.pos=d.easing[j||k](this.state,i,0,1,this.options.duration),this.now=this.start+(this.end-this.start)*this.pos,this.update();return!0}},d.extend(d.fx,{tick:function(){var a=d.timers;for(var b=0;b
    ";d.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),e=b.firstChild,f=e.firstChild,h=e.nextSibling.firstChild.firstChild,this.doesNotAddBorder=f.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,f.style.position="fixed",f.style.top="20px",this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15,f.style.position=f.style.top="",e.style.overflow="hidden",e.style.position="relative",this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),a=b=e=f=g=h=null,d.offset.initialize=d.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;d.offset.initialize(),d.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(d.css(a,"marginTop"))||0,c+=parseFloat(d.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var e=d.css(a,"position");e==="static"&&(a.style.position="relative");var f=d(a),g=f.offset(),h=d.css(a,"top"),i=d.css(a,"left"),j=e==="absolute"&&d.inArray("auto",[h,i])>-1,k={},l={},m,n;j&&(l=f.position()),m=j?l.top:parseInt(h,10)||0,n=j?l.left:parseInt(i,10)||0,d.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):f.css(k)}},d.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),e=cf.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(d.css(a,"marginTop"))||0,c.left-=parseFloat(d.css(a,"marginLeft"))||0,e.top+=parseFloat(d.css(b[0],"borderTopWidth"))||0,e.left+=parseFloat(d.css(b[0],"borderLeftWidth"))||0;return{top:c.top-e.top,left:c.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&(!cf.test(a.nodeName)&&d.css(a,"position")==="static"))a=a.offsetParent;return a})}}),d.each(["Left","Top"],function(a,c){var e="scroll"+c;d.fn[e]=function(c){var f=this[0],g;if(!f)return null;if(c!==b)return this.each(function(){g=cg(this),g?g.scrollTo(a?d(g).scrollLeft():c,a?c:d(g).scrollTop()):this[e]=c});g=cg(f);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:d.support.boxModel&&g.document.documentElement[e]||g.document.body[e]:f[e]}}),d.each(["Height","Width"],function(a,c){var e=c.toLowerCase();d.fn["inner"+c]=function(){return this[0]?parseFloat(d.css(this[0],e,"padding")):null},d.fn["outer"+c]=function(a){return this[0]?parseFloat(d.css(this[0],e,a?"margin":"border")):null},d.fn[e]=function(a){var f=this[0];if(!f)return a==null?null:this;if(d.isFunction(a))return this.each(function(b){var c=d(this);c[e](a.call(this,b,c[e]()))});if(d.isWindow(f)){var g=f.document.documentElement["client"+c];return f.document.compatMode==="CSS1Compat"&&g||f.document.body["client"+c]||g}if(f.nodeType===9)return Math.max(f.documentElement["client"+c],f.body["scroll"+c],f.documentElement["scroll"+c],f.body["offset"+c],f.documentElement["offset"+c]);if(a===b){var h=d.css(f,e),i=parseFloat(h);return d.isNaN(i)?h:i}return this.css(e,typeof a==="string"?a:a+"px")}}),a.jQuery=a.$=d})(window); diff --git a/applications/examples/static/js/jquery.prettyPhoto.js b/applications/examples/static/js/jquery.prettyPhoto.js deleted file mode 100644 index bc30642c..00000000 --- a/applications/examples/static/js/jquery.prettyPhoto.js +++ /dev/null @@ -1,69 +0,0 @@ -/* ------------------------------------------------------------------------ - Class: prettyPhoto - Use: Lightbox clone for jQuery - Author: Stephane Caron (http://www.no-margin-for-errors.com) - Version: 3.0.3 -------------------------------------------------------------------------- */ - -(function($){$.prettyPhoto={version:'3.0.2'};$.fn.prettyPhoto=function(pp_settings){pp_settings=jQuery.extend({animation_speed:'fast',slideshow:false,autoplay_slideshow:false,opacity:0.80,show_title:true,allow_resize:true,default_width:500,default_height:344,counter_separator_label:'/',theme:'facebook',hideflash:false,wmode:'opaque',autoplay:true,modal:false,overlay_gallery:true,keyboard_shortcuts:true,changepicturecallback:function(){},callback:function(){},markup:'
    \ -
     
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ - Expand \ -
    \ - next \ - previous \ -
    \ -
    \ -
    \ -

    \ - Close \ -
    \ - Previous \ -

    0/0

    \ - Next \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    \ -
    ',gallery_markup:'',image_markup:'',flash_markup:'',quicktime_markup:'',iframe_markup:'',inline_markup:'
    {content}
    ',custom_markup:''},pp_settings);var matchedObjects=this,percentBased=false,pp_dimensions,pp_open,pp_contentHeight,pp_contentWidth,pp_containerHeight,pp_containerWidth,windowHeight=$(window).height(),windowWidth=$(window).width(),pp_slideshow;doresize=true,scroll_pos=_get_scroll();$(window).unbind('resize.prettyphoto').bind('resize.prettyphoto',function(){_center_overlay();_resize_overlay();});if(pp_settings.keyboard_shortcuts){$(document).unbind('keydown.prettyphoto').bind('keydown.prettyphoto',function(e){if(typeof $pp_pic_holder!='undefined'){if($pp_pic_holder.is(':visible')){switch(e.keyCode){case 37:$.prettyPhoto.changePage('previous');e.preventDefault();break;case 39:$.prettyPhoto.changePage('next');e.preventDefault();break;case 27:if(!settings.modal) -$.prettyPhoto.close();e.preventDefault();break;};};};});} -$.prettyPhoto.initialize=function(){settings=pp_settings;if($.browser.msie&&parseInt($.browser.version)==6)settings.theme="light_square";theRel=$(this).attr('rel');galleryRegExp=/\[(?:.*)\]/;isSet=(galleryRegExp.exec(theRel))?true:false;pp_images=(isSet)?jQuery.map(matchedObjects,function(n,i){if($(n).attr('rel').indexOf(theRel)!=-1)return $(n).attr('href');}):$.makeArray($(this).attr('href'));pp_titles=(isSet)?jQuery.map(matchedObjects,function(n,i){if($(n).attr('rel').indexOf(theRel)!=-1)return($(n).find('img').attr('alt'))?$(n).find('img').attr('alt'):"";}):$.makeArray($(this).find('img').attr('alt'));pp_descriptions=(isSet)?jQuery.map(matchedObjects,function(n,i){if($(n).attr('rel').indexOf(theRel)!=-1)return($(n).attr('title'))?$(n).attr('title'):"";}):$.makeArray($(this).attr('title'));_buildOverlay(this);if(settings.allow_resize) -$(window).bind('scroll.prettyphoto',function(){_center_overlay();});set_position=jQuery.inArray($(this).attr('href'),pp_images);$.prettyPhoto.open();return false;} -$.prettyPhoto.open=function(event){if(typeof settings=="undefined"){settings=pp_settings;if($.browser.msie&&$.browser.version==6)settings.theme="light_square";pp_images=$.makeArray(arguments[0]);pp_titles=(arguments[1])?$.makeArray(arguments[1]):$.makeArray("");pp_descriptions=(arguments[2])?$.makeArray(arguments[2]):$.makeArray("");isSet=(pp_images.length>1)?true:false;set_position=0;_buildOverlay(event.target);} -if($.browser.msie&&$.browser.version==6)$('select').css('visibility','hidden');if(settings.hideflash)$('object,embed').css('visibility','hidden');_checkPosition($(pp_images).size());$('.pp_loaderIcon').show();if($ppt.is(':hidden'))$ppt.css('opacity',0).show();$pp_overlay.show().fadeTo(settings.animation_speed,settings.opacity);$pp_pic_holder.find('.currentTextHolder').text((set_position+1)+settings.counter_separator_label+$(pp_images).size());$pp_pic_holder.find('.pp_description').show().html(unescape(pp_descriptions[set_position]));(settings.show_title&&pp_titles[set_position]!=""&&typeof pp_titles[set_position]!="undefined")?$ppt.html(unescape(pp_titles[set_position])):$ppt.html(' ');movie_width=(parseFloat(grab_param('width',pp_images[set_position])))?grab_param('width',pp_images[set_position]):settings.default_width.toString();movie_height=(parseFloat(grab_param('height',pp_images[set_position])))?grab_param('height',pp_images[set_position]):settings.default_height.toString();if(movie_height.indexOf('%')!=-1){movie_height=parseFloat(($(window).height()*parseFloat(movie_height)/100)-150);percentBased=true;} -if(movie_width.indexOf('%')!=-1){movie_width=parseFloat(($(window).width()*parseFloat(movie_width)/100)-150);percentBased=true;} -$pp_pic_holder.fadeIn(function(){imgPreloader="";switch(_getFileType(pp_images[set_position])){case'image':imgPreloader=new Image();nextImage=new Image();if(isSet&&set_position<$(pp_images).size()-1)nextImage.src=pp_images[set_position+1];prevImage=new Image();if(isSet&&pp_images[set_position-1])prevImage.src=pp_images[set_position-1];$pp_pic_holder.find('#pp_full_res')[0].innerHTML=settings.image_markup.replace(/{path}/g,pp_images[set_position]);imgPreloader.onload=function(){pp_dimensions=_fitToViewport(imgPreloader.width,imgPreloader.height);_showContent();};imgPreloader.onerror=function(){alert('Image cannot be loaded. Make sure the path is correct and image exist.');$.prettyPhoto.close();};imgPreloader.src=pp_images[set_position];break;case'youtube':pp_dimensions=_fitToViewport(movie_width,movie_height);movie='http://www.youtube.com/v/'+grab_param('v',pp_images[set_position]);if(settings.autoplay)movie+="&autoplay=1";toInject=settings.flash_markup.replace(/{width}/g,pp_dimensions['width']).replace(/{height}/g,pp_dimensions['height']).replace(/{wmode}/g,settings.wmode).replace(/{path}/g,movie);break;case'vimeo':pp_dimensions=_fitToViewport(movie_width,movie_height);movie_id=pp_images[set_position];var regExp=/http:\/\/(www\.)?vimeo.com\/(\d+)/;var match=movie_id.match(regExp);movie='http://player.vimeo.com/video/'+match[2]+'?title=0&byline=0&portrait=0';if(settings.autoplay)movie+="&autoplay=1;";vimeo_width=pp_dimensions['width']+'/embed/?moog_width='+pp_dimensions['width'];toInject=settings.iframe_markup.replace(/{width}/g,vimeo_width).replace(/{height}/g,pp_dimensions['height']).replace(/{path}/g,movie);break;case'quicktime':pp_dimensions=_fitToViewport(movie_width,movie_height);pp_dimensions['height']+=15;pp_dimensions['contentHeight']+=15;pp_dimensions['containerHeight']+=15;toInject=settings.quicktime_markup.replace(/{width}/g,pp_dimensions['width']).replace(/{height}/g,pp_dimensions['height']).replace(/{wmode}/g,settings.wmode).replace(/{path}/g,pp_images[set_position]).replace(/{autoplay}/g,settings.autoplay);break;case'flash':pp_dimensions=_fitToViewport(movie_width,movie_height);flash_vars=pp_images[set_position];flash_vars=flash_vars.substring(pp_images[set_position].indexOf('flashvars')+10,pp_images[set_position].length);filename=pp_images[set_position];filename=filename.substring(0,filename.indexOf('?'));toInject=settings.flash_markup.replace(/{width}/g,pp_dimensions['width']).replace(/{height}/g,pp_dimensions['height']).replace(/{wmode}/g,settings.wmode).replace(/{path}/g,filename+'?'+flash_vars);break;case'iframe':pp_dimensions=_fitToViewport(movie_width,movie_height);frame_url=pp_images[set_position];frame_url=frame_url.substr(0,frame_url.indexOf('iframe')-1);toInject=settings.iframe_markup.replace(/{width}/g,pp_dimensions['width']).replace(/{height}/g,pp_dimensions['height']).replace(/{path}/g,frame_url);break;case'custom':pp_dimensions=_fitToViewport(movie_width,movie_height);toInject=settings.custom_markup;break;case'inline':myClone=$(pp_images[set_position]).clone().css({'width':settings.default_width}).wrapInner('
    ').appendTo($('body')).show();doresize=false;pp_dimensions=_fitToViewport($(myClone).width(),$(myClone).height());doresize=true;$(myClone).remove();toInject=settings.inline_markup.replace(/{content}/g,$(pp_images[set_position]).html());break;};if(!imgPreloader){$pp_pic_holder.find('#pp_full_res')[0].innerHTML=toInject;_showContent();};});return false;};$.prettyPhoto.changePage=function(direction){currentGalleryPage=0;if(direction=='previous'){set_position--;if(set_position<0){set_position=0;return;};}else if(direction=='next'){set_position++;if(set_position>$(pp_images).size()-1){set_position=0;}}else{set_position=direction;};if(!doresize)doresize=true;$('.pp_contract').removeClass('pp_contract').addClass('pp_expand');_hideContent(function(){$.prettyPhoto.open();});};$.prettyPhoto.changeGalleryPage=function(direction){if(direction=='next'){currentGalleryPage++;if(currentGalleryPage>totalPage){currentGalleryPage=0;};}else if(direction=='previous'){currentGalleryPage--;if(currentGalleryPage<0){currentGalleryPage=totalPage;};}else{currentGalleryPage=direction;};itemsToSlide=(currentGalleryPage==totalPage)?pp_images.length-((totalPage)*itemsPerPage):itemsPerPage;$pp_pic_holder.find('.pp_gallery li').each(function(i){$(this).animate({'left':(i*itemWidth)-((itemsToSlide*itemWidth)*currentGalleryPage)});});};$.prettyPhoto.startSlideshow=function(){if(typeof pp_slideshow=='undefined'){$pp_pic_holder.find('.pp_play').unbind('click').removeClass('pp_play').addClass('pp_pause').click(function(){$.prettyPhoto.stopSlideshow();return false;});pp_slideshow=setInterval($.prettyPhoto.startSlideshow,settings.slideshow);}else{$.prettyPhoto.changePage('next');};} -$.prettyPhoto.stopSlideshow=function(){$pp_pic_holder.find('.pp_pause').unbind('click').removeClass('pp_pause').addClass('pp_play').click(function(){$.prettyPhoto.startSlideshow();return false;});clearInterval(pp_slideshow);pp_slideshow=undefined;} -$.prettyPhoto.close=function(){if($pp_overlay.is(":animated"))return;$.prettyPhoto.stopSlideshow();$pp_pic_holder.stop().find('object,embed').css('visibility','hidden');$('div.pp_pic_holder,div.ppt,.pp_fade').fadeOut(settings.animation_speed,function(){$(this).remove();});$pp_overlay.fadeOut(settings.animation_speed,function(){if($.browser.msie&&$.browser.version==6)$('select').css('visibility','visible');if(settings.hideflash)$('object,embed').css('visibility','visible');$(this).remove();$(window).unbind('scroll');settings.callback();doresize=true;pp_open=false;delete settings;});};function _showContent(){$('.pp_loaderIcon').hide();$ppt.fadeTo(settings.animation_speed,1);projectedTop=scroll_pos['scrollTop']+((windowHeight/2)-(pp_dimensions['containerHeight']/2));if(projectedTop<0)projectedTop=0;$pp_pic_holder.find('.pp_content').animate({height:pp_dimensions['contentHeight'],width:pp_dimensions['contentWidth']},settings.animation_speed);$pp_pic_holder.animate({'top':projectedTop,'left':(windowWidth/2)-(pp_dimensions['containerWidth']/2),width:pp_dimensions['containerWidth']},settings.animation_speed,function(){$pp_pic_holder.find('.pp_hoverContainer,#fullResImage').height(pp_dimensions['height']).width(pp_dimensions['width']);$pp_pic_holder.find('.pp_fade').fadeIn(settings.animation_speed);if(isSet&&_getFileType(pp_images[set_position])=="image"){$pp_pic_holder.find('.pp_hoverContainer').show();}else{$pp_pic_holder.find('.pp_hoverContainer').hide();} -if(pp_dimensions['resized']){$('a.pp_expand,a.pp_contract').show();}else{$('a.pp_expand,a.pp_contract').hide();} -if(settings.autoplay_slideshow&&!pp_slideshow&&!pp_open)$.prettyPhoto.startSlideshow();settings.changepicturecallback();pp_open=true;});_insert_gallery();};function _hideContent(callback){$pp_pic_holder.find('#pp_full_res object,#pp_full_res embed').css('visibility','hidden');$pp_pic_holder.find('.pp_fade').fadeOut(settings.animation_speed,function(){$('.pp_loaderIcon').show();callback();});};function _checkPosition(setCount){(setCount>1)?$('.pp_nav').show():$('.pp_nav').hide();};function _fitToViewport(width,height){resized=false;_getDimensions(width,height);imageWidth=width,imageHeight=height;if(((pp_containerWidth>windowWidth)||(pp_containerHeight>windowHeight))&&doresize&&settings.allow_resize&&!percentBased){resized=true,fitting=false;while(!fitting){if((pp_containerWidth>windowWidth)){imageWidth=(windowWidth-200);imageHeight=(height/width)*imageWidth;}else if((pp_containerHeight>windowHeight)){imageHeight=(windowHeight-200);imageWidth=(width/height)*imageHeight;}else{fitting=true;};pp_containerHeight=imageHeight,pp_containerWidth=imageWidth;};_getDimensions(imageWidth,imageHeight);};return{width:Math.floor(imageWidth),height:Math.floor(imageHeight),containerHeight:Math.floor(pp_containerHeight),containerWidth:Math.floor(pp_containerWidth)+40,contentHeight:Math.floor(pp_contentHeight),contentWidth:Math.floor(pp_contentWidth),resized:resized};};function _getDimensions(width,height){width=parseFloat(width);height=parseFloat(height);$pp_details=$pp_pic_holder.find('.pp_details');$pp_details.width(width);detailsHeight=parseFloat($pp_details.css('marginTop'))+parseFloat($pp_details.css('marginBottom'));$pp_details=$pp_details.clone().appendTo($('body')).css({'position':'absolute','top':-10000});detailsHeight+=$pp_details.height();detailsHeight=(detailsHeight<=34)?36:detailsHeight;if($.browser.msie&&$.browser.version==7)detailsHeight+=8;$pp_details.remove();$pp_title=$pp_pic_holder.find('.ppt');$pp_title.width(width);titleHeight=parseFloat($pp_title.css('marginTop'))+parseFloat($pp_title.css('marginBottom'));$pp_title=$pp_title.clone().appendTo($('body')).css({'position':'absolute','top':-10000});titleHeight+=$pp_title.height();$pp_title.remove();pp_contentHeight=height+detailsHeight;pp_contentWidth=width;pp_containerHeight=pp_contentHeight+titleHeight+$pp_pic_holder.find('.pp_top').height()+$pp_pic_holder.find('.pp_bottom').height();pp_containerWidth=width;} -function _getFileType(itemSrc){if(itemSrc.match(/youtube\.com\/watch/i)){return'youtube';}else if(itemSrc.match(/vimeo\.com/i)){return'vimeo';}else if(itemSrc.match(/\b.mov\b/i)){return'quicktime';}else if(itemSrc.match(/\b.swf\b/i)){return'flash';}else if(itemSrc.match(/\biframe=true\b/i)){return'iframe';}else if(itemSrc.match(/\bcustom=true\b/i)){return'custom';}else if(itemSrc.substr(0,1)=='#'){return'inline';}else{return'image';};};function _center_overlay(){if(doresize&&typeof $pp_pic_holder!='undefined'){scroll_pos=_get_scroll();contentHeight=$pp_pic_holder.height(),contentwidth=$pp_pic_holder.width();projectedTop=(windowHeight/2)+scroll_pos['scrollTop']-(contentHeight/2);if(projectedTop<0)projectedTop=0;$pp_pic_holder.css({'top':projectedTop,'left':(windowWidth/2)+scroll_pos['scrollLeft']-(contentwidth/2)});};};function _get_scroll(){if(self.pageYOffset){return{scrollTop:self.pageYOffset,scrollLeft:self.pageXOffset};}else if(document.documentElement&&document.documentElement.scrollTop){return{scrollTop:document.documentElement.scrollTop,scrollLeft:document.documentElement.scrollLeft};}else if(document.body){return{scrollTop:document.body.scrollTop,scrollLeft:document.body.scrollLeft};};};function _resize_overlay(){windowHeight=$(window).height(),windowWidth=$(window).width();if(typeof $pp_overlay!="undefined")$pp_overlay.height($(document).height()).width(windowWidth);};function _insert_gallery(){if(isSet&&settings.overlay_gallery&&_getFileType(pp_images[set_position])=="image"){itemWidth=52+5;navWidth=(settings.theme=="facebook")?58:38;itemsPerPage=Math.floor((pp_dimensions['containerWidth']-100-navWidth)/itemWidth);itemsPerPage=(itemsPerPage";};toInject=settings.gallery_markup.replace(/{gallery}/g,toInject);$pp_pic_holder.find('#pp_full_res').after(toInject);$pp_pic_holder.find('.pp_gallery .pp_arrow_next').click(function(){$.prettyPhoto.changeGalleryPage('next');$.prettyPhoto.stopSlideshow();return false;});$pp_pic_holder.find('.pp_gallery .pp_arrow_previous').click(function(){$.prettyPhoto.changeGalleryPage('previous');$.prettyPhoto.stopSlideshow();return false;});$pp_pic_holder.find('.pp_content').hover(function(){$pp_pic_holder.find('.pp_gallery:not(.disabled)').fadeIn();},function(){$pp_pic_holder.find('.pp_gallery:not(.disabled)').fadeOut();});itemWidth=52+5;$pp_pic_holder.find('.pp_gallery ul li').each(function(i){$(this).css({'position':'absolute','left':i*itemWidth});$(this).find('a').unbind('click').click(function(){$.prettyPhoto.changePage(i);$.prettyPhoto.stopSlideshow();return false;});});};if(settings.slideshow){$pp_pic_holder.find('.pp_nav').prepend('Play') -$pp_pic_holder.find('.pp_nav .pp_play').click(function(){$.prettyPhoto.startSlideshow();return false;});} -$pp_pic_holder.attr('class','pp_pic_holder '+settings.theme);$pp_overlay.css({'opacity':0,'height':$(document).height(),'width':$(window).width()}).bind('click',function(){if(!settings.modal)$.prettyPhoto.close();});$('a.pp_close').bind('click',function(){$.prettyPhoto.close();return false;});$('a.pp_expand').bind('click',function(e){if($(this).hasClass('pp_expand')){$(this).removeClass('pp_expand').addClass('pp_contract');doresize=false;}else{$(this).removeClass('pp_contract').addClass('pp_expand');doresize=true;};_hideContent(function(){$.prettyPhoto.open();});return false;});$pp_pic_holder.find('.pp_previous, .pp_nav .pp_arrow_previous').bind('click',function(){$.prettyPhoto.changePage('previous');$.prettyPhoto.stopSlideshow();return false;});$pp_pic_holder.find('.pp_next, .pp_nav .pp_arrow_next').bind('click',function(){$.prettyPhoto.changePage('next');$.prettyPhoto.stopSlideshow();return false;});_center_overlay();};return this.unbind('click.prettyphoto').bind('click.prettyphoto',$.prettyPhoto.initialize);};function grab_param(name,url){name=name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");var regexS="[\\?&]"+name+"=([^&#]*)";var regex=new RegExp(regexS);var results=regex.exec(url);return(results==null)?"":results[1];}})(jQuery); diff --git a/applications/examples/static/powered_by/web2py_sticker_3d8799.png b/applications/examples/static/powered_by/web2py_sticker_3d8799.png deleted file mode 100644 index b5a88b97e99eb6f0456d1a2cd30c4f04054b60a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 548 zcmV+<0^9wGP)Px#24YJ`L;#rpJph>ZGLx$S000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOW0 z2sSSvrP-7K000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0004hNkl~RFE>*0~%z{jtwy;t4O>H znehkwc=K#x0E{@0jV}Ng$AiNh7-J>^IRF46Lf3V$*1|bA$Htg|XpVUtzX&A z|G1AMZ)j=aVOrN15R$rDYXd@4#I9*CN#M}Z+g`@dQm8;)91$f4I_GBPNK#_+$o6;R zaz3G{t2w?tp6GA)avtcHSPtYkRu~ig>b$;^F6Yy{Sk9*i;nMQ+O66k}70wwvermz%IvVD!x8BJZGS8^I5(hfMEDr>F3yr=dIe+ZO|@47B1RX_Ig zn)&I*&iWp2p>V~S-$ zwf=JcT?q8gcbYG5L4Ugkp3^V1FR5~^2gc@4k-1rc?1|d(=2Ia(b2kN+Qrv$brp%ba mRUY_DPx#24YJ`L;#rpJph>ZGLx$S000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOW0 z2sSCm#(bdw000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0004eNkl01ViXjV}NghMmJ47-L2P*#H0{f^!bmT6pg#+ZYoO%{H&&4!}@i81FSigruI<+KA8;u}j8F64+DwwvW+M8!M16M?}em-up>8l9ai9dC&`Z)mPvxf~dVSPtYmRu~h#cHdA*=fiQjEc;W0aA<}8Q&mUG?5RbAE}9$856_hE zkR&h!5k*Q0ZB1b*qU87zr87=djRxI=Pa{O81NNuFTAMG=)ZXENKzVuRTokII9r`u( zY0pA7 z%l(sL;x;BnflQ?A8MjnZ=~iUP+1fm{jmc3U=R~c&`Bcc9xk(7GsiglEbLwlZ-E7q@ j62d$FL}d1VV_w5ApJO>7c*#)h00000NkvXXu0mjf6>8%N diff --git a/applications/examples/static/powered_by/web2py_sticker_463d99.png b/applications/examples/static/powered_by/web2py_sticker_463d99.png deleted file mode 100644 index 67e6a99b776b5a140999e7419d06a3f0bd1074d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 555 zcmV+`0@VG9P)Px#24YJ`L;#rpJph>ZGLx$S000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOW0 z2sR@q6P3RJ000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0004oNkl~$ckkI%{SV%~z(x;;3GC2lYpkeKa?eH<#U5O_};PKdo z$D5C$0E{@X85aN;$CJY?P)bb%@&Evc2u;&KYYk(}JXT6MMDv)}@rRK6yqX7quTS&u z$m<81c$nU6bO?!Ewbl-yF=Cg@rzEf+=xraP9|%e*d`L+WQFNg(#w+F6K63uusOlX3 zK=ZGv^Rzk84zVqe>sVnNqHFiHl~mO^y7unat2#$fX0!k8`fz-ty(lwBnf*ZMTG!Y1 zx6hQ%5GBwC5jje-$03D6}b)65Ez zW83aipYOU?<)I|LG=!yM4+-HlZ-TuR)ok6B^zUfN#e zz>s2@P@litKPo0}W40)eiIhF#k!niaiYz(X=f`c#ZUu5qG{zjF#@}jt?3{T>2(PK6 te-$D1b?rS^b(4hfi60TE^WT_#_y*r}Gb)bb0Hpu`002ovPDHLkV1l_8@$vuw diff --git a/applications/examples/static/powered_by/web2py_sticker_73993d.png b/applications/examples/static/powered_by/web2py_sticker_73993d.png deleted file mode 100644 index c1a0840800c3854ccaeb770e3d2ebb3953074a0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 547 zcmV+;0^I$HP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOW7 z5)K}rRK)TC000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0004gNklR5?q9GZ;&=+s%U(HJq8!BMU|2^H=xW#atyXW!`hR<0mnoeiPw-B z|M26@M=<~f?8wF!01U&*mmuG74@IauvymKxJ)zA+8 zn)3fy~=M>9? zYV+m(NilI7lcPW;Qud5ns;P7J|y%9e*M+`@b=-;TH^mIUO>}?HB+6002ovPDHLkV1iMl=$`-p diff --git a/applications/examples/static/powered_by/web2py_sticker_993d3d.png b/applications/examples/static/powered_by/web2py_sticker_993d3d.png deleted file mode 100644 index a86918ee826cbf3a5e41b7c3dd827d9fbd97645b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 545 zcmV++0^a?JP)Px#24YJ`L;#rpJph>ZGLx$S000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOW0 z2sR#Yd)cl4000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0004eNkl4Vz){FgPnlc;NKWLpPlVSuy$ZS*lbWeGPCV|-{ zh%zOm?V7@BM9J|rN@omO1LE*CLS#7L{+3&p?B$-NGyEV>UfwykC`h)`{*wAi&!Z}@ z1@W~mEERi-3vWr^GSik4#+lfXETm$)*MWQEUK;0m;xSE&!sNT`dlds~ie*Ae_HzBE zn7EADqd+E7){JMWsdp)|X77?6mobMG$T87-e~KD^tL#Z*<|!_`C6oSD)YNwmp_+BO jxbTH<5vl9nm}B??ig7bY(O?~Z00000NkvXXu0mjfo8scn diff --git a/applications/examples/static/powered_by/web2py_sticker_993d98.png b/applications/examples/static/powered_by/web2py_sticker_993d98.png deleted file mode 100644 index 04ade15942c151dede82d24c00b0c5698a14210e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 536 zcmV+z0_XjSP)Px#24YJ`L;wH)0002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOW0 z2?7`+@a0_CX>@2HM@dakSAh-}0004VNklKO6o3MxGei~gm7rZ{-$peWzuAUA)On~kI$6vkR>p=1W}@- z*wz%5BT9~MQ97gPTVQzfX@tmh!2VoVYxCuq+B-ZDC@=4vOF}iaW51?8?fI(8*OGW? z2v==mO3Jsav|7P95_^h;RBZJ=ur%+*d9Ehz*IQ7S{4IUYa^RX`nNV%M+&?QOZevOm z$VAGX@klk*Zbi17t<6*0m=XnYPSo0)Z-va6hlKE+O8Ti-Q{Om@t5vs32%q>Dkvad3 ac@2M94l{as-v!nH0000Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOW7 z5)2e`w@+>W000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0004dNklm-Lq;klNv6AA{P#S0G=Gh>{bnwXGwE40K&A2XY=OjEP>muB)Wu={#SS+f#(FYq{-J-FV8Rb^!X$8|#jD_mpQy z66jrm$WxMQhZL3~O7<^NI-{x^KpZ|shztkZo^tEZc)4fj3{M2g%Nt`nS9NW-J*2+S z^Iet4f_SbA7cFCQ(zndCp@gv|)+7t5*y43yZrpR@TuIz-msw%*UADc7ficB0p`r0| z{iK+bv$`H0u^| i;T;bVsr_%vd-ww?EIA&r)&6e)00000@?kEP)Px#24YJ`L;#rpJph>ZGLx$S000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iOW0 z2sRD$#h7pa000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0004jNkl@BQ3XN<~Cdo95Arka?E+0l@!!e;j$H z9|I3zT~kCz>1wTw2rUu2roSbDrXSz-GE6_l3Z%suV~P{K_p@>&DY-nd|J~5K0|1=P z7XZNHe#PxJwDUk-Vl|NSNMS_ut9iMSwC?7`Qe5k9CPNZJrN!f?^W`reA2UQ_`FMU$ z`3yw@qeU1KDT%jJ3M&yM``0L)5QrL{V!Tv|5NQV#FO_v_yu4@X8J-A~i+9dNrOMkp zo>E`xx>e;l6JJ}xQn5{sF*Vz_+-XxA#-4a(vyh5yeh#elJ??WY@wi`Sg~{JCw&a01 z#S)>Z@iPA|1oHD;$``jFkik7?Sm-aSa;*pE@|VcmtU&U_)bZw1Aw6?91-4S$e<7#L ooWhel(3i-8IuWVk-6C_d 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 dM(~!v`ZfQ&QsD6>=9doOp_-m*rSj94{{ {{if request.function=='index':}} -

    {{=T("Available databases and tables")}}

    +

    {{=T("Available Databases and Tables")}}

    {{if not databases:}}{{=T("No databases in this application")}}{{pass}} + {{for db in sorted(databases):}} {{for table in databases[db].tables:}} {{qry='%s.%s.id>0'%(db,table)}} @@ -28,20 +29,24 @@ {{qry=''}} {{pass}} {{pass}} -

    - {{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}} -

    - [ {{=A(str(T('insert new'))+' '+table,_href=URL('insert',args=[db,table]))}} ] -

    + + + + {{pass}} +
    + {{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}} + + {{=A(str(T('New Record')),_href=URL('insert',args=[db,table]),_class="btn")}} +
    {{pass}} {{elif request.function=='select':}} -

    {{=XML(str(T("database %s select"))%A(request.args[0],_href=URL('index'))) }} +

    {{=XML(str(T("Database %s select"))%A(request.args[0],_href=URL('index'))) }}

    - {{if table:}} - [ {{=A(str(T('insert new %s'))%table,_href=URL('insert',args=[request.args[0],table]))}} ]

    -

    {{=T("Rows in table")}}


    + {{if table:}} + {{=A(str(T('New Record')),_href=URL('insert',args=[request.args[0],table]),_class="btn")}}

    +

    {{=T("Rows in Table")}}


    {{else:}}

    {{=T("Rows selected")}}


    {{pass}} @@ -51,8 +56,8 @@ {{=T('"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN')}}



    {{=T("%s selected", nrows)}}

    - {{if start>0:}}[ {{=A(T('previous 100 rows'),_href=URL('select',args=request.args[0],vars=dict(start=start-100)))}} ]{{pass}} - {{if stop0:}}{{=A(T('previous 100 rows'),_href=URL('select',args=request.args[0],vars=dict(start=start-100)),_class="btn")}}{{pass}} + {{if stop {{linkto=URL('update',args=request.args[0])}} @@ -61,35 +66,35 @@ {{pass}}

    {{=T("Import/Export")}}


    - [ {{=T("export as csv file")}} ] + {{=T("export as csv file")}} {{=formcsv or ''}} {{elif request.function=='insert':}} -

    {{=T("database")}} {{=A(request.args[0],_href=URL('index'))}} +

    {{=T("Database")}} {{=A(request.args[0],_href=URL('index'))}} {{if hasattr(table,'_primarykey'):}} {{fieldname=table._primarykey[0]}} {{dbname=request.args[0]}} {{tablename=request.args[1]}} {{cond = table[fieldname].type in ['string','text'] and '!=""' or '>0'}} - {{=T("table")}} {{=A(tablename,_href=URL('select',args=dbname,vars=dict(query='%s.%s.%s%s'%(dbname,tablename,fieldname,cond))))}} + {{=T("Table")}} {{=A(tablename,_href=URL('select',args=dbname,vars=dict(query='%s.%s.%s%s'%(dbname,tablename,fieldname,cond))))}} {{else:}} - {{=T("table")}} {{=A(request.args[1],_href=URL('select',args=request.args[0],vars=dict(query='%s.%s.id>0'%tuple(request.args[:2]))))}} + {{=T("Table")}} {{=A(request.args[1],_href=URL('select',args=request.args[0],vars=dict(query='%s.%s.id>0'%tuple(request.args[:2]))))}} {{pass}}

    {{=T("New Record")}}


    {{=form}} {{elif request.function=='update':}} -

    {{=T("database")}} {{=A(request.args[0],_href=URL('index'))}} +

    {{=T("Database")}} {{=A(request.args[0],_href=URL('index'))}} {{if hasattr(table,'_primarykey'):}} {{fieldname=request.vars.keys()[0]}} {{dbname=request.args[0]}} {{tablename=request.args[1]}} {{cond = table[fieldname].type in ['string','text'] and '!=""' or '>0'}} - {{=T("table")}} {{=A(tablename,_href=URL('select',args=dbname,vars=dict(query='%s.%s.%s%s'%(dbname,tablename,fieldname,cond))))}} - {{=T("record")}} {{=A('%s=%s'%request.vars.items()[0],_href=URL('update',args=request.args[:2],vars=request.vars))}} + {{=T("Table")}} {{=A(tablename,_href=URL('select',args=dbname,vars=dict(query='%s.%s.%s%s'%(dbname,tablename,fieldname,cond))))}} + {{=T("Record")}} {{=A('%s=%s'%request.vars.items()[0],_href=URL('update',args=request.args[:2],vars=request.vars))}} {{else:}} - {{=T("table")}} {{=A(request.args[1],_href=URL('select',args=request.args[0],vars=dict(query='%s.%s.id>0'%tuple(request.args[:2]))))}} - {{=T("record id")}} {{=A(request.args[2],_href=URL('update',args=request.args[:3]))}} + {{=T("Table")}} {{=A(request.args[1],_href=URL('select',args=request.args[0],vars=dict(query='%s.%s.id>0'%tuple(request.args[:2]))))}} + {{=T("Record id")}} {{=A(request.args[2],_href=URL('update',args=request.args[:3]))}} {{pass}}

    {{=T("Edit current record")}}



    {{=form}} diff --git a/applications/welcome/controllers/appadmin.py b/applications/welcome/controllers/appadmin.py index 126200b9..fa264bae 100644 --- a/applications/welcome/controllers/appadmin.py +++ b/applications/welcome/controllers/appadmin.py @@ -11,6 +11,8 @@ import copy import gluon.contenttype import gluon.fileutils +response.subtitle = 'Database Administration (appadmin)' + # ## critical --- make a copy of the environment global_env = copy.copy(globals()) diff --git a/applications/welcome/languages/cs.py b/applications/welcome/languages/cs.py index ba362a3f..85c72dce 100644 --- a/applications/welcome/languages/cs.py +++ b/applications/welcome/languages/cs.py @@ -10,7 +10,7 @@ '%s selected': '%s označených', 'Administrative interface': 'pro administrátorské rozhranie kliknite sem', 'Are you sure you want to delete this object?': 'Opravdu chceš odstranit tento objekt?', -'Available databases and tables': 'Dostupné databáze a tabuľky', +'Available Databases and Tables': 'Dostupné databáze a tabuľky', 'Cannot be empty': 'Nemůže být prázdné', 'Change password': 'Změna hesla', 'Check to delete': 'Označit ke smazání', @@ -68,7 +68,7 @@ 'Reset Password key': 'Nastavit registrační kľíč', 'Retrieve username': 'Retrieve username', 'Role': 'Role', -'Rows in table': 'řádků v tabulce', +'Rows in Table': 'řádků v tabulce', 'Rows selected': 'označených řádků', 'Stylesheet': 'CSS', 'Submit': 'Odeslat', @@ -100,8 +100,8 @@ 'cache': 'cache', 'customize me!': 'uprav mě!', 'data uploaded': 'data nahrána', -'database': 'databáze', -'database %s select': 'databáze %s výber', +'Database': 'databáze', +'Database %s select': 'databáze %s výber', 'db': 'db', 'design': 'návrh', 'done!': 'hotovo!', @@ -121,11 +121,11 @@ 'password': 'heslo', 'previous 100 rows': 'předchádzajících 100 řádků', 'profile': 'profil', -'record': 'záznam', +'Record': 'záznam', 'record does not exist': 'záznam neexistuje', -'record id': 'id záznamu', +'Record id': 'id záznamu', 'register': 'registrovat', 'state': 'stav', -'table': 'tabulka', +'Table': 'tabulka', 'unable to parse csv file': 'nedá sa zpracovat csv soubor', } diff --git a/applications/welcome/languages/default.py b/applications/welcome/languages/default.py index 17cc65dc..7fddedd2 100644 --- a/applications/welcome/languages/default.py +++ b/applications/welcome/languages/default.py @@ -2,4 +2,15 @@ { '!langcode!': 'en-us', '!langname!': 'English (US)', +'%s %%(shop)': '%s %%(shop)', +'%s %%(shop[0])': '%s %%(shop[0])', +'%s %%{shop[0]}': '%s %%{shop[0]}', +'%s %%{shop}': '%s %%{shop}', +'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S', +'@markmin\x01**Hello World**': '**Hello World**', +'enter an integer between %(min)g and %(max)g': 'enter an integer between %(min)g and %(max)g', +'enter date and time as %(format)s': 'enter date and time as %(format)s', +'Hello World': 'Hello World', +'Hello World ## comment': 'Hello World ', +'Hello World## comment': 'Hello World', } diff --git a/applications/welcome/languages/es.py b/applications/welcome/languages/es.py index cd54bced..1780400c 100644 --- a/applications/welcome/languages/es.py +++ b/applications/welcome/languages/es.py @@ -24,7 +24,7 @@ 'Are you sure you want to uninstall application "%s"': '¿Está seguro que desea desinstalar la aplicación "%s"', 'Are you sure you want to uninstall application "%s"?': '¿Está seguro que desea desinstalar la aplicación "%s"?', 'Authentication': 'Autenticación', -'Available databases and tables': 'Bases de datos y tablas disponibles', +'Available Databases and Tables': 'Bases de datos y tablas disponibles', '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.', 'Change Password': 'Cambie Contraseña', @@ -99,7 +99,7 @@ 'Reset Password key': 'Reset Password key', 'Resolve Conflict file': 'archivo Resolución de Conflicto', 'Role': 'Rol', -'Rows in table': 'Filas en la tabla', +'Rows in Table': 'Filas en la tabla', 'Rows selected': 'Filas seleccionadas', 'Saved file hash:': 'Hash del archivo guardado:', 'Static files': 'Archivos estáticos', @@ -165,8 +165,8 @@ 'currently saved or': 'actualmente guardado o', 'customize me!': 'Adaptame!', 'data uploaded': 'datos subidos', -'database': 'base de datos', -'database %s select': 'selección en base de datos %s', +'Database': 'base de datos', +'Database %s select': 'selección en base de datos %s', 'database administration': 'administración base de datos', 'db': 'db', 'defines tables': 'define tablas', @@ -218,9 +218,9 @@ 'pack all': 'empaquetar todo', 'pack compiled': 'empaquete compiladas', 'previous 100 rows': '100 filas anteriores', -'record': 'registro', +'Record': 'registro', 'record does not exist': 'el registro no existe', -'record id': 'id de registro', +'Record id': 'id de registro', 'register': 'registrese', 'remove compiled': 'eliminar compiladas', 'restore': 'restaurar', @@ -232,7 +232,7 @@ 'some files could not be removed': 'algunos archivos no pudieron ser removidos', 'state': 'estado', 'static': 'estáticos', -'table': 'tabla', +'Table': 'tabla', 'test': 'probar', 'the application logic, each URL path is mapped in one exposed function in the controller': 'la lógica de la aplicación, cada ruta URL se mapea en una función expuesta en el controlador', 'the data representation, define database tables and sets': 'la representación de datos, define tablas y conjuntos de base de datos', diff --git a/applications/welcome/languages/fr-ca.py b/applications/welcome/languages/fr-ca.py index 599cddbf..2491a9ea 100644 --- a/applications/welcome/languages/fr-ca.py +++ b/applications/welcome/languages/fr-ca.py @@ -14,7 +14,7 @@ 'Ajax Recipes': 'Recettes Ajax', 'Are you sure you want to delete this object?': 'Êtes-vous sûr de vouloir supprimer cet objet?', 'Authentication': 'Authentification', -'Available databases and tables': 'Bases de données et tables disponibles', +'Available Databases and Tables': 'Bases de données et tables disponibles', 'Buy this book': 'Acheter ce livre', 'Cannot be empty': 'Ne peut pas être vide', 'Check to delete': 'Cliquez pour supprimer', @@ -95,7 +95,7 @@ 'Reset Password key': 'Réinitialiser le mot clé', 'Resources': 'Ressources', 'Role': 'Rôle', -'Rows in table': 'Lignes du tableau', +'Rows in Table': 'Lignes du tableau', 'Rows selected': 'Lignes sélectionnées', 'Semantic': 'Sémantique', 'Services': 'Services', @@ -135,8 +135,8 @@ 'change password': 'changer le mot de passe', 'customize me!': 'personnalisez-moi!', 'data uploaded': 'données téléchargées', -'database': 'base de données', -'database %s select': 'base de données %s select', +'Database': 'base de données', +'Database %s select': 'base de données %s select', 'db': 'db', 'design': 'design', 'done!': 'fait!', @@ -157,12 +157,12 @@ 'please input your password again': "S'il vous plaît entrer votre mot de passe", 'previous 100 rows': '100 lignes précédentes', 'profile': 'profile', -'record': 'enregistrement', +'Record': 'enregistrement', 'record does not exist': "l'archive n'existe pas", -'record id': "id d'enregistrement", +'Record id': "id d'enregistrement", 'register': "s'inscrire", 'state': 'état', -'table': 'tableau', +'Table': 'tableau', 'unable to parse csv file': "incapable d'analyser le fichier cvs", 'value already in database or empty': 'valeur déjà dans la base ou vide', } diff --git a/applications/welcome/languages/fr.py b/applications/welcome/languages/fr.py index 8db13409..f7893576 100644 --- a/applications/welcome/languages/fr.py +++ b/applications/welcome/languages/fr.py @@ -16,7 +16,7 @@ 'appadmin is disabled because insecure channel': "appadmin est désactivée parce que le canal n'est pas sécurisé", 'Are you sure you want to delete this object?': 'Êtes-vous sûr de vouloir supprimer cet objet?', 'Authentication': 'Authentification', -'Available databases and tables': 'Bases de données et tables disponibles', +'Available Databases and Tables': 'Bases de données et tables disponibles', 'Buy this book': 'Acheter ce livre', 'cache': 'cache', 'Cannot be empty': 'Ne peut pas être vide', @@ -34,8 +34,8 @@ 'customize me!': 'personnalisez-moi!', 'data uploaded': 'données téléchargées', 'Database': 'Base de données', -'database': 'base de données', -'database %s select': 'base de données %s select', +'Database': 'base de données', +'Database %s select': 'base de données %s select', 'db': 'db', 'DB Model': 'Modèle DB', 'Delete:': 'Supprimer:', @@ -114,9 +114,9 @@ 'Quick Examples': 'Examples Rapides', 'Readme': 'Lisez-moi', 'Recipes': 'Recettes', -'record': 'enregistrement', +'Record': 'enregistrement', 'record does not exist': "l'archive n'existe pas", -'record id': "id d'enregistrement", +'Record id': "id d'enregistrement", 'Record ID': "ID d'enregistrement", 'Register': "S'inscrire", 'register': "s'inscrire", @@ -127,7 +127,7 @@ 'Reset Password key': 'Réinitialiser le mot clé', 'Resources': 'Ressources', 'Role': 'Rôle', -'Rows in table': 'Lignes du tableau', +'Rows in Table': 'Lignes du tableau', 'Rows selected': 'Lignes sélectionnées', 'Semantic': 'Sémantique', 'Services': 'Services', @@ -136,7 +136,7 @@ 'Submit': 'Soumettre', 'Support': 'Support', 'Sure you want to delete this object?': 'Êtes-vous sûr de vouloir supprimer cet objet?', -'table': 'tableau', +'Table': 'tableau', 'Table name': 'Nom du tableau', 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'La "query" est une condition comme "db.table1.champ1==\'valeur\'". Quelque chose comme "db.table1.champ1==db.table2.champ2" résulte en un JOIN SQL.', 'The Core': 'Le noyau', diff --git a/applications/welcome/languages/hi.py b/applications/welcome/languages/hi.py index e2bbc7d1..8dc9f19f 100644 --- a/applications/welcome/languages/hi.py +++ b/applications/welcome/languages/hi.py @@ -9,7 +9,7 @@ '%s %%{row} updated': '%s पंक्तियाँ अद्यतन', '%s selected': '%s चुना हुआ', 'Administrative interface': 'प्रशासनिक इंटरफेस के लिए यहाँ क्लिक करें', -'Available databases and tables': 'उपलब्ध डेटाबेस और तालिका', +'Available Databases and Tables': 'उपलब्ध डेटाबेस और तालिका', 'Cannot be empty': 'खाली नहीं हो सकता', 'Change Password': 'पासवर्ड बदलें', 'Check to delete': 'हटाने के लिए चुनें', @@ -43,7 +43,7 @@ 'Powered by': 'Powered by', 'Query:': 'प्रश्न:', 'Register': 'पंजीकृत (रजिस्टर) करना ', -'Rows in table': 'तालिका में पंक्तियाँ ', +'Rows in Table': 'तालिका में पंक्तियाँ ', 'Rows selected': 'चयनित (चुने गये) पंक्तियाँ ', 'Stylesheet': 'Stylesheet', 'Sure you want to delete this object?': 'सुनिश्चित हैं कि आप इस वस्तु को हटाना चाहते हैं?', @@ -61,8 +61,8 @@ 'change password': 'change password', 'customize me!': 'मुझे अनुकूलित (कस्टमाइज़) करें!', 'data uploaded': 'डाटा अपलोड सम्पन्न ', -'database': 'डेटाबेस', -'database %s select': 'डेटाबेस %s चुनी हुई', +'Database': 'डेटाबेस', +'Database %s select': 'डेटाबेस %s चुनी हुई', 'db': 'db', 'design': 'रचना करें', 'done!': 'हो गया!', @@ -77,11 +77,11 @@ 'next 100 rows': 'अगले 100 पंक्तियाँ', 'or import from csv file': 'या csv फ़ाइल से आयात', 'previous 100 rows': 'पिछले 100 पंक्तियाँ', -'record': 'record', +'Record': 'Record', 'record does not exist': 'रिकॉर्ड मौजूद नहीं है', -'record id': 'रिकॉर्ड पहचानकर्ता (आईडी)', +'Record id': 'रिकॉर्ड पहचानकर्ता (आईडी)', 'register': 'register', 'state': 'स्थिति', -'table': 'तालिका', +'Table': 'तालिका', 'unable to parse csv file': 'csv फ़ाइल पार्स करने में असमर्थ', } diff --git a/applications/welcome/languages/hu.py b/applications/welcome/languages/hu.py index a5133a63..bd996f66 100644 --- a/applications/welcome/languages/hu.py +++ b/applications/welcome/languages/hu.py @@ -9,7 +9,7 @@ '%s %%{row} updated': '%s sorok frissítődtek', '%s selected': '%s kiválasztott', 'Administrative interface': 'az adminisztrációs felületért kattints ide', -'Available databases and tables': 'Elérhető adatbázisok és táblák', +'Available Databases and Tables': 'Elérhető adatbázisok és táblák', 'Cannot be empty': 'Nem lehet üres', 'Check to delete': 'Törléshez válaszd ki', 'Client IP': 'Client IP', @@ -50,7 +50,7 @@ 'Registration key': 'Registration key', 'Reset Password key': 'Reset Password key', 'Role': 'Role', -'Rows in table': 'Sorok a táblában', +'Rows in Table': 'Sorok a táblában', 'Rows selected': 'Kiválasztott sorok', 'Stylesheet': 'Stylesheet', 'Sure you want to delete this object?': 'Biztos törli ezt az objektumot?', @@ -71,8 +71,8 @@ 'change password': 'jelszó megváltoztatása', 'customize me!': 'változtass meg!', 'data uploaded': 'adat feltöltve', -'database': 'adatbázis', -'database %s select': 'adatbázis %s kiválasztás', +'Database': 'adatbázis', +'Database %s select': 'adatbázis %s kiválasztás', 'db': 'db', 'design': 'design', 'done!': 'kész!', @@ -88,11 +88,11 @@ 'next 100 rows': 'következő 100 sor', 'or import from csv file': 'vagy betöltés csv fájlból', 'previous 100 rows': 'előző 100 sor', -'record': 'bejegyzés', +'Record': 'bejegyzés', 'record does not exist': 'bejegyzés nem létezik', -'record id': 'bejegyzés id', +'Record id': 'bejegyzés id', 'register': 'regisztráció', 'state': 'állapot', -'table': 'tábla', +'Table': 'tábla', 'unable to parse csv file': 'nem lehet a csv fájlt beolvasni', } diff --git a/applications/welcome/languages/it.py b/applications/welcome/languages/it.py index afa3109a..a73486c8 100644 --- a/applications/welcome/languages/it.py +++ b/applications/welcome/languages/it.py @@ -9,99 +9,178 @@ '%s selected': '%s selezionato', '%Y-%m-%d': '%d/%m/%Y', '%Y-%m-%d %H:%M:%S': '%d/%m/%Y %H:%M:%S', +'@markmin\x01Number of entries: **%s**': 'Number of entries: **%s**', +'About': 'About', +'Access Control': 'Access Control', +'Administrative Interface': 'Administrative Interface', 'Administrative interface': 'Interfaccia amministrativa', +'Ajax Recipes': 'Ajax Recipes', 'appadmin is disabled because insecure channel': 'Amministrazione (appadmin) disabilitata: comunicazione non sicura', -'Available databases and tables': 'Database e tabelle disponibili', +'Are you sure you want to delete this object?': 'Are you sure you want to delete this object?', +'Available Databases and Tables': 'Database e tabelle disponibili', +'Buy this book': 'Buy this book', 'cache': 'cache', 'Cannot be empty': 'Non può essere vuoto', 'change password': 'Cambia password', 'Check to delete': 'Seleziona per cancellare', +'Clear CACHE?': 'Clear CACHE?', +'Clear DISK': 'Clear DISK', +'Clear RAM': 'Clear RAM', 'Client IP': 'Client IP', +'Community': 'Community', +'Components and Plugins': 'Components and Plugins', 'Controller': 'Controller', 'Copyright': 'Copyright', +'Created By': 'Created By', +'Created On': 'Created On', 'Current request': 'Richiesta (request) corrente', 'Current response': 'Risposta (response) corrente', 'Current session': 'Sessione (session) corrente', 'customize me!': 'Personalizzami!', 'data uploaded': 'dati caricati', 'Database': 'Database', -'database': 'database', -'database %s select': 'database %s select', +'Database %s select': 'Database %s select', 'db': 'db', 'DB Model': 'Modello di DB', 'Delete': 'Delete', 'Delete:': 'Cancella:', +'Demo': 'Demo', +'Deployment Recipes': 'Deployment Recipes', 'Description': 'Descrizione', 'design': 'progetta', +'DISK': 'DISK', +'Disk Cleared': 'Disk Cleared', 'Documentation': 'Documentazione', +"Don't know what to do?": "Don't know what to do?", 'done!': 'fatto!', +'Download': 'Download', 'E-mail': 'E-mail', 'Edit': 'Modifica', 'Edit current record': 'Modifica record corrente', 'edit profile': 'modifica profilo', 'Edit This App': 'Modifica questa applicazione', +'Email and SMS': 'Email and SMS', +'enter an integer between %(min)g and %(max)g': 'enter an integer between %(min)g and %(max)g', +'Errors': 'Errors', 'export as csv file': 'esporta come file CSV', +'FAQ': 'FAQ', 'First name': 'Nome', +'Forms and Validators': 'Forms and Validators', +'Free Applications': 'Free Applications', +'Group %(group_id)s created': 'Group %(group_id)s created', 'Group ID': 'ID Gruppo', +'Group uniquely assigned to user %(id)s': 'Group uniquely assigned to user %(id)s', +'Groups': 'Groups', 'hello': 'hello', 'hello world': 'salve mondo', 'Hello World': 'Salve Mondo', 'Hello World in a flash!': 'Salve Mondo in un flash!', +'Home': 'Home', +'How did you get here?': 'How did you get here?', +'import': 'import', 'Import/Export': 'Importa/Esporta', 'Index': 'Indice', 'insert new': 'inserisci nuovo', 'insert new %s': 'inserisci nuovo %s', 'Internal State': 'Stato interno', +'Introduction': 'Introduction', 'Invalid email': 'Email non valida', +'Invalid login': 'Invalid login', 'Invalid Query': 'Richiesta (query) non valida', 'invalid request': 'richiesta non valida', +'Is Active': 'Is Active', 'Last name': 'Cognome', 'Layout': 'Layout', +'Layout Plugins': 'Layout Plugins', +'Layouts': 'Layouts', +'Live Chat': 'Live Chat', +'Logged in': 'Logged in', 'login': 'accesso', +'Login': 'Login', 'logout': 'uscita', +'Logout': 'Logout', +'Lost Password': 'Lost Password', +'Lost password?': 'Lost password?', 'lost password?': 'dimenticato la password?', 'Main Menu': 'Menu principale', +'Manage Cache': 'Manage Cache', 'Menu Model': 'Menu Modelli', +'Modified By': 'Modified By', +'Modified On': 'Modified On', +'My Sites': 'My Sites', 'Name': 'Nome', 'New Record': 'Nuovo elemento (record)', 'new record inserted': 'nuovo record inserito', 'next 100 rows': 'prossime 100 righe', 'No databases in this application': 'Nessun database presente in questa applicazione', 'not authorized': 'non autorizzato', +'Object or table name': 'Object or table name', 'Online examples': 'Vedere gli esempi', 'or import from csv file': 'oppure importa da file CSV', 'Origin': 'Origine', +'Other Plugins': 'Other Plugins', +'Other Recipes': 'Other Recipes', +'Overview': 'Overview', 'Password': 'Password', +"Password fields don't match": "Password fields don't match", +'please input your password again': 'please input your password again', +'Plugins': 'Plugins', 'Powered by': 'Powered by', +'Preface': 'Preface', 'previous 100 rows': '100 righe precedenti', +'Profile': 'Profile', +'Python': 'Python', 'Query:': 'Richiesta (query):', -'record': 'record', +'Quick Examples': 'Quick Examples', +'RAM': 'RAM', +'Ram Cleared': 'Ram Cleared', +'Recipes': 'Recipes', +'Record': 'Record', 'record does not exist': 'il record non esiste', -'record id': 'record id', 'Record ID': 'Record ID', +'Record id': 'Record id', +'Register': 'Register', 'register': 'registrazione', +'Registration identifier': 'Registration identifier', 'Registration key': 'Chiave di Registazione', +'Registration successful': 'Registration successful', +'Remember me (for 30 days)': 'Remember me (for 30 days)', 'Reset Password key': 'Resetta chiave Password ', 'Role': 'Ruolo', -'Rows in table': 'Righe nella tabella', +'Rows in Table': 'Righe nella tabella', 'Rows selected': 'Righe selezionate', +'Semantic': 'Semantic', +'Services': 'Services', 'state': 'stato', 'Stylesheet': 'Foglio di stile (stylesheet)', +'submit': 'submit', +'Submit': 'Submit', +'Support': 'Support', 'Sure you want to delete this object?': 'Vuoi veramente cancellare questo oggetto?', -'table': 'tabella', +'Table': 'tabella', 'Table name': 'Nome tabella', 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'La richiesta (query) è una condizione come ad esempio "db.tabella1.campo1==\'valore\'". Una condizione come "db.tabella1.campo1==db.tabella2.campo2" produce un "JOIN" SQL.', +'The Core': 'The Core', 'The output of the file is a dictionary that was rendered by the view %s': 'L\'output del file è un "dictionary" che è stato visualizzato dalla vista %s', +'The Views': 'The Views', +'This App': 'This App', 'This is a copy of the scaffolding application': "Questa è una copia dell'applicazione di base (scaffold)", 'Timestamp': 'Ora (timestamp)', +'Twitter': 'Twitter', 'unable to parse csv file': 'non riesco a decodificare questo file CSV', 'Update': 'Update', 'Update:': 'Aggiorna:', 'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Per costruire richieste (query) più complesse si usano (...)&(...) come "e" (AND), (...)|(...) come "o" (OR), e ~(...) come negazione (NOT).', +'User %(id)s Logged-in': 'User %(id)s Logged-in', +'User %(id)s Registered': 'User %(id)s Registered', 'User ID': 'ID Utente', +'Verify Password': 'Verify Password', +'Videos': 'Videos', 'View': 'Vista', +'Welcome': 'Welcome', 'Welcome %s': 'Benvenuto %s', 'Welcome to web2py': 'Benvenuto su web2py', +'Welcome to web2py!': 'Welcome to web2py!', 'Which called the function %s located in the file %s': 'che ha chiamato la funzione %s presente nel file %s', 'You are successfully running web2py': 'Stai eseguendo web2py con successo', 'You can modify this application and adapt it to your needs': 'Puoi modificare questa applicazione adattandola alle tue necessità', diff --git a/applications/welcome/languages/nl.py b/applications/welcome/languages/nl.py index 8efd85e4..33a06002 100644 --- a/applications/welcome/languages/nl.py +++ b/applications/welcome/languages/nl.py @@ -50,7 +50,7 @@ 'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'LET OP: TESTEN IS NIET THREAD SAFE, PROBEER NIET GELIJKTIJDIG MEERDERE TESTS TE DOEN.', 'ATTENTION: you cannot edit the running application!': 'LET OP: je kan de applicatie die nu draait niet editen!', 'Authentication': 'Authenticatie', -'Available databases and tables': 'Beschikbare databases en tabellen', +'Available Databases and Tables': 'Beschikbare databases en tabellen', 'Back': 'Terug', 'Buy this book': 'Koop dit boek', 'Cache': 'Cache', @@ -95,8 +95,8 @@ 'customize me!': 'pas me aan!', 'data uploaded': 'data geupload', 'Database': 'Database', -'database': 'database', -'database %s select': 'database %s select', +'Database': 'Database', +'Database %s select': 'Database %s select', 'database administration': 'database administratie', 'Date and Time': 'Datum en Tijd', 'db': 'db', @@ -260,9 +260,9 @@ 'RAM Cache Keys': 'RAM Cache Keys', 'Ram Cleared': 'Ram Geleegd', 'Recipes': 'Recepten', -'record': 'record', +'Record': 'Record', 'record does not exist': 'record bestaat niet', -'record id': 'record id', +'Record id': 'Record id', 'Record ID': 'Record ID', 'register': 'registreer', 'Register': 'Registreer', @@ -277,7 +277,7 @@ 'restore': 'herstel', 'revert': 'herstel', 'Role': 'Rol', -'Rows in table': 'Rijen in tabel', +'Rows in Table': 'Rijen in tabel', 'Rows selected': 'Rijen geselecteerd', 'save': 'bewaar', 'Save profile': 'Bewaar profiel', @@ -300,7 +300,7 @@ 'submit': 'submit', 'Support': 'Support', 'Sure you want to delete this object?': 'Weet je zeker dat je dit object wilt verwijderen?', -'table': 'Tabel', +'Table': 'Tabel', 'Table name': 'Tabelnaam', 'test': 'test', 'Testing application': 'Applicatie testen', diff --git a/applications/welcome/languages/pl.py b/applications/welcome/languages/pl.py index 366987c5..a94ec312 100644 --- a/applications/welcome/languages/pl.py +++ b/applications/welcome/languages/pl.py @@ -10,7 +10,7 @@ '%s selected': '%s wybranych', 'Administrative interface': 'Kliknij aby przejść do panelu administracyjnego', 'Authentication': 'Uwierzytelnienie', -'Available databases and tables': 'Dostępne bazy danych i tabele', +'Available Databases and Tables': 'Dostępne bazy danych i tabele', 'Cannot be empty': 'Nie może być puste', 'Change Password': 'Zmień hasło', 'Check to delete': 'Zaznacz aby usunąć', @@ -59,7 +59,7 @@ 'Register': 'Zarejestruj', 'Registration key': 'Klucz rejestracji', 'Role': 'Rola', -'Rows in table': 'Wiersze w tabeli', +'Rows in Table': 'Wiersze w tabeli', 'Rows selected': 'Wybrane wiersze', 'Stylesheet': 'Arkusz stylów', 'Submit': 'Wyślij', @@ -83,8 +83,8 @@ 'change password': 'change password', 'customize me!': 'dostosuj mnie!', 'data uploaded': 'dane wysłane', -'database': 'baza danych', -'database %s select': 'wybór z bazy danych %s', +'Database': 'baza danych', +'Database %s select': 'wybór z bazy danych %s', 'db': 'baza danych', 'design': 'projektuj', 'done!': 'zrobione!', @@ -99,11 +99,11 @@ 'next 100 rows': 'następne 100 wierszy', 'or import from csv file': 'lub zaimportuj z pliku csv', 'previous 100 rows': 'poprzednie 100 wierszy', -'record': 'rekord', +'Record': 'rekord', 'record does not exist': 'rekord nie istnieje', -'record id': 'id rekordu', +'Record id': 'id rekordu', 'register': 'register', 'state': 'stan', -'table': 'tabela', +'Table': 'tabela', 'unable to parse csv file': 'nie można sparsować pliku csv', } diff --git a/applications/welcome/languages/pt-br.py b/applications/welcome/languages/pt-br.py index b9b8a8bf..ecdfba3f 100644 --- a/applications/welcome/languages/pt-br.py +++ b/applications/welcome/languages/pt-br.py @@ -12,7 +12,7 @@ 'Access Control': 'Access Control', 'Administrative interface': 'Interface administrativa', 'Ajax Recipes': 'Ajax Recipes', -'Available databases and tables': 'Bancos de dados e tabelas disponíveis', +'Available Databases and Tables': 'Bancos de dados e tabelas disponíveis', 'Buy this book': 'Buy this book', 'Cannot be empty': 'Não pode ser vazio', 'Check to delete': 'Marque para apagar', @@ -79,7 +79,7 @@ 'Reset Password key': 'Reset Password key', 'Resources': 'Resources', 'Role': 'Role', -'Rows in table': 'Linhas na tabela', +'Rows in Table': 'Linhas na tabela', 'Rows selected': 'Linhas selecionadas', 'Semantic': 'Semantic', 'Services': 'Services', @@ -115,8 +115,8 @@ 'change password': 'modificar senha', 'customize me!': 'Personalize-me!', 'data uploaded': 'dados enviados', -'database': 'banco de dados', -'database %s select': 'Selecionar banco de dados %s', +'Database': 'banco de dados', +'Database %s select': 'Selecionar banco de dados %s', 'db': 'bd', 'design': 'design', 'done!': 'concluído!', @@ -132,11 +132,11 @@ 'next 100 rows': 'próximas 100 linhas', 'or import from csv file': 'ou importar de um arquivo csv', 'previous 100 rows': '100 linhas anteriores', -'record': 'registro', +'Record': 'registro', 'record does not exist': 'registro não existe', -'record id': 'id do registro', +'Record id': 'id do registro', 'register': 'Registre-se', 'state': 'estado', -'table': 'tabela', +'Table': 'tabela', 'unable to parse csv file': 'não foi possível analisar arquivo csv', } diff --git a/applications/welcome/languages/pt.py b/applications/welcome/languages/pt.py index f8e01ab1..8b0c633f 100644 --- a/applications/welcome/languages/pt.py +++ b/applications/welcome/languages/pt.py @@ -12,7 +12,7 @@ 'Administrative interface': 'Painel administrativo', 'Author Reference Auth User': 'Author Reference Auth User', 'Author Reference Auth User.username': 'Author Reference Auth User.username', -'Available databases and tables': 'bases de dados e tabelas disponíveis', +'Available Databases and Tables': 'bases de dados e tabelas disponíveis', 'Cannot be empty': 'não pode ser vazio', 'Category Create': 'Category Create', 'Category Select': 'Category Select', @@ -58,7 +58,7 @@ 'Powered by': 'Suportado por', 'Query:': 'Interrogação:', 'Replyto Reference Post': 'Replyto Reference Post', -'Rows in table': 'Linhas numa tabela', +'Rows in Table': 'Linhas numa tabela', 'Rows selected': 'Linhas seleccionadas', 'Stylesheet': 'Folha de estilo', 'Sure you want to delete this object?': 'Tem a certeza que deseja eliminar este objecto?', @@ -83,8 +83,8 @@ 'create new post': 'create new post', 'customize me!': 'Personaliza-me!', 'data uploaded': 'informação enviada', -'database': 'base de dados', -'database %s select': 'selecção de base de dados %s', +'Database': 'base de dados', +'Database %s select': 'selecção de base de dados %s', 'db': 'bd', 'design': 'design', 'done!': 'concluído!', @@ -102,9 +102,9 @@ 'next 100 rows': 'próximas 100 linhas', 'or import from csv file': 'ou importe a partir de ficheiro csv', 'previous 100 rows': '100 linhas anteriores', -'record': 'registo', +'Record': 'registo', 'record does not exist': 'registo inexistente', -'record id': 'id de registo', +'Record id': 'id de registo', 'register': 'register', 'search category': 'search category', 'search comment': 'search comment', @@ -116,6 +116,6 @@ 'show comment': 'show comment', 'show post': 'show post', 'state': 'estado', -'table': 'tabela', +'Table': 'tabela', 'unable to parse csv file': 'não foi possível carregar ficheiro csv', } diff --git a/applications/welcome/languages/ro.py b/applications/welcome/languages/ro.py index e2f0a31a..1352c26e 100644 --- a/applications/welcome/languages/ro.py +++ b/applications/welcome/languages/ro.py @@ -53,7 +53,7 @@ 'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATENȚIE: Nu puteți efectua mai multe teste o dată deoarece lansarea în execuție a mai multor subpocese nu este sigură.', 'ATTENTION: you cannot edit the running application!': 'ATENȚIE: nu puteți edita o aplicație în curs de execuție!', 'Authentication': 'Autentificare', -'Available databases and tables': 'Baze de date și tabele disponibile', +'Available Databases and Tables': 'Baze de date și tabele disponibile', 'Back': 'Înapoi', 'Buy this book': 'Cumpără această carte', 'cache': 'cache', @@ -92,8 +92,8 @@ 'customize me!': 'Personalizează-mă!', 'data uploaded': 'date încărcate', 'Database': 'Baza de date', -'database': 'bază de date', -'database %s select': 'selectare bază de date %s', +'Database': 'bază de date', +'Database %s select': 'selectare bază de date %s', 'database administration': 'administrare bază de date', 'Date and Time': 'Data și ora', 'db': 'db', @@ -247,9 +247,9 @@ 'Quick Examples': 'Exemple rapide', 'RAM Cache Keys': 'Chei cache RAM', 'Recipes': 'Rețete', -'record': 'înregistrare', +'Record': 'înregistrare', 'record does not exist': 'înregistrare inexistentă', -'record id': 'id înregistrare', +'Record id': 'id înregistrare', 'Record ID': 'ID înregistrare', 'register': 'înregistrare', 'Register': 'Înregistrare', @@ -264,7 +264,7 @@ 'restore': 'restaurare', 'revert': 'revenire', 'Role': 'Rol', -'Rows in table': 'Linii în tabel', +'Rows in Table': 'Linii în tabel', 'Rows selected': 'Linii selectate', 'save': 'salvare', 'Save profile': 'Salvează profil', @@ -284,7 +284,7 @@ 'Submit': 'Înregistrează', 'Support': 'Suport', 'Sure you want to delete this object?': 'Sigur ștergeți acest obiect?', -'table': 'tabel', +'Table': 'tabel', 'Table name': 'Nume tabel', 'test': 'test', 'Testing application': 'Testare aplicație', diff --git a/applications/welcome/languages/ru.py b/applications/welcome/languages/ru.py index 8782bb9a..ce632207 100644 --- a/applications/welcome/languages/ru.py +++ b/applications/welcome/languages/ru.py @@ -28,7 +28,7 @@ 'Administrative interface': 'административный интерфейс', 'Ajax Recipes': 'Ajax Recipes', 'Are you sure you want to delete this object?': 'Вы уверены, что хотите удалить этот объект?', -'Available databases and tables': 'Базы данных и таблицы', +'Available Databases and Tables': 'Базы данных и таблицы', 'Buy this book': 'Buy this book', 'cache': 'cache', 'Cannot be empty': 'Пустое значение недопустимо', @@ -45,9 +45,9 @@ 'Current session': 'Текущая сессия', 'customize me!': 'настройте внешний вид!', 'data uploaded': 'данные загружены', -'database': 'база данных', +'Database': 'база данных', 'Database': 'Database', -'database %s select': 'выбор базы данных %s', +'Database %s select': 'выбор базы данных %s', 'db': 'БД', 'DB Model': 'DB Model', 'Delete:': 'Удалить:', @@ -129,7 +129,7 @@ 'Quick Examples': 'Quick Examples', 'Recipes': 'Recipes', 'record does not exist': 'запись не найдена', -'record id': 'id записи', +'Record id': 'id записи', 'Record ID': 'ID записи', 'Register': 'Зарегистрироваться', 'Registration identifier': 'Registration identifier', @@ -137,7 +137,7 @@ 'Remember me (for 30 days)': 'Запомнить меня (на 30 дней)', 'Reset Password key': 'Сбросить ключ пароля', 'Role': 'Роль', -'Rows in table': 'Строк в таблице', +'Rows in Table': 'Строк в таблице', 'Rows selected': 'Выделено строк', 'Semantic': 'Semantic', 'Services': 'Services', @@ -146,7 +146,7 @@ 'Submit': 'Отправить', 'Support': 'Support', 'Sure you want to delete this object?': 'Подтвердите удаление объекта', -'table': 'таблица', +'Table': 'таблица', 'Table name': 'Имя таблицы', 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': '"Запрос" - это условие вида "db.table1.field1==\'значение\'". Выражение вида "db.table1.field1==db.table2.field2" формирует SQL JOIN.', 'The Core': 'The Core', diff --git a/applications/welcome/languages/sk.py b/applications/welcome/languages/sk.py index fd28f3ff..34d34e63 100644 --- a/applications/welcome/languages/sk.py +++ b/applications/welcome/languages/sk.py @@ -9,7 +9,7 @@ '%s %%{row} updated': '%s upravených záznamov', '%s selected': '%s označených', 'Administrative interface': 'pre administrátorské rozhranie kliknite sem', -'Available databases and tables': 'Dostupné databázy a tabuľky', +'Available Databases and Tables': 'Dostupné databázy a tabuľky', 'Cannot be empty': 'Nemôže byť prázdne', 'Check to delete': 'Označiť na zmazanie', 'Controller': 'Controller', @@ -56,7 +56,7 @@ 'Remember me (for 30 days)': 'Zapamätaj si ma (na 30 dní)', 'Reset Password key': 'Nastaviť registračný kľúč', 'Role': 'Rola', -'Rows in table': 'riadkov v tabuľke', +'Rows in Table': 'riadkov v tabuľke', 'Rows selected': 'označených riadkov', 'Stylesheet': 'Stylesheet', 'Submit': 'Odoslať', @@ -85,8 +85,8 @@ 'cache': 'cache', 'customize me!': 'prispôsob ma!', 'data uploaded': 'údaje naplnené', -'database': 'databáza', -'database %s select': 'databáza %s výber', +'Database': 'databáza', +'Database %s select': 'databáza %s výber', 'db': 'db', 'design': 'návrh', 'done!': 'hotovo!', @@ -102,11 +102,11 @@ 'or import from csv file': 'alebo naimportovať z csv súboru', 'password': 'heslo', 'previous 100 rows': 'predchádzajúcich 100 riadkov', -'record': 'záznam', +'Record': 'záznam', 'record does not exist': 'záznam neexistuje', -'record id': 'id záznamu', +'Record id': 'id záznamu', 'register': 'registrovať', 'state': 'stav', -'table': 'tabuľka', +'Table': 'tabuľka', 'unable to parse csv file': 'nedá sa načítať csv súbor', } diff --git a/applications/welcome/languages/uk.py b/applications/welcome/languages/uk.py index 1bf341e2..4561f5cd 100644 --- a/applications/welcome/languages/uk.py +++ b/applications/welcome/languages/uk.py @@ -36,7 +36,7 @@ 'Ajax Recipes': 'Рецепти для Ajax', 'appadmin is disabled because insecure channel': 'використовується незахищенний канал (HTTP). Appadmin вимкнено', 'Are you sure you want to delete this object?': "Ви впевнені, що хочете вилучити цей об'єкт?", -'Available databases and tables': 'Доступні бази даних та таблиці', +'Available Databases and Tables': 'Доступні бази даних та таблиці', 'Buy this book': 'Купити книжку', 'cache': 'кеш', 'Cache': 'Кеш', @@ -58,9 +58,9 @@ 'Current session': 'Поточна сесія (current session)', 'customize me!': 'причепуріть мене!', 'data uploaded': 'дані завантажено', -'database': 'база даних', +'Database': 'база даних', 'Database': 'База даних', -'database %s select': 'Вибірка з бази даних %s', +'Database %s select': 'Вибірка з бази даних %s', 'db': 'база даних', 'DB Model': 'Модель БД', 'Delete:': 'Вилучити:', @@ -157,10 +157,10 @@ 'RAM Cache Keys': 'Ключі ОЗП-кешу', 'Ram Cleared': 'ОЗП-кеш очищено', 'Recipes': 'Рецепти', -'record': 'запис', +'Record': 'запис', 'Record %(id)s updated': 'Запис %(id)s змінено', 'record does not exist': 'запису не існує', -'record id': 'ід. запису', +'Record id': 'ід. запису', 'Record ID': 'Ід.запису', 'Record Updated': 'Запис змінено', 'Register': 'Реєстрація', @@ -171,7 +171,7 @@ 'Request reset password': 'Запит на зміну пароля', 'Reset Password key': 'Ключ скидання пароля', 'Role': 'Роль', -'Rows in table': 'Рядки в таблиці', +'Rows in Table': 'Рядки в таблиці', 'Rows selected': 'Відмічено рядків', 'Save profile': 'Зберегти параметри', 'Semantic': 'Семантика', @@ -183,7 +183,7 @@ 'submit': 'submit', 'Submit': 'Застосувати', 'Support': 'Підтримка', -'table': 'Таблиця', +'Table': 'Таблиця', 'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': '"Запит" це умова, на зразок "db.table1.field1==\'значення\'". Вираз "db.table1.field1==db.table2.field2" повертає результат об\'єднання (SQL JOIN) таблиць.', 'The Core': 'Ядро', 'The output of the file is a dictionary that was rendered by the view %s': 'Результат функції - словник пар (назва=значення) було відображено з допомогою відображення (view) %s', diff --git a/applications/welcome/languages/zh.py b/applications/welcome/languages/zh.py index 0567e55e..30c8a575 100644 --- a/applications/welcome/languages/zh.py +++ b/applications/welcome/languages/zh.py @@ -24,7 +24,7 @@ 'Are you sure you want to uninstall application "%s"': '確定要移除應用程式 "%s"', 'Are you sure you want to uninstall application "%s"?': '確定要移除應用程式 "%s"', 'Authentication': '驗證', -'Available databases and tables': '可提供的資料庫和資料表', +'Available Databases and Tables': '可提供的資料庫和資料表', 'Cannot be empty': '不可空白', 'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': '無法編譯:應用程式中含有錯誤,請除錯後再試一次.', 'Change Password': '變更密碼', @@ -101,7 +101,7 @@ 'Reset Password key': '重設密碼', 'Resolve Conflict file': '解決衝突檔案', 'Role': '角色', -'Rows in table': '在資料表裏的資料', +'Rows in Table': '在資料表裏的資料', 'Rows selected': '筆資料被選擇', 'Saved file hash:': '檔案雜湊值已紀錄:', 'Static files': '靜態檔案', @@ -144,8 +144,8 @@ 'change password': '變更密碼', 'customize me!': '請調整我!', 'data uploaded': '資料已上傳', -'database': '資料庫', -'database %s select': '已選擇 %s 資料庫', +'Database': '資料庫', +'Database %s select': '已選擇 %s 資料庫', 'db': 'db', 'design': '設計', 'done!': '完成!', @@ -160,11 +160,11 @@ 'next 100 rows': '往後 100 筆', 'or import from csv file': '或是從逗號分隔檔(CSV)匯入', 'previous 100 rows': '往前 100 筆', -'record': '紀錄', +'Record': '紀錄', 'record does not exist': '紀錄不存在', -'record id': '紀錄編號', +'Record id': '紀錄編號', 'register': '註冊', 'state': '狀態', -'table': '資料表', +'Table': '資料表', 'unable to parse csv file': '無法解析逗號分隔檔(csv)', } diff --git a/applications/welcome/static/images/arrows-ffffff.png b/applications/welcome/static/images/arrows-ffffff.png deleted file mode 100644 index 995df52065bc250180081f895070ee63de05bfe7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 244 zcmeAS@N?(olHy`uVBq!ia0vp^B0!wS#0(^(;%-|4Ddu7)&kzm{j@u9Y9{{*+s`nvx*DV21Ml+qsS;fz%XuL>4nJa0`Jj^84%m5X5;uE3CAVF z2N9nKtOSqrVt}o#u!ao`Oz-VzRsdAU5?8-h#`yueUg8f`IEZS-7|`VfI;%CEN6Z_3 zu0odpbaDWNS1qDMJRHmR_`Dr_xU)E#1e!2pWLmb^BVoa2Gvpw~q=lIH5>?Y&xBxWz z*NxjilaK~55RCa{c$#P~_2t3DZG3y|vng}6D0jCI z#My|y@GRD~poA$rDlUvizOzl(O8?gbApmZ<@asRjSh~Jq>##>J)O}ldzEYVP3KJ%WOaAZiLYPi4 zm)4>fuRcZbwC|HcBh!0^Ks1645RQAC`E<1zD|`h zFyKz-!VckBG`%ANfd4hHIG)TINi`%wGYq>1VIcU+emL6- zTzGg99Sh=fEZp~?2wT-rD4B}e&}az2lSkI#HsltX0deL+Ponc_lh_f136mFE?NR|u zwfG>yItDV??GKt8K|5?&x=5ocBaK?T5(b^3mmefflDk;meW59+wLs`>!Al&@=hUAU z3i;M!d2aw3W)G^X{X%yu2?zPNOG=N0t3t6%CX?Q0p@bXT%sUqP%f<@03+t}umec*L zm^iQZshUyRPDlMJ*1#d<+6Ra;G_x8&T>fZ>;2#P=Tq6iDN({G_ajy7NX5^-~D^Az` E2JT=&k^lez diff --git a/applications/welcome/static/images/css3buttons_icons.png b/applications/welcome/static/images/css3buttons_icons.png deleted file mode 100644 index d858c9a5c1b357f2d703fd6baf2f4d2903839c4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3322 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 Ee|IBwIRF3v diff --git a/applications/welcome/static/images/poweredby.png b/applications/welcome/static/images/poweredby.png deleted file mode 100644 index a767243799bdcb63b8803d2a1d39158b98d8ebfa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4150 zcmV-65XtX}P)pf zDkl?aX22Da8se-~ai&snJSm4QWE_HV#x^Eqb1;h+WP=gGC}0>O(AJWA?|$#y`Ox%3 zLLzZesU+u9_j~uYg(z=EJnx@%fEz1Hx z2!UZ3_IoKMrfJ&W{2ho8LeSgW`^$|RH$J3wcX$7E#flXlEh{S{olc8PCWE3V6c-nx zsw$>wa`x<5{C+=GRaHczQFL8LQ4~zmw1GBF6M#%61LT!=I-R7`X$-@_<#OTk`A8;{ zWHK2H!$1gu+wBG*olYaABoqoEgdm+x+h7*n1p)zbxg3D~T`H9#m&@UHyD1pR--9TM zLT6{^-IitjL~Cwt{&+YX=IGI*tX;d7*49?i=`>!imz675^0lvh4PDn68yn-Ed+tF> z$?)(nciwp?t5&UI$BrGWTeptR&Q7*%+eSDXCYQ@GXU-gkhK4wK@+8&O)m*r6flqzv zQ}p)sa^S!Ls;jFRA0Ov)pZgq7Km9a=gM+wSF0$Dyt5>h)y6diEWMqU@t5#87UXIJ< zA{vd-)z!t;ty@{Yem$8?hSjTA^YyQPo%;HE`+)x*#Ih_xp^&q=x%oatRaFUji%6%_ zw6wG^bLLD=oH)VSwQITQrkmKleLEXAY+&=|&A8oePMtc%u3fv(G>wfLH!?mxPHSr` zmo8nxbT!pqpB(nhXaShK~GN)4?OSy zjg5`8x3{x&=~7~`7`m?Ga=Gw$Jb1lcJRT1YhvRR~(^5**#fulOZES25nM{TmGiI=I z9Xsgn@8_|{9wQQopzAu}aG2%Gmy<{&=<4di=kpPbMv2Gc zjE#*kJUmQmYb(o^E#v@lR8>_`QBlFW@4n0N+}GEKShsGSwPeW>;dDB2xm?6zG5hp|5cqsP`*$XjA(>3#^?K2Do$>K; zii?Yh$K#l$Ngxog7cdM1DJ9u#mP{st&*!s)oy+C2$0d_V91e$_MMx=$#bS2W;rII| zSz|mNCzHt#2n2Au-8}#N^K9L^m7bm+VzJmHC4~^w*4A?8op*BIefLpWSxGjV{i}g( zSr$8Y?v!HPx^>n^KJpQvC<>No=6OWd5kgGaO#VFxMWE|CmSs(f=u*l_-%RhQg{S%S zPEl1%!@#oSwLX~qwYakO7r*#L_V3?6>Ak9|c2-o#cmT@F%UQj8H47ImL9I~@3m{YVMYvXDrSOq!$cOb9_HohA{B69^XL@_3N)4=Ev#Qj$rh z7#|(S>+w)sU2Ox{)YL>vOAE7R&BE{ZqbLgTc$|Iv_OWZ%E(Qh$c>M9lS@R!jShRQ% zr4{A*z5JmSg#aN)jK>(fc!^*rWas}=05(m$0Y6?}5z?}FzwZqCWnouoBiy3?pLgQ^fOeg(%?L?ZUV3n5Tdl?NYukS~1U3+&jjgR!wOUVQ0ABCXfaIJ*@oB~IOm#KMvmlU+$7 zgn~ej&1N`t`aLfE{`bt8GY9js#}~vjO#HzBGaBj;0>1aew;3HCVd>JPXqt8fWGN-F z=qSOG5^C$~_}}gMO$CENOvAwK^`L4hbfw`UY zsE;)9?53ZweEIUcwM?k|3TtVaMtONTB_$>HG^3-VT)K1-MF?W?I6wNyf1#=>Uaxlw z^(jK3`MMT9G_R98?)oTOp4q_hW5=1(KF1EsreRVP@KIe`gQ}>k|LQt=-h7J{pZElR zzdv6Q+g73|Boj%J$prO{jTDE1ynps=euF~f-9WZL_aO3PJzHi`3TE;x6*ybUOLJbLR+#LI|PYa5yL_2~k;5L3V-y zx~}J~z%(&0_aGq8<4&iOva&Mts{)O@Y|T!OJ5O1uBqPHkWHK3aUB~0`5R1h)efl&# zJv|&cbciEIju4GT?Kzs7nrNtRVCJk@_S_DKgHR|$Wo6~G!O%1e1o=Se_xicF`vJB* zvk@sJt+QuST{{!6)58yb@Fe?p@8#hYD`;+RCYQ@y@u;gOO^nCLRhYDQ+`yZMk1#$q zPSuQRid+7Sgt`4uyi=rqTe(fL&7cC+f3i6dT|3*nk zDK2-OE(8KaRe0ykqZrv7<>lqJvMD3Wg4=FocKe(>KMTQRhRGLAUcV2^w0Qc5Pa!Rf z_V#wppFhvmty_8Jl~*`(=FAkJ{C+=?NQBPLP8Kg-OlfIpKAi-LgF&1wSKhs@E?lI< z2fhXHii&_TW`IUO`A6H)KgDQ>RY&6E=o&F35Ubf)YQ<>&_F{&15Hg$`2Bvny7hRy ztb5`=QB-x>>`@4TLvx@a*!k<1`Q8)X;>)YQ!app!je9=+F`T-SEnBzn?3S(Ed+)up zx3^CTic>)r0wb3rF&?A3DolMt182^hp(x;IU}S*zPX3k;&z}#LB$kTPHv4+E|NL3v z$s|P%H?JK#z~I0jMLr*cmj?LizptTY)+~yH!7FV_z~}K&Utgc!%;o)f9Uiv*@)zvi zy@#fzX0DEW5{a}VRpDxuEWL{_fB9co@Zk@0@U_=~d{?fvwwC7RW?EWWsH>}^s;Y`$ zFlZM~mStfW2AZbXSySJ8r|lp%os5r-@%GUk-hS&SOO`CbscH=TzMsnKD)#N&!!tkr zZkl#=qNmU4j28T!`Qq1k>xMuR7 zPNgujIo5t_tqpKZO$|5Rcq8-Y&!@e;olq!b^L|0`f^`*&6;)M<$K!lw{S(yJ)lpkl zH>r5ZZ#AE-l!Z!o#IfTnShx^@f@N7(N?4f(w;-lr z*nw=Kdli&)x?E_}fh-{y407SZ1-|o*ZvuI~?da&>_Sf%#H05DKC@oV@j?ar4bLQ&CZ2yR@Pxj0_BMtmkcddwWSIk}O!T08Ldn{q9MQ z_8etwY>cbtzUF2wAHucz2?Bv7E#k2_v%)i2wQ3cySPZAr`GMx2D4M46KN~h{%;{f?*g!JoL~*KY#e)hr7zk%AAupP=Y1% zyefp4Rv9TJreTmX47*(^rNlB#vJ;Z=zoe+Dip%9fQItQsWhtd3l}aI{#Nlw*m&1R` z_k~=z&;+_#6h&cha4_@CGtX=nfTz2=dqZn$>&N9Zs1$CJuWn-&q)X}uDbwD2HC(*ycgt4t?ty+@+wPUlR;uUiAH4mbx%Td3O?Q*$ zf&zQmF8}g8dC^~1Y@56N`Id%svugXbOJqMzNq%PY>BN*-n!)@W7LRXkPCY$Kvh?pylS=lQEeJmx&}%I_=-`FKFUe^aWI+!LPc+s5;Ys_!vxdGhVg=U0pN)oi@O zH(|f%$AZ)c_dD2+Fh64a*igX$#11wJasvDy3=tjxDF+*z&Y+=G2RoXV5q8l~>f;U; zSXkqU26{?8VjPWfP)eX#Y8W|De&GL-eKmQ98S63@?fZFZo^AD{N4pM&9@*aVN_Vbp z^|qYI$u>urZReRrZ&O^TJg>~`(x&v&vs8m8`Pvvv*_d*2mhSJFey=A#Uy1q3A9|9{K22WQ% Jmvv4FO#s~6iZ1{F diff --git a/applications/welcome/static/images/ui-icons_222222_256x240.png b/applications/welcome/static/images/ui-icons_222222_256x240.png deleted file mode 100644 index b273ff111d219c9b9a8b96d57683d0075fb7871a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4369 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 diff --git a/applications/welcome/views/appadmin.html b/applications/welcome/views/appadmin.html index 1d967c2f..541a18bb 100644 --- a/applications/welcome/views/appadmin.html +++ b/applications/welcome/views/appadmin.html @@ -10,8 +10,9 @@ //--> {{if request.function=='index':}} -

    {{=T("Available databases and tables")}}

    +

    {{=T("Available Databases and Tables")}}

    {{if not databases:}}{{=T("No databases in this application")}}{{pass}} + {{for db in sorted(databases):}} {{for table in databases[db].tables:}} {{qry='%s.%s.id>0'%(db,table)}} @@ -28,20 +29,24 @@ {{qry=''}} {{pass}} {{pass}} -

    - {{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}} -

    - [ {{=A(str(T('insert new'))+' '+table,_href=URL('insert',args=[db,table]))}} ] -

    + + + + {{pass}} +
    + {{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}} + + {{=A(str(T('New Record')),_href=URL('insert',args=[db,table]),_class="btn")}} +
    {{pass}} {{elif request.function=='select':}} -

    {{=XML(str(T("database %s select"))%A(request.args[0],_href=URL('index'))) }} +

    {{=XML(str(T("Database %s select"))%A(request.args[0],_href=URL('index'))) }}

    - {{if table:}} - [ {{=A(str(T('insert new %s'))%table,_href=URL('insert',args=[request.args[0],table]))}} ]

    -

    {{=T("Rows in table")}}


    + {{if table:}} + {{=A(str(T('New Record')),_href=URL('insert',args=[request.args[0],table]),_class="btn")}}

    +

    {{=T("Rows in Table")}}


    {{else:}}

    {{=T("Rows selected")}}


    {{pass}} @@ -51,8 +56,8 @@ {{=T('"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN')}}



    {{=T("%s selected", nrows)}}

    - {{if start>0:}}[ {{=A(T('previous 100 rows'),_href=URL('select',args=request.args[0],vars=dict(start=start-100)))}} ]{{pass}} - {{if stop0:}}{{=A(T('previous 100 rows'),_href=URL('select',args=request.args[0],vars=dict(start=start-100)),_class="btn")}}{{pass}} + {{if stop {{linkto=URL('update',args=request.args[0])}} @@ -61,35 +66,35 @@ {{pass}}

    {{=T("Import/Export")}}


    - [
    {{=T("export as csv file")}} ] + {{=T("export as csv file")}} {{=formcsv or ''}} {{elif request.function=='insert':}} -

    {{=T("database")}} {{=A(request.args[0],_href=URL('index'))}} +

    {{=T("Database")}} {{=A(request.args[0],_href=URL('index'))}} {{if hasattr(table,'_primarykey'):}} {{fieldname=table._primarykey[0]}} {{dbname=request.args[0]}} {{tablename=request.args[1]}} {{cond = table[fieldname].type in ['string','text'] and '!=""' or '>0'}} - {{=T("table")}} {{=A(tablename,_href=URL('select',args=dbname,vars=dict(query='%s.%s.%s%s'%(dbname,tablename,fieldname,cond))))}} + {{=T("Table")}} {{=A(tablename,_href=URL('select',args=dbname,vars=dict(query='%s.%s.%s%s'%(dbname,tablename,fieldname,cond))))}} {{else:}} - {{=T("table")}} {{=A(request.args[1],_href=URL('select',args=request.args[0],vars=dict(query='%s.%s.id>0'%tuple(request.args[:2]))))}} + {{=T("Table")}} {{=A(request.args[1],_href=URL('select',args=request.args[0],vars=dict(query='%s.%s.id>0'%tuple(request.args[:2]))))}} {{pass}}

    {{=T("New Record")}}


    {{=form}} {{elif request.function=='update':}} -

    {{=T("database")}} {{=A(request.args[0],_href=URL('index'))}} +

    {{=T("Database")}} {{=A(request.args[0],_href=URL('index'))}} {{if hasattr(table,'_primarykey'):}} {{fieldname=request.vars.keys()[0]}} {{dbname=request.args[0]}} {{tablename=request.args[1]}} {{cond = table[fieldname].type in ['string','text'] and '!=""' or '>0'}} - {{=T("table")}} {{=A(tablename,_href=URL('select',args=dbname,vars=dict(query='%s.%s.%s%s'%(dbname,tablename,fieldname,cond))))}} - {{=T("record")}} {{=A('%s=%s'%request.vars.items()[0],_href=URL('update',args=request.args[:2],vars=request.vars))}} + {{=T("Table")}} {{=A(tablename,_href=URL('select',args=dbname,vars=dict(query='%s.%s.%s%s'%(dbname,tablename,fieldname,cond))))}} + {{=T("Record")}} {{=A('%s=%s'%request.vars.items()[0],_href=URL('update',args=request.args[:2],vars=request.vars))}} {{else:}} - {{=T("table")}} {{=A(request.args[1],_href=URL('select',args=request.args[0],vars=dict(query='%s.%s.id>0'%tuple(request.args[:2]))))}} - {{=T("record id")}} {{=A(request.args[2],_href=URL('update',args=request.args[:3]))}} + {{=T("Table")}} {{=A(request.args[1],_href=URL('select',args=request.args[0],vars=dict(query='%s.%s.id>0'%tuple(request.args[:2]))))}} + {{=T("Record id")}} {{=A(request.args[2],_href=URL('update',args=request.args[:3]))}} {{pass}}

    {{=T("Edit current record")}}



    {{=form}} diff --git a/gluon/cache.py b/gluon/cache.py index bc9cc0f9..3499ac14 100644 --- a/gluon/cache.py +++ b/gluon/cache.py @@ -298,7 +298,7 @@ class CacheOnDisk(CacheAbstract): try: storage = self._open_shelf_with_lock() try: - if not storage.has_key(CacheAbstract.cache_stats_name): + if not CacheAbstract.cache_stats_name in storage: storage[CacheAbstract.cache_stats_name] = { 'hit_total': 0, 'misses': 0, diff --git a/gluon/compileapp.py b/gluon/compileapp.py index e00e6910..5a186c08 100644 --- a/gluon/compileapp.py +++ b/gluon/compileapp.py @@ -50,6 +50,8 @@ is_pypy = settings.global_settings.is_pypy is_gae = settings.global_settings.web2py_runtime_gae is_jython = settings.global_settings.is_jython +pjoin = os.path.join + TEST_CODE = \ r""" def _TEST(): @@ -319,7 +321,7 @@ def local_import_aux(name, reload_force=False, app='welcome'): """ OLD IMPLEMENTATION: items = name.replace('/','.').split('.') - filename, modulepath = items[-1], os.path.join(apath,'modules',*items[:-1]) + filename, modulepath = items[-1], pjoin(apath,'modules',*items[:-1]) imp.acquire_lock() try: file=None @@ -348,11 +350,9 @@ def build_environment(request, response, session, store_current=True): """ Build the environment dictionary into which web2py files are executed. """ - - _validators = validators - _html = html - environment = dict(map(lambda key: (key, getattr(_html, key)), _html.__all__)) - environment.update(map(lambda key: (key, getattr(_validators, key)), _validators.__all__)) + h,v = html,validators + environment = dict((k,getattr(h,k)) for k in h.__all__) + environment.update((k,getattr(v, k)) for k in v.__all__) if not request.env: request.env = Storage() @@ -389,7 +389,7 @@ def build_environment(request, response, session, store_current=True): environment['local_import'] = \ lambda name, reload=False, app=request.application:\ local_import_aux(name,reload,app) - BaseAdapter.set_folder(os.path.join(request.folder, 'databases')) + BaseAdapter.set_folder(pjoin(request.folder, 'databases')) response._view_environment = copy.copy(environment) return environment @@ -419,11 +419,11 @@ def compile_views(folder): Compiles all the views in the application specified by `folder` """ - path = os.path.join(folder, 'views') + path = pjoin(folder, 'views') for file in listdir(path, '^[\w/\-]+(\.\w+)+$'): data = parse_template(file, path) filename = ('views/%s.py' % file).replace('/', '_').replace('\\', '_') - filename = os.path.join(folder, 'compiled', filename) + filename = pjoin(folder, 'compiled', filename) write_file(filename, data) save_pyc(filename) os.unlink(filename) @@ -434,10 +434,10 @@ def compile_models(folder): Compiles all the models in the application specified by `folder` """ - path = os.path.join(folder, 'models') + path = pjoin(folder, 'models') for file in listdir(path, '.+\.py$'): - data = read_file(os.path.join(path, file)) - filename = os.path.join(folder, 'compiled','models',file) + data = read_file(pjoin(path, file)) + filename = pjoin(folder, 'compiled','models',file) mktree(filename) write_file(filename, data) save_pyc(filename) @@ -449,15 +449,15 @@ def compile_controllers(folder): Compiles all the controllers in the application specified by `folder` """ - path = os.path.join(folder, 'controllers') + path = pjoin(folder, 'controllers') for file in listdir(path, '.+\.py$'): - ### why is this here? save_pyc(os.path.join(path, file)) - data = read_file(os.path.join(path,file)) + ### why is this here? save_pyc(pjoin(path, file)) + data = read_file(pjoin(path,file)) exposed = regex_expose.findall(data) for function in exposed: command = data + "\nresponse._vars=response._caller(%s)\n" % \ function - filename = os.path.join(folder, 'compiled', ('controllers/' + filename = pjoin(folder, 'compiled', ('controllers/' + file[:-3]).replace('/', '_') + '_' + function + '.py') write_file(filename, command) @@ -474,18 +474,18 @@ def run_models_in(environment): folder = environment['request'].folder c = environment['request'].controller f = environment['request'].function - cpath = os.path.join(folder, 'compiled') + cpath = pjoin(folder, 'compiled') if os.path.exists(cpath): for model in listdir(cpath, '^models_\w+\.pyc$', 0): restricted(read_pyc(model), environment, layer=model) - path = os.path.join(cpath, 'models') + path = pjoin(cpath, 'models') models = listdir(path, '^\w+\.pyc$',0,sort=False) compiled=True else: - path = os.path.join(folder, 'models') + path = pjoin(folder, 'models') models = listdir(path, '^\w+\.py$',0,sort=False) compiled=False - paths = (path, os.path.join(path,c), os.path.join(path,c,f)) + paths = (path, pjoin(path,c), pjoin(path,c,f)) for model in models: if not os.path.split(model)[0] in paths and c!='appadmin': continue @@ -509,11 +509,11 @@ def run_controller_in(controller, function, environment): # if compiled should run compiled! folder = environment['request'].folder - path = os.path.join(folder, 'compiled') + path = pjoin(folder, 'compiled') badc = 'invalid controller (%s/%s)' % (controller, function) badf = 'invalid function (%s/%s)' % (controller, function) if os.path.exists(path): - filename = os.path.join(path, 'controllers_%s_%s.pyc' + filename = pjoin(path, 'controllers_%s_%s.pyc' % (controller, function)) if not os.path.exists(filename): raise HTTP(404, @@ -528,7 +528,7 @@ def run_controller_in(controller, function, environment): [add_path_first(path) for path in paths] # TESTING END - filename = os.path.join(folder, 'controllers/%s.py' + filename = pjoin(folder, 'controllers/%s.py' % controller) if not os.path.exists(filename): raise HTTP(404, @@ -539,7 +539,7 @@ def run_controller_in(controller, function, environment): code += TEST_CODE restricted(code, environment, layer=filename) else: - filename = os.path.join(folder, 'controllers/%s.py' + filename = pjoin(folder, 'controllers/%s.py' % controller) if not os.path.exists(filename): raise HTTP(404, @@ -576,19 +576,20 @@ def run_view_in(environment): request = environment['request'] response = environment['response'] + view = response.view folder = request.folder - path = os.path.join(folder, 'compiled') - badv = 'invalid view (%s)' % response.view + path = pjoin(folder, 'compiled') + badv = 'invalid view (%s)' % view patterns = response.generic_patterns or [] regex = re.compile('|'.join(map(fnmatch.translate, patterns))) short_action = '%(controller)s/%(function)s.%(extension)s' % request allow_generic = patterns and regex.search(short_action) - if not isinstance(response.view, str): - ccode = parse_template(response.view, os.path.join(folder, 'views'), + if not isinstance(view, str): + ccode = parse_template(view, pjoin(folder, 'views'), context=environment) restricted(ccode, environment, 'file stream') elif os.path.exists(path): - x = response.view.replace('/', '_') + x = view.replace('/', '_') files = ['views_%s.pyc' % x] if allow_generic: files.append('views_generic.%s.pyc' % request.extension) @@ -599,7 +600,7 @@ def run_view_in(environment): files.append('views_generic.pyc') # end backward compatibility code for f in files: - filename = os.path.join(path,f) + filename = pjoin(path,f) if os.path.exists(filename): code = read_pyc(filename) restricted(code, environment, layer=filename) @@ -608,10 +609,10 @@ def run_view_in(environment): rewrite.thread.routes.error_message % badv, web2py_error=badv) else: - filename = os.path.join(folder, 'views', response.view) + filename = pjoin(folder, 'views', view) if not os.path.exists(filename) and allow_generic: - response.view = 'generic.' + request.extension - filename = os.path.join(folder, 'views', response.view) + view = 'generic.' + request.extension + filename = pjoin(folder, 'views', view) if not os.path.exists(filename): raise HTTP(404, rewrite.thread.routes.error_message % badv, @@ -619,12 +620,12 @@ def run_view_in(environment): layer = filename if is_gae: ccode = getcfs(layer, filename, - lambda: compile2(parse_template(response.view, - os.path.join(folder, 'views'), + lambda: compile2(parse_template(view, + pjoin(folder, 'views'), context=environment),layer)) else: - ccode = parse_template(response.view, - os.path.join(folder, 'views'), + ccode = parse_template(view, + pjoin(folder, 'views'), context=environment) restricted(ccode, environment, layer) @@ -633,8 +634,8 @@ def remove_compiled_application(folder): Deletes the folder `compiled` containing the compiled application. """ try: - shutil.rmtree(os.path.join(folder, 'compiled')) - path = os.path.join(folder, 'controllers') + shutil.rmtree(pjoin(folder, 'compiled')) + path = pjoin(folder, 'controllers') for file in listdir(path,'.*\.pyc$',drop=False): os.unlink(file) except OSError: @@ -646,7 +647,7 @@ def compile_application(folder): Compiles all models, views, controller for the application in `folder`. """ remove_compiled_application(folder) - os.mkdir(os.path.join(folder, 'compiled')) + os.mkdir(pjoin(folder, 'compiled')) compile_models(folder) compile_controllers(folder) compile_views(folder) diff --git a/gluon/globals.py b/gluon/globals.py index 7bf41549..5e94b726 100644 --- a/gluon/globals.py +++ b/gluon/globals.py @@ -117,7 +117,8 @@ class Request(Storage): user_agent_parser.detect(self.env.http_user_agent) user_agent = Storage(user_agent) for key,value in user_agent.items(): - if isinstance(value,dict): user_agent[key] = Storage(value) + if isinstance(value,dict): + user_agent[key] = Storage(value) return user_agent def requires_https(self): @@ -222,9 +223,9 @@ class Response(Storage): return page def include_meta(self): - s = '\n' - for key,value in (self.meta or {}).items(): - s += '\n' % (key,xmlescape(value)) + s = '\n'.join( + '\n' % (k,xmlescape(v)) + for k,v in (self.meta or {}).iteritems()) self.write(s,escape=False) def include_files(self): @@ -297,14 +298,15 @@ class Response(Storage): default to the last request argument otherwise) """ + headers = self.headers # for attachment settings and backward compatibility - keys = [item.lower() for item in self.headers] + keys = [item.lower() for item in headers] if attachment: if filename is None: attname = "" else: attname = filename - self.headers["Content-Disposition"] = \ + headers["Content-Disposition"] = \ "attachment;filename=%s" % attname if not request: @@ -313,30 +315,31 @@ class Response(Storage): stream_file_or_304_or_206(stream, chunk_size=chunk_size, request=request, - headers=self.headers) + headers=headers) # ## the following is for backward compatibility if hasattr(stream, 'name'): filename = stream.name if filename and not 'content-type' in keys: - self.headers['Content-Type'] = contenttype(filename) + headers['Content-Type'] = contenttype(filename) if filename and not 'content-length' in keys: try: - self.headers['Content-Length'] = \ + headers['Content-Length'] = \ os.path.getsize(filename) except OSError: pass - + + env = request.env # Internet Explorer < 9.0 will not allow downloads over SSL unless caching is enabled - if request.is_https and isinstance(request.env.http_user_agent,str) and \ - not re.search(r'Opera', request.env.http_user_agent) and \ - re.search(r'MSIE [5-8][^0-9]', request.env.http_user_agent): - self.headers['Pragma'] = 'cache' - self.headers['Cache-Control'] = 'private' + if request.is_https and isinstance(env.http_user_agent,str) and \ + not re.search(r'Opera', env.http_user_agent) and \ + re.search(r'MSIE [5-8][^0-9]', env.http_user_agent): + headers['Pragma'] = 'cache' + headers['Cache-Control'] = 'private' - if request and request.env.web2py_use_wsgi_file_wrapper: - wrapped = request.env.wsgi_file_wrapper(stream, chunk_size) + if request and env.web2py_use_wsgi_file_wrapper: + wrapped = env.wsgi_file_wrapper(stream, chunk_size) else: wrapped = streamer(stream, chunk_size=chunk_size) return wrapped @@ -364,11 +367,13 @@ class Response(Storage): (filename, stream) = field.retrieve(name) except IOError: raise HTTP(404) - self.headers['Content-Type'] = contenttype(name) + headers = self.headers + headers['Content-Type'] = contenttype(name) if attachment: - self.headers['Content-Disposition'] = \ - "attachment; filename=%s" % filename - return self.stream(stream, chunk_size = chunk_size, request=request) + headers['Content-Disposition'] = \ + 'attachment; filename=%s' % filename + return self.stream(stream, chunk_size=chunk_size, request=request) + def json(self, data, default=None): return json(data, default = default or custom_json) @@ -405,8 +410,15 @@ class Response(Storage): dbstats = [TABLE(*[TR(PRE(row[0]),'%.2fms' % (row[1]*1000)) \ for row in i.db._timings]) \ for i in thread.instances] + dbtables = dict([(i.uri, {'defined': sorted(list(set(i.db.tables) - + set(i.db._LAZY_TABLES.keys()))) or + '[no defined tables]', + 'lazy': sorted(i.db._LAZY_TABLES.keys()) or + '[no lazy tables]'}) + for i in thread.instances]) else: dbstats = [] # if no db or on GAE + dbtables = {} u = web2py_uuid() return DIV( BUTTON('design',_onclick="document.location='%s'" % admin), @@ -416,6 +428,8 @@ class Response(Storage): DIV(BEAUTIFY(current.session),_class="hidden",_id="session-%s"%u), BUTTON('response',_onclick="jQuery('#response-%s').slideToggle()"%u), DIV(BEAUTIFY(current.response),_class="hidden",_id="response-%s"%u), + BUTTON('db tables',_onclick="jQuery('#db-tables-%s').slideToggle()"%u), + DIV(BEAUTIFY(dbtables),_class="hidden",_id="db-tables-%s"%u), BUTTON('db stats',_onclick="jQuery('#db-stats-%s').slideToggle()"%u), DIV(BEAUTIFY(dbstats),_class="hidden",_id="db-stats-%s"%u), SCRIPT("jQuery('.hidden').hide()") @@ -452,14 +466,15 @@ class Session(Storage): response.session_id_name = 'session_id_%s' % masterapp.lower() # Load session data from cookie - + cookies = request.cookies + if cookie_key: response.session_cookie_key = cookie_key response.session_cookie_key2 = hashlib.md5(cookie_key).digest() - cookie_name = request.application.lower()+'_session_data' + cookie_name = masterapp.lower()+'_session_data' response.session_cookie_name = cookie_name - if cookie_data in request.cookies: - cookie_value = request.cookies[cookie_name].value + if cookie_name in cookies: + cookie_value = cookies[cookie_name].value cookie_parts = cookie_value.split(":") enc = cookie_parts[2] cipher = AES.new(cookie_key) @@ -477,9 +492,9 @@ class Session(Storage): return response.session_new = False client = request.client and request.client.replace(':', '.') - if response.session_id_name in request.cookies: + if response.session_id_name in cookies: response.session_id = \ - request.cookies[response.session_id_name].value + cookies[response.session_id_name].value if regex_session_id.match(response.session_id): response.session_filename = \ os.path.join(up(request.folder), masterapp, @@ -532,38 +547,35 @@ class Session(Storage): table_migrate = False tname = tablename + '_' + masterapp table = db.get(tname, None) + Field = db.Field if table is None: - table = db.define_table( + db.define_table( tname, - db.Field('locked', 'boolean', default=False), - db.Field('client_ip', length=64), - db.Field('created_datetime', 'datetime', + Field('locked', 'boolean', default=False), + Field('client_ip', length=64), + Field('created_datetime', 'datetime', default=request.now), - db.Field('modified_datetime', 'datetime'), - db.Field('unique_key', length=64), - db.Field('session_data', 'blob'), + Field('modified_datetime', 'datetime'), + Field('unique_key', length=64), + Field('session_data', 'blob'), migrate=table_migrate, ) + table = db[tname] # to allow for lazy table try: - # Get session data out of the database - - # Key comes from the cookie - key = request.cookies[response.session_id_name].value + # Get session data out of the database + # Key comes from the cookie + key = cookies[response.session_id_name].value (record_id, unique_key) = key.split(':') if record_id == '0': raise Exception, 'record_id == 0' - # Select from database. + # Select from database rows = db(table.id == record_id).select() - - # Make sure the session data exists in the database + # Make sure the session data exists in the database if len(rows) == 0 or rows[0].unique_key != unique_key: raise Exception, 'No record' - - # rows[0].update_record(locked=True) - - - # Unpickle the data + # rows[0].update_record(locked=True) + # Unpickle the data session_data = cPickle.loads(rows[0].session_data) self.update(session_data) except Exception: @@ -573,8 +585,9 @@ class Session(Storage): response._dbtable_and_field = \ (response.session_id_name, table, record_id, unique_key) response.session_id = '%s:%s' % (record_id, unique_key) - response.cookies[response.session_id_name] = response.session_id - response.cookies[response.session_id_name]['path'] = '/' + rcookies = response.cookies + rcookies[response.session_id_name] = response.session_id + rcookies[response.session_id_name]['path'] = '/' self.__hash = hashlib.md5(str(self)).digest() if self.flash: (response.flash, self.flash) = (self.flash, None) diff --git a/gluon/html.py b/gluon/html.py index b758c597..2d6b8131 100644 --- a/gluon/html.py +++ b/gluon/html.py @@ -296,7 +296,8 @@ def URL( if other.endswith('/'): other += '/' # add trailing slash to make last trailing empty arg explicit - if vars.has_key('_signature'): vars.pop('_signature') + if '_signature' in vars: + vars.pop('_signature') list_vars = [] for (key, vals) in sorted(vars.items()): if not isinstance(vals, (list, tuple)): @@ -387,7 +388,7 @@ def verifyURL(request, hmac_key=None, hash_vars=True, salt=None, user_signature= """ - if not request.get_vars.has_key('_signature'): + if not '_signature' in request.get_vars: return False # no signature in the request URL # check if user_signature requires @@ -484,15 +485,17 @@ class XmlComponent(object): components += [other] return CAT(*components) - def add_class(self, name): + def add_class(self, name): """ add a class to _class attribute """ - classes = set(self['_class'].split())|set(name.split()) + c = self['_class'] + classes = (set(c.split()) if c else set())|set(name.split()) self['_class'] = ' '.join(classes) if classes else None return self def remove_class(self, name): """ remove a class from _class attribute """ - classes = set(self['_class'].split())-set(name.split()) + c = self['_class'] + classes = (set(c.split()) if c else set())-set(name.split()) self['_class'] = ' '.join(classes) if classes else None return self @@ -656,17 +659,17 @@ class DIV(XmlComponent): self.attributes = attributes self._fixup() # converts special attributes in components attributes - self._postprocessing() self.parent = None for c in self.components: self._setnode(c) + self._postprocessing() def update(self, **kargs): """ dictionary like updating of the tag attributes """ - for (key, value) in kargs.items(): + for (key, value) in kargs.iteritems(): self[key] = value return self @@ -811,7 +814,9 @@ class DIV(XmlComponent): c.latest = self.latest c.session = self.session c.formname = self.formname - if hideerror: c['hideerror'] = hideerror + if hideerror and not \ + self.attributes.get('hideerror',False): + c['hideerror'] = hideerror newstatus = c._traverse(status,hideerror) and newstatus # for input, textarea, select, option @@ -1038,7 +1043,7 @@ class DIV(XmlComponent): tag = getattr(self,'tag').replace('/', '') if args and tag not in args: check = False - for (key, value) in kargs.items(): + for (key, value) in kargs.iteritems(): if key not in ['first_only', 'replace', 'find_text']: if isinstance(value, (str, int)): if self[key] != str(value): @@ -1109,16 +1114,15 @@ class DIV(XmlComponent): sibs = [s for s in self.parent.components if not s == self] matches = [] first_only = False - if kargs.has_key("first_only"): - first_only = kargs["first_only"] - del kargs["first_only"] + if 'first_only' in kargs: + first_only = kargs.pop('first_only') for c in sibs: try: check = True tag = getattr(c,'tag').replace("/","") if args and tag not in args: check = False - for (key, value) in kargs.items(): + for (key, value) in kargs.iteritems(): if c[key] != value: check = False if check: @@ -1682,14 +1686,14 @@ class INPUT(DIV): if name is None or name == '': return True name = str(name) - + request_vars_get = self.request_vars.get if self['_type'] != 'checkbox': self['old_value'] = self['value'] or self['_value'] or '' - value = self.request_vars.get(name, '') + value = request_vars_get(name, '') self['value'] = value else: self['old_value'] = self['value'] or False - value = self.request_vars.get(name) + value = request_vars_get(name) if isinstance(value, (tuple, list)): self['value'] = self['_value'] in value else: @@ -1932,14 +1936,15 @@ class FORM(DIV): # check formname and formkey status = True - if self.session: - formkey = self.session.get('_formkey[%s]' % self.formname, None) + request_vars = self.request_vars + if session: + formkey = session.get('_formkey[%s]' % formname, None) # check if user tampering with form and void CSRF - if formkey != self.request_vars._formkey: + if formkey != request_vars._formkey: status = False - if self.formname != self.request_vars._formname: + if formname != request_vars._formname: status = False - if status and self.session: + if status and session: # check if editing a record that has been modified by the server if hasattr(self,'record_hash') and self.record_hash != formkey: status = False @@ -1983,10 +1988,10 @@ class FORM(DIV): def hidden_fields(self): c = [] + attr = self.attributes.get('hidden',{}) if 'hidden' in self.attributes: - for (key, value) in self.attributes.get('hidden',{}).items(): - c.append(INPUT(_type='hidden', _name=key, _value=value)) - + c = [INPUT(_type='hidden', _name=key, _value=value) + for (key, value) in attr.iteritems()] if hasattr(self, 'formkey') and self.formkey: c.append(INPUT(_type='hidden', _name='_formkey', _value=self.formkey)) @@ -2055,7 +2060,7 @@ class FORM(DIV): onsuccess(self) if next: if self.vars: - for key,value in self.vars.items(): + for key,value in self.vars.iteritems(): next = next.replace('[%s]' % key, urllib.quote(str(value))) if not next.startswith('/'): @@ -2116,11 +2121,11 @@ class FORM(DIV): inputs = [INPUT(_type='button', _value=name, _onclick=FORM.REDIRECT_JS % link) \ - for name,link in buttons.items()] + for name,link in buttons.iteritems()] inputs += [INPUT(_type='hidden', _name=name, _value=value) - for name,value in hidden.items()] + for name,value in hidden.iteritems()] form = FORM(INPUT(_type='submit',_value=text),*inputs) form.process() return form @@ -2268,10 +2273,11 @@ class MENU(DIV): select = SELECT(**self.attributes) for item in data: if len(item) <= 4 or item[4] == True: - if item[2]: - select.append(OPTION(CAT(prefix, item[0]), _value=item[2], _selected=item[1])) - if len(item)>3 and len(item[3]): - self.serialize_mobile(item[3], select, prefix = CAT(prefix, item[0], '/')) + select.append(OPTION(CAT(prefix, item[0]), + _value=item[2], _selected=item[1])) + if len(item)>3 and len(item[3]): + self.serialize_mobile( + item[3], select, prefix = CAT(prefix, item[0], '/')) select['_onchange'] = 'window.location=this.value' return select @@ -2323,7 +2329,7 @@ def test(): >>> print form.accepts({'myvar':'34'}, formname=None) False >>> print form.xml() -
    invalid expression
    +
    invalid expression
    >>> print form.accepts({'myvar':'4'}, formname=None, keepvalues=True) True >>> print form.xml() @@ -2337,7 +2343,7 @@ def test(): >>> print form.accepts({'myvar':'as df'}, formname=None) False >>> print form.xml() -
    only alphanumeric!
    +
    only alphanumeric!
    >>> session={} >>> form=FORM(INPUT(value=\"Hello World\", _name=\"var\", requires=IS_MATCH('^\w+$'))) >>> if form.accepts({}, session,formname=None): print 'passed' diff --git a/gluon/http.py b/gluon/http.py index c4389b9e..548ac6d9 100644 --- a/gluon/http.py +++ b/gluon/http.py @@ -77,41 +77,45 @@ class HTTP(BaseException): str(cookie)[11:] for cookie in cookies.values()] def to(self, responder): - if self.status in defined_status: - status = '%d %s' % (self.status, defined_status[self.status]) + status = self.status + headers = self.headers + if status in defined_status: + status = '%d %s' % (status, defined_status[status]) else: - status = str(self.status) + ' ' - if not 'Content-Type' in self.headers: - self.headers['Content-Type'] = 'text/html; charset=UTF-8' + status = str(status) + ' ' + if not 'Content-Type' in headers: + headers['Content-Type'] = 'text/html; charset=UTF-8' body = self.body if status[:1] == '4': if not body: body = status if isinstance(body, str): - if len(body)<512 and self.headers['Content-Type'].startswith('text/html'): + if len(body)<512 and headers['Content-Type'].startswith('text/html'): body += '' % ('x'*512) ### trick IE - self.headers['Content-Length'] = len(body) - headers = [] - for (k, v) in self.headers.items(): + headers['Content-Length'] = len(body) + rheaders = [] + for k, v in headers.iteritems(): if isinstance(v, list): - for item in v: - headers.append((k, str(item))) + rheaders += [(k, str(item)) for item in v] else: - headers.append((k, str(v))) - responder(status, headers) - if hasattr(body, '__iter__') and not isinstance(self.body, str): + rheaders.append((k, str(v))) + responder(status, rheaders) + if isinstance(body,str): + return [body] + elif hasattr(body, '__iter__'): return body - return [str(body)] + else: + return [str(body)] @property def message(self): - ''' + """ compose a message describing this exception - "status defined_status [web2py_error]" + "status defined_status [web2py_error]" message elements that are not defined are omitted - ''' + """ msg = '%(status)d' if self.status in defined_status: msg = '%(status)d %(defined_status)s' diff --git a/gluon/languages.py b/gluon/languages.py index 2c8231d5..f2d78c52 100644 --- a/gluon/languages.py +++ b/gluon/languages.py @@ -10,7 +10,7 @@ Plural subsystem is created by Vladyslav Kozlovskyy (Ukraine) """ -from os import path as ospath, stat as ostat, sep as osep +import os import re from utf8 import Utf8 from cgi import escape @@ -20,7 +20,7 @@ import marshal import copy_reg from fileutils import abspath, listdir import settings -from cfs import getcfs, cfs +from cfs import getcfs from thread import allocate_lock from html import XML, xmlescape from contrib.markmin.markmin2html import render, markmin_escape @@ -28,10 +28,37 @@ from string import maketrans __all__ = ['translator', 'findT', 'update_all_languages'] +ospath = os.path +ostat = os.stat +osep = os.sep +isdir = os.path.isdir +is_gae = settings.global_settings.web2py_runtime_gae + +DEFAULT_LANGUAGE = 'en' + +# DEFAULT PLURAL-FORMS RULES: +# language doesn't use plural forms +DEFAULT_NPLURALS = 1 +# only one singular/plural form is used +DEFAULT_GET_PLURAL_ID = lambda n: 0 +# word is unchangeable +DEFAULT_CONSTRUCTOR_PLURAL_FORM = lambda word, plural_id: word + +def safe_eval(text): + if text.strip(): + try: + import ast + return ast.literal_eval(text) + except ImportError: + return eval(text,{},{}) + return None + # used as default filter in translator.M() -markmin = lambda s: render( regex_param.sub( - lambda m: '{' + markmin_escape(m.group('s')) + '}', - s ), sep='br', autolinks=None, id_prefix='' ) +def markmin_aux(m): + return '{%s}' % markmin_escape(m.group('s')) +def markmin(s): + return render(regex_param.sub(markmin_aux,s), + sep='br', autolinks=None, id_prefix='') NUMBERS = (int,long,float) @@ -49,28 +76,24 @@ regex_param=re.compile(r'{(?P.+?)}') regex_language = \ re.compile('^([a-zA-Z]{2})(\-[a-zA-Z]{2})?(\-[a-zA-Z]+)?$') regex_langfile = re.compile('^[a-zA-Z]{2}(-[a-zA-Z]{2})?\.py$') -regex_langinfo = re.compile("^[^'\"]*['\"]([^'\"]*)['\"]\s*:\s*['\"]([^'\"]*)['\"].*$") regex_backslash = re.compile(r"\\([\\{}%])") regex_plural = re.compile('%({.+?})') regex_plural_dict = re.compile('^{(?P[^()[\]][^()[\]]*?)\((?P[^()\[\]]+)\)}$') # %%{word(varname or number)} regex_plural_tuple = re.compile('^{(?P[^[\]()]+)(?:\[(?P\d+)\])?}$') # %%{word[index]} or %%{word} -regex_plural_q = re.compile('^asdf$') # %%{?word?cnt}, %%{??cnt} or %%{?cnt} regex_plural_rules = re.compile('^plural_rules-[a-zA-Z]{2}(-[a-zA-Z]{2})?\.py$') -upper_fun = lambda s: unicode(s,'utf-8').upper().encode('utf-8') -title_fun = lambda s: unicode(s,'utf-8').title().encode('utf-8') -cap_fun = lambda s: unicode(s,'utf-8').capitalize().encode('utf-8') - -# DEFAULT PLURAL-FORMS RULES: -default_nplurals = 1 # language doesn't use plural forms -default_get_plural_id = lambda n: 0 # only one singular/plural form is used -default_construct_plural_form = lambda word, plural_id: word # word is unchangeable - +# UTF8 helper functions +def upper_fun(s): + return unicode(s,'utf-8').upper().encode('utf-8') +def title_fun(s): + return unicode(s,'utf-8').title().encode('utf-8') +def cap_fun(s): + return lambda s: unicode(s,'utf-8').capitalize().encode('utf-8') ttab_in = maketrans("\\%{}", '\x1c\x1d\x1e\x1f') ttab_out = maketrans('\x1c\x1d\x1e\x1f', "\\%{}") # cache of translated messages: -# of structure: +# global_language_cache: # { 'languages/xx.py': # ( {"def-message": "xx-message", # ... @@ -78,35 +101,38 @@ ttab_out = maketrans('\x1c\x1d\x1e\x1f', "\\%{}") # 'languages/yy.py': ( {dict}, lock_object ) # ... # } -tcache={} + +global_language_cache={} def get_from_cache(cache, val, fun): - lock=cache[1] + lang_dict, lock = cache lock.acquire() try: - result=cache[0].get(val); + result = lang_dict.get(val); finally: lock.release() if result: return result lock.acquire() try: - result=cache[0].setdefault(val, fun()) + result = lang_dict.setdefault(val, fun()) finally: lock.release() return result -def clear_cache(cache): - lock=cache[1] +def clear_cache(filename): + cache = global_language_cache.setdefault( + filename, ({}, allocate_lock())) + lang_dict, lock = cache lock.acquire() try: - cache[0].clear(); + lang_dict.clear(); finally: lock.release() - def lang_sampling(lang_tuple, langlist): - """ search *lang_tuple* in *langlist* + """ + search *lang_tuple* in *langlist* Args: lang_tuple (tuple of strings): ('aa'[[,'-bb'],'-cc']) @@ -137,32 +163,28 @@ def lang_sampling(lang_tuple, langlist): def read_dict_aux(filename): - fp = portalocker.LockedFile(filename, 'r') - lang_text = fp.read().replace('\r\n', '\n') - fp.close() - # clear cache of processed messages: - clear_cache(tcache.setdefault(filename, ({}, allocate_lock()))) - if not lang_text.strip(): - return {} + lang_text = portalocker.read_locked(filename).replace('\r\n', '\n') + clear_cache(filename) try: - return eval(lang_text) + return safe_eval(lang_text) or {} except Exception, e: - status='Syntax error in %s (%s)' % (filename, e) + status = 'Syntax error in %s (%s)' % (filename, e) logging.error(status) return {'__corrupted__':status} - def read_dict(filename): - """ return dictionary with translation messages + """ + return dictionary with translation messages """ return getcfs('lang:'+filename, filename, lambda: read_dict_aux(filename)) def get_lang_info(lang, langdir): - """retrieve lang information from *langdir*/*lang*.py file. - Read few strings from lang.py file until keys !langname!, - !langcode! or keys greater then '!*' were found + """ + retrieve lang information from *langdir*/*lang*.py file. + Read few strings from lang.py file until keys !langname!, + !langcode! or keys greater then '!*' were found args: lang (str): lang-code or 'default' @@ -173,159 +195,78 @@ def get_lang_info(lang, langdir): e.g.: ('en', 'English', 1338549043.0) """ filename = ospath.join(langdir, lang+'.py') - langcode=langname='' - f = portalocker.LockedFile(filename, 'r') - try: - while not (langcode and langname): - line = f.readline() - if not line: - break - match=regex_langinfo.match(line) - if match: - k = match.group(1) - if k == '!langname!': - langname = match.group(2) - elif k == '!langcode!': - langcode = match.group(2) - elif k[0:1] > '!': - break - finally: - f.close() - if not langcode: - langcode = lang if lang != 'default' else 'en' - return langcode, langname or langcode, ostat(filename).st_mtime + d = read_dict(filename) + langcode = d.get('!langcode!',DEFAULT_LANGUAGE) + langname = d.get('!langname!',langcode) + return (langcode, langname or langcode, ostat(filename).st_mtime) -def read_possible_languages_aux(langdir): +def read_possible_languages(appdir): langs = {} # scan languages directory for langfiles: - for langfile in [f for f in - listdir(langdir, regex_langfile) + - listdir(langdir, '^default\.py$') - if osep not in f]: - lang=langfile[:-3] - langs[lang]=get_lang_info(lang, langdir) - if 'default' not in langs: + langdir = ospath.join(appdir,'languages') + for filename in os.listdir(langdir): + if regex_langfile.match(filename) or filename=='default.py': + lang = filename[:-3] + langs[lang] = get_lang_info(lang, langdir) + if not 'en' in langs: # if default.py is not found, add default value: - langs['default'] = ('en', 'English', 0) - deflang=langs['default'] - if deflang[0] not in langs: - # create language from default.py: - langs[deflang[0]] = (deflang[0], deflang[1], 0) + langs['en'] = ('en', 'English', 0) return langs -def read_possible_languages(path): - lang_path = ospath.join(path, 'languages') - return getcfs('langs:'+lang_path, lang_path, - lambda: read_possible_languages_aux(lang_path)) - - -def read_plural_rules_aux(filename): - """retrieve plural rules from rules/*plural_rules-lang*.py file. +def read_global_plural_rules(filename): + """ + retrieve plural rules from rules/*plural_rules-lang*.py file. args: filename (str): plural_rules filename returns: - tuple(nplurals, get_plural_id, construct_plural_form) - e.g.: (3, , ) + (nplurals, get_plural_id, construct_plural_form, status) + e.g.: (3, , , ok) """ - f = portalocker.LockedFile(filename, 'r') - plural_py=f.read().replace('\r\n','\n') - f.close() + env = {} + data = portalocker.read_locked(filename) try: - exec(plural_py) - nplurals=locals().get('nplurals', default_nplurals) - get_plural_id=locals().get('get_plural_id', default_get_plural_id) - construct_plural_form=locals().get('construct_plural_form', - default_construct_plural_form) + exec(data) in env status='ok' except Exception, e: - nplurals=default_nplurals - get_plural_id=default_get_plural_id - construct_plural_form=default_construct_plural_form status='Syntax error in %s (%s)' % (filename, e) logging.error(status) + nplurals = env.get('nplurals', DEFAULT_NPLURALS) + get_plural_id = env.get('get_plural_id', DEFAULT_GET_PLURAL_ID) + construct_plural_form = env.get('construct_plural_form', + DEFAULT_CONSTRUCTOR_PLURAL_FORM) return (nplurals, get_plural_id, construct_plural_form, status) -def read_plural_rules(lang): - filename = abspath('gluon','contrib','rules', 'plural_rules-%s.py' % lang) - return getcfs('plural_rules-'+lang, filename, - lambda: read_plural_rules_aux(filename)) -pcache={} def read_possible_plurals(): - """ create list of all possible plural rules files - result is cached to increase speed """ - global pcache + create list of all possible plural rules files + result is cached to increase speed + """ pdir = abspath('gluon','contrib','rules') plurals = {} # scan rules directory for plural_rules-*.py files: - for pname in [f for f in listdir(pdir, regex_plural_rules) - if osep not in f]: - - lang=pname[13:-3] - fname=ospath.join(pdir, pname) - mtime=ostat(fname).st_mtime - if lang in pcache and pcache[lang][2] == mtime: - # if plural_file's mtime wasn't changed - use previous value: - plurals[lang]=pcache[lang] - else: - # otherwise, reread plural_rules-file: - if 'plural_rules-'+lang in cfs: - n,f1,f2,status=read_plural_rules(lang) - else: - n,f1,f2,status=read_plural_rules_aux(fname) - plurals[lang]=(n, pname, mtime, status) - pcache=plurals - return pcache - -def get_plural_rules(languages): - """get plural-forms rules for language *lang* - if rules not found - default rules will be return and lang=='unknown' - - args: - lang (str): the languages, for one of which the plural-forms is return - - returns: - tuples(lang, plural_rules-filename, nplurals, - get_plural_id(), construct_plural_form(), status) - """ - if isinstance(languages, str): - languages = [languages] - - all_plurals=read_possible_plurals() - for lang in languages: - match_language = regex_language.match(lang.strip().lower()) - if match_language: - match_language = tuple(part - for part in match_language.groups() - if part) - lang = lang_sampling(match_language, all_plurals.keys()) - if lang: - ( nplurals, - get_plural_id, - construct_plural_form, - status - ) = read_plural_rules(lang) - return (lang, all_plurals[lang][1], nplurals, - get_plural_id, - construct_plural_form, - status) - return ('unknown', None, default_nplurals, - default_get_plural_id, - default_construct_plural_form, - 'ok') + for pname in os.listdir(pdir): + if not isdir(pname) and regex_plural_rules.match(pname): + lang = pname[13:-3] + fname = ospath.join(pdir, pname) + n, f1, f2, status = read_global_plural_rules(fname) + if status == 'ok': + plurals[lang] = (lang, n, f1, f2, pname) + plurals['default'] = ('default', + DEFAULT_NPLURALS, + DEFAULT_GET_PLURAL_ID, + DEFAULT_CONSTRUCTOR_PLURAL_FORM, + None) + return plurals +PLURAL_RULES = read_possible_plurals() def read_plural_dict_aux(filename): - fp = portalocker.LockedFile(filename, 'r') - lang_text = fp.read().replace('\r\n', '\n') - fp.close() - if not lang_text.strip(): - return {} + lang_text = portalocker.read_locked(filename).replace('\r\n', '\n') try: - return eval(lang_text) + return eval(lang_text) or {} except Exception, e: status='Syntax error in %s (%s)' % (filename, e) logging.error(status) @@ -335,7 +276,6 @@ def read_plural_dict(filename): return getcfs('plurals:'+filename, filename, lambda: read_plural_dict_aux(filename)) - def write_plural_dict(filename, contents): if '__corrupted__' in contents: return @@ -466,13 +406,10 @@ class lazyT(object): return lazyT(self.m, symbols, self.T, self.f, self.t, self.M) class translator(object): - """ this class is instantiated by gluon.compileapp.build_environment as the T object - :: - T.force(None) # turns off translation T.force('fr, it') # forces web2py to translate using fr.py or it.py @@ -480,27 +417,21 @@ class translator(object): notice 1: there is no need to force since, by default, T uses http_accept_language to determine a translation file. - - notice 2: en and en-en are considered different languages! - - notice 3: if language xx-yy is not found force() probes other similar - languages using such algorithm: xx-yy.py -> xx.py -> xx-yy*.py -> xx*.py + notice 2: + en and en-en are considered different languages! + notice 3: + if language xx-yy is not found force() probes other similar + languages using such algorithm: + xx-yy.py -> xx.py -> xx-yy*.py -> xx*.py """ def __init__(self, request): - global tcache self.request = request self.folder = request.folder - dfile = ospath.join(self.folder,'languages','default.py') - if ospath.exists(dfile): - self.default_language_file = dfile - self.default_t = read_dict(dfile) - else: # languages/default.py is not found - self.default_language_file = ospath.join(self.folder, 'languages','') - self.default_t = {} - self.cache = tcache.setdefault(self.default_language_file, ({}, allocate_lock())) - self.current_languages = [self.get_possible_languages_info('default')[0]] + self.langpath = ospath.join(self.folder,'languages') + self.filenames = set(os.listdir(self.langpath)) self.http_accept_language = request.env.http_accept_language + # self.cache # filled in self.force() # self.accepted_language = None # filled in self.force() # self.language_file = None # filled in self.force() # self.plural_language = None # filled in self.force() @@ -511,12 +442,89 @@ class translator(object): # self.plural_file = None # filled in self.force() # self.plural_dict = None # filled in self.force() # self.plural_status = None # filled in self.force() - self.requested_languages = self.force(self.http_accept_language) + + self.requested_languages = \ + self.force(self.http_accept_language) self.lazy = True self.otherTs = {} self.filter = markmin self.ftag = 'markmin' + def get_possible_languages(self): + return [lang[:-3] for lang in self.filenames \ + if regex_langfile.match(lang)] + + def set_current_languages(self, *languages): + """ + set current AKA "default" languages + setting one of this languages makes force() function + turn translation off to use default language + """ + if len(languages) == 1 and isinstance( + languages[0], (tuple, list)): + languages = languages[0] + self.current_languages = languages + self.force(self.http_accept_language) + + def set_plural(self, language): + """ + initialize plural forms subsystem + invoked from self.force() + """ + lang = language[:2] + (self.plural_language, + self.nplurals, + self.get_plural_id, + self.construct_plural_form, + self.plural_filename + ) = PLURAL_RULES.get(language,PLURAL_RULES['default']) + for lang in (language, language[:5], language[:2]): + filename = 'plural-%s.py' % lang + if filename in self.filenames: + self.plural_file = ospath.join(self.langpath,filename) + self.plural_dict = read_plural_dict(self.plural_file) + break + else: + self.plural_file = None + self.plural_dict = {} + + def plural(self, word, n): + """ + get plural form of word for number *n* + NOTE: *word* MUST be defined in current language + (T.accepted_language) + + invoked from T()/M() in %%{} tag + args: + word (str): word in singular + n (numeric): number plural form created for + + returns: + (str): word in appropriate singular/plural form + """ + nplurals = self.nplurals + if int(n)==1: + return word + elif word: + id = min(int(n)-1,1) # self.get_plural_id(abs(int(n))) + # id = 0 first plural form + # id = 1 second plural form + # etc. + forms = self.plural_dict.get(word, []) + if len(forms)>=id: + # have this plural form + return forms[id-1] + else: + # guessing this plural form + forms += ['']*(nplurals-len(forms)-1) + form = self.construct_plural_form(word, id) + forms[id-1] = form + self.plural_dict[word] = forms + if self.plural_file and not is_gae: + write_plural_dict(self.plural_file, + self.plural_dict) + return form + def get_possible_languages_info(self, lang=None): """ return info for selected language or dictionary with all @@ -533,90 +541,12 @@ class translator(object): langname(from !langname! key), langfile_mtime ) } """ - if lang: - return read_possible_languages(self.folder).get(lang) - return read_possible_languages(self.folder) - - def get_possible_languages(self): - """ get list of all possible languages for current applications """ - return sorted( set(lang for lang in - read_possible_languages(self.folder).iterkeys() - if lang != 'default') - | set(self.current_languages)) - - def set_current_languages(self, *languages): - """ - set current AKA "default" languages - setting one of this languages makes force() function - turn translation off to use default language - """ - if len(languages) == 1 and isinstance(languages[0], (tuple, list)): - languages = languages[0] - self.current_languages = languages - self.force(self.http_accept_language) - - def set_plural(self, languages): - """ initialize plural forms subsystem - invoked from self.force() - """ - ( self.plural_language, - self.plural_rules_file, - self.nplurals, - self.get_plural_id, - self.construct_plural_form, - self.plural_status - ) = get_plural_rules(languages) - - if self.plural_language == 'unknown': - self.plural_file = None - self.plural_dict = {} - else: - self.plural_file = ospath.join(self.folder, - 'languages', - 'plural-%s.py' % self.plural_language) - if ospath.exists(self.plural_file): - self.plural_dict = read_plural_dict(self.plural_file) - else: - self.plural_dict = {} - - def plural(self, word, n): - """ get plural form of word for number *n* - NOTE: *word" MUST be defined in current language - (T.accepted_language) - - invoked from T()/M() in %%{} tag - args: - word (str): word in singular - n (numeric): number plural form created for - - returns: - (str): word in appropriate singular/plural form - """ - nplurals = self.nplurals - if word: - id = self.get_plural_id(abs(int(n))) - if id > 0: - forms = self.plural_dict.get(word, []) - if forms: - try: - form = forms[id-1] - except: - form = None - if form: return form - form = self.construct_plural_form(word, id) - if len(forms) < nplurals-1: - forms.extend('' for i in xrange(nplurals-len(forms)-1)) - forms[id-1] = form - self.plural_dict[word] = forms - if (self.plural_file and - not settings.global_settings.web2py_runtime_gae): - write_plural_dict(self.plural_file, self.plural_dict) - return form - return word + info = read_possible_languages(self.folder) + if lang: info = info.get(lang) + return info def force(self, *languages): """ - select language(s) for translation if a list of languages is passed as a parameter, @@ -627,49 +557,41 @@ class translator(object): default language will be selected if none of them matches possible_languages. """ - global tcache language = '' - - if not languages or languages[0] is None: + if isinstance(languages,str): + languages = regex_language.findall(languages.lower()) + elif not languages or languages[0] is None: languages = [] - if len(languages) == 1 and isinstance(languages[0], (str, unicode)): - languages = languages[0] - - if languages: - if isinstance(languages, (str, unicode)): - parts = languages.split(';') - languages = [] - for al in parts: - languages.extend(al.split(',')) - - possible_languages = self.get_possible_languages() - for lang in languages: - match_language = regex_language.match(lang.strip().lower()) - if match_language: - match_language = tuple(part - for part in match_language.groups() - if part) - language = lang_sampling(match_language, - self.current_languages) - if language: - break - language = lang_sampling(match_language, possible_languages) - if language: - self.language_file = ospath.join(self.folder, - 'languages', - language + '.py') - if ospath.exists(self.language_file): - self.t = read_dict(self.language_file) - self.cache = tcache.setdefault(self.language_file, - ({},allocate_lock())) - self.set_plural(language) - self.accepted_language = language - return languages - self.accepted_language = language or self.current_languages[0] - self.language_file = self.default_language_file - self.cache = tcache[self.language_file] - self.t = self.default_t - self.set_plural(language or self.current_languages) + for lang in languages: + if lang+'.py' in self.filenames: + language = lang + langfile = language+'.py' + break + elif len(lang)>5 and lang[:5]+'.py' in self.filenames: + language = lang[:5] + langfile = language+'.py' + break + elif len(lang)>2 and lang[:2]+'.py' in self.filenames: + language = lang[:2] + langfile = language+'.py' + break + else: + if 'default.py' in self.filenames: + language = DEFAULT_LANGUAGE + langfile = 'default.py' + else: + language = DEFAULT_LANGUAGE + langfile = None + self.accepted_language = language + if langfile: + self.language_file = ospath.join(self.langpath,langfile) + self.t = read_dict(self.language_file) + else: + self.language_file = None + self.t = {} + self.cache = global_language_cache.setdefault( + self.language_file,({},allocate_lock())) + self.set_plural(language) return languages def __call__(self, message, symbols={}, language=None, lazy=None): @@ -700,26 +622,30 @@ class translator(object): prefix = '@'+(ftag or 'userdef')+'\x01' else: prefix = '@'+self.ftag+'\x01' - message = get_from_cache(self.cache, prefix+message, - lambda: get_tr(message, prefix, filter)) + message = get_from_cache( + self.cache, prefix+message, + lambda: get_tr(message, prefix, filter)) if symbols or symbols == 0 or symbols == "": if isinstance(symbols, dict): - symbols.update( (key, xmlescape(value).translate(ttab_in)) - for key, value in symbols.iteritems() - if not isinstance(value, NUMBERS) ) + symbols.update( + (key, xmlescape(value).translate(ttab_in)) + for key, value in symbols.iteritems() + if not isinstance(value, NUMBERS) ) else: if not isinstance(symbols, tuple): symbols = (symbols,) - symbols = tuple(value if isinstance(value, NUMBERS) - else xmlescape(value).translate(ttab_in) - for value in symbols) + symbols = tuple( + value if isinstance(value, NUMBERS) + else xmlescape(value).translate(ttab_in) + for value in symbols) message = self.params_substitution(message, symbols) return XML(message.translate(ttab_out)) - def M(self, message, symbols={}, language=None, lazy=None, filter=None, ftag=None): - """ get cached translated markmin-message with inserted parametes - - if lazy==True lazyT object is returned + def M(self, message, symbols={}, language=None, + lazy=None, filter=None, ftag=None): + """ + get cached translated markmin-message with inserted parametes + if lazy==True lazyT object is returned """ if lazy is None: lazy = self.lazy @@ -751,18 +677,20 @@ class translator(object): """ key = prefix+message mt = self.t.get(key, None) - if mt is not None: - return mt - if not message.startswith('##') and not '\n' in message: - tokens = message.rsplit('##', 1) - else: - # this allows markmin syntax in translations - tokens = [message] - self.t[key] = mt = self.default_t.get(key, tokens[0]) - if (self.language_file != self.default_language_file and - not settings.global_settings.web2py_runtime_gae): - write_dict(self.language_file, self.t) - return regex_backslash.sub(lambda m: m.group(1).translate(ttab_in), mt) + if mt is None: + # we did not find a translation + if message.find('##')>0 and not '\n' in message: + # remove comments + message = message.rsplit('##', 1)[0] + # guess translation same as original + self.t[key] = mt = message + # update language file for later translation + if self.language_file and not is_gae: + write_dict(self.language_file, self.t) + # fix backslash escaping + mt = regex_backslash.sub( + lambda m: m.group(1).translate(ttab_in), mt) + return mt def params_substitution(self, message, symbols): """ @@ -866,19 +794,21 @@ class translator(object): """ get cached translated message with inserted parameters(symbols) """ - message = get_from_cache(self.cache, message, lambda: self.get_t(message)) + message = get_from_cache(self.cache, message, + lambda: self.get_t(message)) if symbols or symbols == 0 or symbols == "": if isinstance(symbols, dict): - symbols.update( (key, str(value).translate(ttab_in)) - for key, value in symbols.iteritems() - if not isinstance(value, NUMBERS) ) + symbols.update( + (key, str(value).translate(ttab_in)) + for key, value in symbols.iteritems() + if not isinstance(value, NUMBERS) ) else: if not isinstance(symbols, tuple): symbols = (symbols,) - symbols = tuple(value if isinstance(value, NUMBERS) - else str(value).translate(ttab_in) - for value in symbols) - + symbols = tuple( + value if isinstance(value, NUMBERS) + else str(value).translate(ttab_in) + for value in symbols) message = self.params_substitution(message, symbols) return message.translate(ttab_out) @@ -892,26 +822,25 @@ def findT(path, language='en'): cp = ospath.join(path, 'controllers') vp = ospath.join(path, 'views') mop = ospath.join(path, 'modules') - for file in listdir(mp, '^.+\.py$', 0) + listdir(cp, '^.+\.py$', 0)\ - + listdir(vp, '^.+\.html$', 0) + listdir(mop, '^.+\.py$', 0): - fp = portalocker.LockedFile(file, 'r') - data = fp.read() - fp.close() + for filename in \ + listdir(mp, '^.+\.py$', 0)+listdir(cp, '^.+\.py$', 0)\ + +listdir(vp, '^.+\.html$', 0)+listdir(mop, '^.+\.py$', 0): + data = portalocker.read_locked(filename) items = regex_translate.findall(data) for item in items: try: - message = eval(item) - if not message.startswith('#') and not '\n' in message: - tokens = message.rsplit('##', 1) - else: - # this allows markmin syntax in translations - tokens = [message] - if len(tokens) == 2: - message = tokens[0].strip() + '##' + tokens[1].strip() - if message and not message in sentences: - sentences[message] = message + message = safe_eval(item) except: - pass + continue # silently ignore inproperly formatted strings + if not message.startswith('#') and not '\n' in message: + tokens = message.rsplit('##', 1) + else: + # this allows markmin syntax in translations + tokens = [message] + if len(tokens) == 2: + message = tokens[0].strip()+'##'+tokens[1].strip() + if message and not message in sentences: + sentences[message] = message if not '!langcode!' in sentences: sentences['!langcode!'] = ( 'en' if language in ('default', 'en') else language) @@ -937,6 +866,3 @@ def update_all_languages(application_path): if __name__ == '__main__': import doctest doctest.testmod() - - - diff --git a/gluon/main.py b/gluon/main.py index 7f95ecb0..85f57fca 100644 --- a/gluon/main.py +++ b/gluon/main.py @@ -21,7 +21,6 @@ import re import copy import sys import time -import thread import datetime import signal import socket @@ -29,6 +28,7 @@ import tempfile import random import string import urllib2 +from thread import allocate_lock from fileutils import abspath, write_file, parse_version from settings import global_settings @@ -69,8 +69,11 @@ import logging.config import gluon.messageboxhandler logging.gluon = gluon +exists = os.path.exists +pjoin = os.path.join + logpath = abspath("logging.conf") -if os.path.exists(logpath): +if exists(logpath): logging.config.fileConfig(abspath("logging.conf")) else: logging.basicConfig() @@ -87,10 +90,10 @@ from dal import BaseAdapter from settings import global_settings from validators import CRYPT from cache import Cache -from html import URL as Url, xmlescape +from html import URL, xmlescape from utils import is_valid_ip_address +from rewrite import load, url_in, thread as rwthread, try_rewrite_on_error import newcron -import rewrite __all__ = ['wsgibase', 'save_password', 'appfactory', 'HttpServer'] @@ -103,7 +106,7 @@ requests = 0 # gc timer regex_client = re.compile('[\w\-:]+(\.[\w\-]+)*\.?') # ## to account for IPV6 try: - version_info = open(os.path.join(global_settings.gluon_parent, 'VERSION'), 'r') + version_info = open(pjoin(global_settings.gluon_parent, 'VERSION'), 'r') raw_version_string = version_info.read().strip() version_info.close() global_settings.web2py_version = parse_version(raw_version_string) @@ -118,7 +121,7 @@ except: if not global_settings.web2py_runtime_gae: logger.warn('unable to import Rocket') -rewrite.load() +load() def get_client(env): """ @@ -129,11 +132,16 @@ def get_client(env): """ g = regex_client.search(env.get('http_x_forwarded_for', '')) if g: - return g.group() - g = regex_client.search(env.get('remote_addr', '')) - if g: - return g.group() - return '127.0.0.1' + client = g.group() + else: + g = regex_client.search(env.get('remote_addr', '')) + if g: + client = g.group() + else: + client = '127.0.0.1' + if not is_valid_ip_address(client): + raise HTTP(400,"Bad Request (request.client=%s)" % client) + return client def copystream_progress(request, chunk_size= 10**5): """ @@ -253,7 +261,8 @@ def middleware_aux(request, response, *middleware_apps): for item in middleware_apps: app=item(app) def caller(app): - return app(request.wsgi.environ,request.wsgi.start_response) + wsgi = request.wsgi + return app(wsgi.environ, wsgi.start_response) return lambda caller=caller, app=app: caller(app) return middleware @@ -279,14 +288,14 @@ def parse_get_post_vars(request, environ): # parse POST variables on POST, PUT, BOTH only in post_vars try: - request.body = copystream_progress(request) ### stores request body + request.body = body = copystream_progress(request) except IOError: raise HTTP(400,"Bad Request - HTTP body is incomplete") - if (request.body and request.env.request_method in ('POST', 'PUT', 'BOTH')): - dpost = cgi.FieldStorage(fp=request.body,environ=environ,keep_blank_values=1) + if (body and request.env.request_method in ('POST', 'PUT', 'BOTH')): + dpost = cgi.FieldStorage(fp=body,environ=environ,keep_blank_values=1) # The same detection used by FieldStorage to detect multipart POSTs is_multipart = dpost.type[:10] == 'multipart/' - request.body.seek(0) + body.seek(0) isle25 = sys.version_info[1] <= 5 def listify(a): @@ -357,9 +366,10 @@ def wsgibase(environ, responder): request = Request() response = Response() session = Session() - request.env.web2py_path = global_settings.applications_parent - request.env.web2py_version = web2py_version - request.env.update(global_settings) + env = request.env + env.web2py_path = global_settings.applications_parent + env.web2py_version = web2py_version + env.update(global_settings) static_file = False try: try: @@ -373,79 +383,80 @@ def wsgibase(environ, responder): # serve file if static # ################################################## - if not environ.get('PATH_INFO',None) and \ - environ.get('REQUEST_URI',None): - # for fcgi, get path_info and query_string from request_uri + eget = environ.get + if not eget('PATH_INFO',None) and eget('REQUEST_URI',None): + # for fcgi, get path_info and + # query_string from request_uri items = environ['REQUEST_URI'].split('?') environ['PATH_INFO'] = items[0] if len(items) > 1: environ['QUERY_STRING'] = items[1] else: environ['QUERY_STRING'] = '' - if not environ.get('HTTP_HOST',None): - environ['HTTP_HOST'] = '%s:%s' % (environ.get('SERVER_NAME'), - environ.get('SERVER_PORT')) + if not eget('HTTP_HOST',None): + environ['HTTP_HOST'] = \ + eget('SERVER_NAME')+':'+eget('SERVER_PORT') + + + (static_file, environ) = url_in(request, environ) - (static_file, environ) = rewrite.url_in(request, environ) if static_file: - if environ.get('QUERY_STRING', '')[:10] == 'attachment': - response.headers['Content-Disposition'] = 'attachment' + if environ.get('QUERY_STRING','').startswith( + 'attachment'): + response.headers['Content-Disposition'] \ + = 'attachment' response.stream(static_file, request=request) # ################################################## # fill in request items # ################################################## - - http_host = request.env.http_host.split(':',1)[0] - - local_hosts = [http_host,'::1','127.0.0.1','::ffff:127.0.0.1'] + app = request.application ## must go after url_in! + + http_host = env.http_host.split(':',1)[0] + local_hosts = [http_host,'::1','127.0.0.1', + '::ffff:127.0.0.1'] if not global_settings.web2py_runtime_gae: local_hosts.append(socket.gethostname()) - try: local_hosts.append(socket.gethostbyname(http_host)) - except socket.gaierror: pass - request.client = get_client(request.env) - if not is_valid_ip_address(request.client): - raise HTTP(400,"Bad Request (request.client=%s)" % \ - request.client) - request.folder = abspath('applications', - request.application) + os.sep - x_req_with = str(request.env.http_x_requested_with).lower() - request.ajax = x_req_with == 'xmlhttprequest' - request.cid = request.env.http_web2py_component_element - request.is_local = request.env.remote_addr in local_hosts - request.is_https = request.env.wsgi_url_scheme \ - in ['https', 'HTTPS'] or request.env.https == 'on' - - # ################################################## - # compute a request.uuid to be used for tickets and toolbar - # ################################################## - - response.uuid = request.compute_uuid() + try: + local_hosts.append( + socket.gethostbyname(http_host)) + except socket.gaierror: + pass + client = get_client(env) + x_req_with = str(env.http_x_requested_with).lower() + + request.update(dict( + client = client, + folder = abspath('applications',app) + os.sep, + ajax = x_req_with == 'xmlhttprequest', + cid = env.http_web2py_component_element, + is_local = env.remote_addr in local_hosts, + is_https = env.wsgi_url_scheme \ + in ['https', 'HTTPS'] or env.https=='on')) + request.uuid = request.compute_uuid() # requires client # ################################################## # access the requested application # ################################################## - if not os.path.exists(request.folder): - if request.application == \ - rewrite.thread.routes.default_application \ - and request.application != 'welcome': - request.application = 'welcome' - redirect(Url(r=request)) - elif rewrite.thread.routes.error_handler: - _handler = rewrite.thread.routes.error_handler - redirect(Url(_handler['application'], + if not exists(request.folder): + if app == rwthread.routes.default_application \ + and app != 'welcome': + redirect(URL('welcome','default','index')) + elif rwthread.routes.error_handler: + _handler = rwthread.routes.error_handler + redirect(URL(_handler['application'], _handler['controller'], _handler['function'], - args=request.application)) + args=app)) else: - raise HTTP(404, rewrite.thread.routes.error_message \ + raise HTTP(404, rwthread.routes.error_message \ % 'invalid request', web2py_error='invalid application') elif not request.is_local and \ - os.path.exists(os.path.join(request.folder,'DISABLED')): + exists(pjoin(request.folder,'DISABLED')): raise HTTP(503, "

    Temporarily down for maintenance

    ") - request.url = Url(r=request, + request.url = URL(r=request, args=request.args, extension=request.raw_extension) @@ -492,22 +503,23 @@ def wsgibase(environ, responder): # ################################################## # set no-cache headers # ################################################## - - response.headers['Content-Type'] = \ + + headers = response.headers + headers['Content-Type'] = \ contenttype('.'+request.extension) - response.headers['Cache-Control'] = \ + headers['Cache-Control'] = \ 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0' - response.headers['Expires'] = \ + headers['Expires'] = \ time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime()) - response.headers['Pragma'] = 'no-cache' + headers['Pragma'] = 'no-cache' # ################################################## # run controller # ################################################## - if global_settings.debugging and request.application != "admin": + if global_settings.debugging and app != "admin": import gluon.debug - # activate the debugger and wait to reach application code + # activate the debugger gluon.debug.dbg.do_debug(mainpyfile=request.folder) serve_controller(request, response, session) @@ -549,22 +561,24 @@ def wsgibase(environ, responder): # ################################################## if request.cid: - if response.flash and not 'web2py-component-flash' \ - in http_response.headers: - http_response.headers['web2py-component-flash'] = \ + rheaders + if response.flash and \ + not 'web2py-component-flash' in rheaders: + rheaders['web2py-component-flash'] = \ urllib2.quote(xmlescape(response.flash)\ .replace('\n','')) - if response.js and not 'web2py-component-command' \ - in http_response.headers: - http_response.headers['web2py-component-command'] = \ + if response.js and \ + not 'web2py-component-command' in readers: + readers['web2py-component-command'] = \ response.js.replace('\n','') + rcookies = response.cookies if session._forget and \ response.session_id_name in response.cookies: - del response.cookies[response.session_id_name] + del rcookies[response.session_id_name] elif session._secure: - response.cookies[response.session_id_name]['secure'] = True + rcookies[response.session_id_name]['secure'] = True - http_response.cookies2headers(response.cookies) + http_response.cookies2headers(rcookies) ticket=None except RestrictedError, e: @@ -583,7 +597,7 @@ def wsgibase(environ, responder): BaseAdapter.close_all_instances('rollback') http_response = \ - HTTP(500, rewrite.thread.routes.error_message_ticket % \ + HTTP(500, rwthread.routes.error_message_ticket % \ dict(ticket=ticket), web2py_error='ticket %s' % ticket) @@ -606,7 +620,7 @@ def wsgibase(environ, responder): e = RestrictedError('Framework', '', '', locals()) ticket = e.log(request) or 'unrecoverable' http_response = \ - HTTP(500, rewrite.thread.routes.error_message_ticket \ + HTTP(500, rwthread.routes.error_message_ticket \ % dict(ticket=ticket), web2py_error='ticket %s' % ticket) @@ -616,7 +630,7 @@ def wsgibase(environ, responder): response.session_file.close() session._unlock(response) - http_response, new_environ = rewrite.try_rewrite_on_error( + http_response, new_environ = try_rewrite_on_error( http_response, request, environ, ticket) if not http_response: return wsgibase(new_environ,responder) @@ -641,7 +655,7 @@ def save_password(password, port): print '*********************************************************' elif password == '': # reuse the current password if any - if os.path.exists(password_file): + if exists(password_file): return else: password = '' @@ -672,9 +686,9 @@ def appfactory(wsgiapp=wsgibase, [, profilerfilename='profiler.log']]]) """ - if profilerfilename and os.path.exists(profilerfilename): + if profilerfilename and exists(profilerfilename): os.unlink(profilerfilename) - locker = thread.allocate_lock() + locker = allocate_lock() def app_with_logging(environ, responder): """ @@ -785,7 +799,7 @@ class HttpServer(object): os.chdir(path) [add_path_first(p) for p in (path, abspath('site-packages'), "")] custom_import_install(web2py_path) - if os.path.exists("logging.conf"): + if exists("logging.conf"): logging.config.fileConfig("logging.conf") save_password(password, port) @@ -800,9 +814,9 @@ class HttpServer(object): logger.info('SSL is off') elif not rocket.ssl: logger.warning('Python "ssl" module unavailable. SSL is OFF') - elif not os.path.exists(ssl_certificate): + elif not exists(ssl_certificate): logger.warning('unable to open SSL certificate. SSL is OFF') - elif not os.path.exists(ssl_private_key): + elif not exists(ssl_private_key): logger.warning('unable to open SSL private key. SSL is OFF') else: sock_list.extend([ssl_private_key, ssl_certificate]) @@ -848,9 +862,3 @@ class HttpServer(object): except: pass - - - - - - diff --git a/gluon/portalocker.py b/gluon/portalocker.py index f516e73e..9d92cb4f 100644 --- a/gluon/portalocker.py +++ b/gluon/portalocker.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# portalocker.py - Cross-platform (posix/nt) API for flock-style file locking. +# portalocker.py +# Cross-platform (posix/nt) API for flock-style file locking. # Requires python 1.5.2 or better. """ @@ -141,6 +142,17 @@ class LockedFile(object): def __del__(self): self.close() +def read_locked(filename): + fp = LockedFile(filename, 'r') + data = fp.read() + fp.close() + return data + +def write_locked(filename,data): + fp = LockedFile(filename, 'w') + data = fp.write(data) + fp.close() + if __name__=='__main__': f = LockedFile('test.txt',mode='wb') f.write('test ok') diff --git a/gluon/restricted.py b/gluon/restricted.py index 74f3b34c..bb5ba670 100644 --- a/gluon/restricted.py +++ b/gluon/restricted.py @@ -88,16 +88,19 @@ class TicketStorage(Storage): ticket_id, ): if not self.db: - ef = self._error_file(request, ticket_id, 'rb', app) + try: + ef = self._error_file(request, ticket_id, 'rb', app) + except IOError: + return {} try: return cPickle.load(ef) finally: ef.close() - table = self._get_table(self.db, self.tablename, app) - rows = self.db(table.ticket_id == ticket_id).select() - if rows: - return cPickle.loads(rows[0].ticket_data) - return None + else: + table = self._get_table(self.db, self.tablename, app) + rows = self.db(table.ticket_id == ticket_id).select() + return cPickle.loads(rows[0].ticket_data) if rows else {} + class RestrictedError(Exception): @@ -164,10 +167,10 @@ class RestrictedError(Exception): ticket_storage = TicketStorage(db=request.tickets_db) d = ticket_storage.load(request, app, ticket_id) - self.layer = d['layer'] - self.code = d['code'] - self.output = d['output'] - self.traceback = d['traceback'] + self.layer = d.get('layer') + self.code = d.get('code') + self.output = d.get('output') + self.traceback = d.get('traceback') self.snapshot = d.get('snapshot') def __str__(self): diff --git a/gluon/rewrite.py b/gluon/rewrite.py index d7faf450..731cee67 100644 --- a/gluon/rewrite.py +++ b/gluon/rewrite.py @@ -27,9 +27,17 @@ from http import HTTP from fileutils import abspath, read_file from settings import global_settings -logger = logging.getLogger('web2py.rewrite') +isdir = os.path.isdir +isfile = os.path.isfile +exists = os.path.exists +pjoin = os.path.join -thread = threading.local() # thread-local storage for routing parameters +logger = logging.getLogger('web2py.rewrite') +thread = threading.local() # thread-local storage for routing params + +regex_at = re.compile(r'(?(.*)') def _router_default(): "return new copy of default base router" @@ -75,7 +83,7 @@ def _params_default(app=None): params_apps = dict() params = _params_default(app=None) # regex rewrite parameters -thread.routes = params # default to base regex rewrite parameters +thread.routes = params # default to base regex rewrite parameters routers = None def log_rewrite(string): @@ -97,13 +105,18 @@ def log_rewrite(string): else: logger.debug(string) -ROUTER_KEYS = set(('default_application', 'applications', 'default_controller', 'controllers', - 'default_function', 'functions', 'default_language', 'languages', - 'domain', 'domains', 'root_static', 'path_prefix', - 'exclusive_domain', 'map_hyphen', 'map_static', - 'acfe_match', 'file_match', 'args_match')) +ROUTER_KEYS = set( + ('default_application', 'applications', + 'default_controller', 'controllers', + 'default_function', 'functions', + 'default_language', 'languages', + 'domain', 'domains', 'root_static', 'path_prefix', + 'exclusive_domain', 'map_hyphen', 'map_static', + 'acfe_match', 'file_match', 'args_match')) -ROUTER_BASE_KEYS = set(('applications', 'default_application', 'domains', 'path_prefix')) +ROUTER_BASE_KEYS = set( + ('applications', 'default_application', + 'domains', 'path_prefix')) # The external interface to rewrite consists of: # @@ -223,9 +236,7 @@ def try_redirect_on_error(http_object, request, ticket=None): (redir,status,ticket, urllib.quote_plus(request.env.request_uri), request.url) - return HTTP(303, - 'You are being redirected here' % url, - Location=url) + return HTTP(303,'You are being redirected here' % url,Location=url) return http_object @@ -258,7 +269,7 @@ def load(routes='routes.py', app=None, data=None, rdict=None): path = abspath(routes) else: path = abspath('applications', app, routes) - if not os.path.exists(path): + if not exists(path): return data = read_file(path).replace('\r\n','\n') @@ -309,9 +320,11 @@ def load(routes='routes.py', app=None, data=None, rdict=None): # parse the app-specific routes.py if present # all_apps = [] - for appname in [app for app in os.listdir(abspath('applications')) if not app.startswith('.')]: - if os.path.isdir(abspath('applications', appname)) and \ - os.path.isdir(abspath('applications', appname, 'controllers')): + apppath = abspath('applications') + for appname in os.listdir(apppath): + if not appname.startswith('.') and \ + isdir(abspath(apppath,appname)) and \ + isdir(abspath(apppath,appname,'controllers')): all_apps.append(appname) if routers: router = Storage(routers.BASE) # new copy @@ -321,7 +334,7 @@ def load(routes='routes.py', app=None, data=None, rdict=None): raise SyntaxError, "BASE-only key '%s' in router '%s'" % (key, appname) router.update(routers[appname]) routers[appname] = router - if os.path.exists(abspath('applications', appname, routes)): + if exists(abspath('applications', appname, routes)): load(routes, appname) if routers: @@ -336,14 +349,9 @@ def load(routes='routes.py', app=None, data=None, rdict=None): log_rewrite('URL rewrite is on. configuration in %s' % path) -regex_at = re.compile(r'(?(.*)') - def compile_regex(k, v): """ Preprocess and compile the regular expressions in routes_app/in/out - The resulting regex will match a pattern of the form: [remote address]:[protocol]://[host]:[method] [path] @@ -380,8 +388,9 @@ def compile_regex(k, v): def load_routers(all_apps): "load-time post-processing of routers" - for app in routers.keys(): - # initialize apps with routers that aren't present, on behalf of unit tests + for app in routers: + # initialize apps with routers that aren't present, + # on behalf of unit tests if app not in all_apps: all_apps.append(app) router = Storage(routers.BASE) # new copy @@ -420,10 +429,10 @@ def load_routers(all_apps): routers.BASE.domains[router.domain] = app if isinstance(router.controllers, str) and router.controllers == 'DEFAULT': router.controllers = set() - if os.path.isdir(abspath('applications', app)): + if isdir(abspath('applications', app)): cpath = abspath('applications', app, 'controllers') for cname in os.listdir(cpath): - if os.path.isfile(abspath(cpath, cname)) and cname.endswith('.py'): + if isfile(abspath(cpath, cname)) and cname.endswith('.py'): router.controllers.add(cname[:-3]) if router.controllers: router.controllers.add('static') @@ -458,16 +467,20 @@ def load_routers(all_apps): # domains = dict() if routers.BASE.domains: - for (domain, app) in [(d.strip(':'), a.strip('/')) for (d, a) in routers.BASE.domains.items()]: - port = None + for (d, a) in routers.BASE.domains.iteritems(): + (domain, app) = (d.strip(':'), a.strip('/')) if ':' in domain: (domain, port) = domain.split(':') - ctlr = None - fcn = None + else: + port = None if '/' in app: (app, ctlr) = app.split('/', 1) + else: + ctlr = None if ctlr and '/' in ctlr: (ctlr, fcn) = ctlr.split('/') + else: + fcn = None if app not in all_apps and app not in routers: raise SyntaxError, "unknown app '%s' in domains" % app domains[(domain, port)] = (app, ctlr, fcn) @@ -514,7 +527,8 @@ def regex_filter_in(e): query = e.get('QUERY_STRING', None) e['WEB2PY_ORIGINAL_URI'] = e['PATH_INFO'] + (query and ('?' + query) or '') if thread.routes.routes_in: - path = regex_uri(e, thread.routes.routes_in, "routes_in", e['PATH_INFO']) + path = regex_uri(e, thread.routes.routes_in, + "routes_in", e['PATH_INFO']) rmatch = regex_redirect.match(path) if rmatch: raise HTTP(int(rmatch.group(1)),location=rmatch.group(2)) @@ -581,6 +595,9 @@ regex_args = re.compile(r''' /?$) # trailing slash ''', re.X) +def sluggify(key): + return key.lower().replace('.','_') + def regex_url_in(request, environ): "rewrite and parse incoming URL" @@ -594,9 +611,8 @@ def regex_url_in(request, environ): if thread.routes.routes_in: environ = regex_filter_in(environ) - - for (key, value) in environ.items(): - request.env[key.lower().replace('.', '_')] = value + + request.env.update((sluggify(k),v) for k,v in environ.iteritems()) path = request.env.path_info.replace('\\', '/') @@ -606,7 +622,7 @@ def regex_url_in(request, environ): match = regex_static.match(regex_space.sub('_', path)) if match and match.group('x'): - static_file = os.path.join(request.env.applications_parent, + static_file = pjoin(request.env.applications_parent, 'applications', match.group('b'), 'static', match.group('x')) return (static_file, environ) @@ -908,7 +924,7 @@ class MapUrlIn(object): ''' if len(self.args) == 1 and self.arg0 in self.router.root_static: self.controller = self.request.controller = 'static' - root_static_file = os.path.join(self.request.env.applications_parent, + root_static_file = pjoin(self.request.env.applications_parent, 'applications', self.application, self.controller, self.arg0) log_rewrite("route: root static=%s" % root_static_file) @@ -962,7 +978,8 @@ class MapUrlIn(object): bad_static = bad_static or name in ('', '.', '..') or not self.router._file_match.match(name) if bad_static: log_rewrite('bad static path=%s' % file) - raise HTTP(400, thread.routes.error_message % 'invalid request', + raise HTTP(400, + thread.routes.error_message % 'invalid request', web2py_error='invalid static file') # # support language-specific static subdirectories, @@ -970,13 +987,13 @@ class MapUrlIn(object): # if language-specific file doesn't exist, try same file in static # if self.language: - static_file = os.path.join(self.request.env.applications_parent, - 'applications', self.application, - 'static', self.language, file) - if not self.language or not os.path.isfile(static_file): - static_file = os.path.join(self.request.env.applications_parent, - 'applications', self.application, - 'static', file) + static_file = pjoin(self.request.env.applications_parent, + 'applications', self.application, + 'static', self.language, file) + if not self.language or not isfile(static_file): + static_file = pjoin(self.request.env.applications_parent, + 'applications', self.application, + 'static', file) log_rewrite("route: static=%s" % static_file) return static_file @@ -1040,12 +1057,14 @@ class MapUrlIn(object): uri += '.' + self.extension if self.language: uri = '/%s%s' % (self.language, uri) - uri = '/%s%s' % (app, uri) - uri += self.args and urllib.quote('/' + '/'.join([str(x) for x in self.args])) or '' - uri += (self.query and ('?' + self.query) or '') + uri = '/%s%s%s%s' % ( + app, + uri, + urllib.quote('/'+'/'.join(str(x) for x in self.args)) if self.args else '', + ('?' + self.query) if self.query else '') self.env['REQUEST_URI'] = uri - for (key, value) in self.env.items(): - self.request.env[key.lower().replace('.', '_')] = value + self.request.env.update( + (sluggify(k),v) for k,v in self.env.iteritems()) @property def arg0(self): diff --git a/gluon/rocket.py b/gluon/rocket.py index 12fd8dc6..43284a21 100644 --- a/gluon/rocket.py +++ b/gluon/rocket.py @@ -1407,7 +1407,7 @@ class Worker(Thread): raise BadRequest req = match.groupdict() - for k,v in req.items(): + for k,v in req.iteritems(): if not v: req[k] = "" if k == 'path': @@ -1694,7 +1694,8 @@ class FileSystemWorker(Worker): try: # Get our file path - headers = dict([(str(k.lower()), v) for k, v in self.read_headers(sock_file).items()]) + reader = self.read_headers(sock_file) + headers = dict((k.lower(),v) for k,v in reader.iteritems()) rpath = request.get('path', '').lstrip('/') filepath = os.path.join(self.root, rpath) filepath = os.path.abspath(filepath) diff --git a/gluon/settings.py b/gluon/settings.py index 3715edc6..a8d23280 100644 --- a/gluon/settings.py +++ b/gluon/settings.py @@ -18,7 +18,8 @@ if not hasattr(os, 'mkdir'): if global_settings.db_sessions is not True: global_settings.db_sessions = set() -global_settings.gluon_parent = os.environ.get('web2py_path', os.getcwd()) +global_settings.gluon_parent = \ + os.environ.get('web2py_path', os.getcwd()) global_settings.applications_parent = global_settings.gluon_parent @@ -26,12 +27,14 @@ global_settings.app_folders = set() global_settings.debugging = False -global_settings.is_pypy = hasattr(platform,'python_implementation') and \ - platform.python_implementation() == 'PyPy' +global_settings.is_pypy = \ + hasattr(platform,'python_implementation') and \ + platform.python_implementation() == 'PyPy' -global_settings.is_jython = 'java' in sys.platform.lower() or \ - hasattr(sys, 'JYTHON_JAR') or \ - str(sys.copyright).find('Jython') > 0 +global_settings.is_jython = \ + 'java' in sys.platform.lower() or \ + hasattr(sys, 'JYTHON_JAR') or \ + str(sys.copyright).find('Jython') > 0 diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py index b3df0aee..6f3b9220 100644 --- a/gluon/sqlhtml.py +++ b/gluon/sqlhtml.py @@ -36,6 +36,8 @@ import re import cStringIO from gluon import current, redirect, A, URL, DIV, H3, UL, LI, SPAN, INPUT import inspect +import settings +is_gae = settings.global_settings.web2py_runtime_gae table_field = re.compile('[\w_]+\.[\w_]+') widget_class = re.compile('^\w*') @@ -581,7 +583,7 @@ class AutocompleteWidget(object): def callback(self): if self.keyword in self.request.vars: field = self.fields[0] - if settings.global_settings.web2py_runtime_gae: + if is_gae: rows = self.db(field.__ge__(self.request.vars[self.keyword])&field.__lt__(self.request.vars[self.keyword]+ u'\ufffd')).select(orderby=self.orderby,limitby=self.limitby,*self.fields) else: rows = self.db(field.like(self.request.vars[self.keyword]+'%')).select(orderby=self.orderby,limitby=self.limitby,distinct=self.distinct,*self.fields) @@ -1834,7 +1836,7 @@ class SQLFORM(FORM): else: rows = dbset.select(left=left,orderby=orderby,*columns) - if exportManager.has_key(export_type): + if export_type in exportManager: value = exportManager[export_type] clazz = value[0] if hasattr(value, '__getitem__') else value oExp = clazz(rows) diff --git a/gluon/template.py b/gluon/template.py index 9f147895..a8481338 100644 --- a/gluon/template.py +++ b/gluon/template.py @@ -15,10 +15,10 @@ Contributors: """ import os -import re import cgi import cStringIO import logging +from re import compile, sub, escape, DOTALL try: # have web2py from restricted import RestrictedError @@ -57,6 +57,18 @@ class SuperNode(Node): def __repr__(self): return "%s->%s" % (self.name, self.value) +def output_aux(node,blocks): + # If we have a block level + # If we can override this block. + # Override block from vars. + # Else we take the default + # Else its just a string + return (blocks[node.name].output(blocks) + if node.name in blocks else + node.output(blocks)) \ + if isinstance(node, BlockNode) \ + else str(node) + class BlockNode(Node): """ Block Container. @@ -81,8 +93,7 @@ class BlockNode(Node): def __repr__(self): lines = ['%sblock %s%s' % (self.left,self.name,self.right)] - for node in self.nodes: - lines.append(str(node)) + lines += [str(node) for node in self.nodes] lines.append('%send%s' % (self.left, self.right)) return ''.join(lines) @@ -90,11 +101,8 @@ class BlockNode(Node): """ Get this BlockNodes content, not including child Nodes """ - lines = [] - for node in self.nodes: - if not isinstance(node, BlockNode): - lines.append(str(node)) - return ''.join(lines) + return ''.join(str(node) for node in self.nodes \ + if not isinstance(node, BlockNode)) def append(self, node): """ @@ -122,30 +130,14 @@ class BlockNode(Node): else: raise TypeError("Invalid type; must be instance of ``BlockNode``. %s" % other) + def output(self, blocks): """ Merges all nodes into a single string. - blocks -- Dictionary of blocks that are extending from this template. """ - lines = [] - # Get each of our nodes - for node in self.nodes: - # If we have a block level node. - if isinstance(node, BlockNode): - # If we can override this block. - if node.name in blocks: - # Override block from vars. - lines.append(blocks[node.name].output(blocks)) - # Else we take the default - else: - lines.append(node.output(blocks)) - # Else its just a string - else: - lines.append(str(node)) - # Now combine all of our lines together. - return ''.join(lines) + return ''.join(output_aux(node,blocks) for node in self.nodes) class Content(BlockNode): """ @@ -165,29 +157,13 @@ class Content(BlockNode): self.pre_extend = pre_extend def __str__(self): - lines = [] - # For each of our nodes - for node in self.nodes: - # If it is a block node. - if isinstance(node, BlockNode): - # And the node has a name that corresponds with a block in us - if node.name in self.blocks: - # Use the overriding output. - lines.append(self.blocks[node.name].output(self.blocks)) - else: - # Otherwise we just use the nodes output. - lines.append(node.output(self.blocks)) - else: - # It is just a string, so include it. - lines.append(str(node)) - # Merge our list together. - return ''.join(lines) + return ''.join(output_aux(node,self.blocks) for node in self.nodes) def _insert(self, other, index = 0): """ Inserts object at index. """ - if isinstance(other, str) or isinstance(other, Node): + if isinstance(other, (str, Node)): self.nodes.insert(index, other) else: raise TypeError("Invalid type, must be instance of ``str`` or ``Node``.") @@ -201,8 +177,7 @@ class Content(BlockNode): if isinstance(other, (list, tuple)): # Must reverse so the order stays the same. other.reverse() - for item in other: - self._insert(item, index) + (self._insert(item, index) for item in other) else: self._insert(other, index) @@ -210,7 +185,7 @@ class Content(BlockNode): """ Adds a node to list. If it is a BlockNode then we assign a block for it. """ - if isinstance(node, str) or isinstance(node, Node): + if isinstance(node, (str, Node)): self.nodes.append(node) if isinstance(node, BlockNode): self.blocks[node.name] = node @@ -233,18 +208,18 @@ class Content(BlockNode): class TemplateParser(object): default_delimiters = ('{{','}}') - r_tag = re.compile(r'(\{\{.*?\}\})', re.DOTALL) + r_tag = compile(r'(\{\{.*?\}\})', DOTALL) - r_multiline = re.compile(r'(""".*?""")|(\'\'\'.*?\'\'\')', re.DOTALL) + r_multiline = compile(r'(""".*?""")|(\'\'\'.*?\'\'\')', DOTALL) # These are used for re-indentation. # Indent + 1 - re_block = re.compile('^(elif |else:|except:|except |finally:).*$', - re.DOTALL) + re_block = compile('^(elif |else:|except:|except |finally:).*$',DOTALL) + # Indent - 1 - re_unblock = re.compile('^(return|continue|break|raise)( .*)?$', re.DOTALL) + re_unblock = compile('^(return|continue|break|raise)( .*)?$', DOTALL) # Indent - 1 - re_pass = re.compile('^pass( .*)?$', re.DOTALL) + re_pass = compile('^pass( .*)?$', DOTALL) def __init__(self, text, name = "ParserContainer", @@ -291,13 +266,16 @@ class TemplateParser(object): # allow optional alternative delimiters self.delimiters = delimiters if delimiters != self.default_delimiters: - escaped_delimiters = (re.escape(delimiters[0]),re.escape(delimiters[1])) - self.r_tag = re.compile(r'(%s.*?%s)' % escaped_delimiters, re.DOTALL) - elif context.has_key('response') and hasattr(context['response'],'delimiters'): + escaped_delimiters = (escape(delimiters[0]), + escape(delimiters[1])) + self.r_tag = compile(r'(%s.*?%s)' % escaped_delimiters, DOTALL) + elif hasattr(context.get('response',None),'delimiters'): if context['response'].delimiters != self.default_delimiters: - escaped_delimiters = (re.escape(context['response'].delimiters[0]), - re.escape(context['response'].delimiters[1])) - self.r_tag = re.compile(r'(%s.*?%s)' % escaped_delimiters,re.DOTALL) + escaped_delimiters = ( + escape(context['response'].delimiters[0]), + escape(context['response'].delimiters[1])) + self.r_tag = compile(r'(%s.*?%s)' % escaped_delimiters, + DOTALL) # Create a root level Content that everything will go into. self.content = Content(name=name) @@ -524,17 +502,19 @@ class TemplateParser(object): # the parent nodes. self.content.nodes = [] + t_content = t.content + # Set our include, unique by filename - t.content.blocks['__include__' + filename] = buf + t_content.blocks['__include__' + filename] = buf # Make sure our pre_extended nodes go first - t.content.insert(pre) + t_content.insert(pre) # Then we extend our blocks - t.content.extend(self.content) + t_content.extend(self.content) # Work off the parent node. - self.content = t.content + self.content = t_content def parse(self, text): @@ -553,69 +533,20 @@ class TemplateParser(object): ij = self.r_tag.split(text) # j = current index # i = current item + stack = self.stack for j in range(len(ij)): i = ij[j] if i: - if len(self.stack) == 0: + if not stack: self._raise_error('The "end" tag is unmatched, please check if you have a starting "block" tag') # Our current element in the stack. - top = self.stack[-1] + top = stack[-1] if in_tag: line = i - # If we are missing any strings!!!! - # This usually happens with the following example - # template code - # - # {{a = '}}'}} - # or - # {{a = '}}blahblah{{'}} - # - # This will fix these - # This is commented out because the current template - # system has this same limitation. Since this has a - # performance hit on larger templates, I do not recommend - # using this code on production systems. This is still here - # for "i told you it *can* be fixed" purposes. - # - # -# if line.count("'") % 2 != 0 or line.count('"') % 2 != 0: -# -# # Look ahead -# la = 1 -# nextline = ij[j+la] -# -# # As long as we have not found our ending -# # brackets keep going -# while '}}' not in nextline: -# la += 1 -# nextline += ij[j+la] -# # clear this line, so we -# # don't attempt to parse it -# # this is why there is an "if i" -# # around line 530 -# ij[j+la] = '' -# -# # retrieve our index. -# index = nextline.index('}}') -# -# # Everything before the new brackets -# before = nextline[:index+2] -# -# # Everything after -# after = nextline[index+2:] -# -# # Make the next line everything after -# # so it parses correctly, this *should* be -# # all html -# ij[j+1] = after -# -# # Add everything before to the current line -# line += before - # Get rid of '{{' and '}}' line = line[2:-2].strip() @@ -633,9 +564,9 @@ class TemplateParser(object): # Perform block comment escaping. # This performs escaping ON anything # in between """ and """ - line = re.sub(TemplateParser.r_multiline, - remove_newline, - line) + line = sub(TemplateParser.r_multiline, + remove_newline, + line) if line.startswith('='): # IE: {{=response.title}} @@ -672,7 +603,7 @@ class TemplateParser(object): self.lexers[name](parser = self, value = value, top = top, - stack = self.stack,) + stack = stack) elif name == '=': # So we have a variable to insert into @@ -693,7 +624,7 @@ class TemplateParser(object): # so anything after this gets added # to this node. This allows us to # "nest" nodes. - self.stack.append(node) + stack.append(node) elif name == 'end' and not value.startswith('='): # We are done with this node. @@ -702,7 +633,7 @@ class TemplateParser(object): self.blocks[top.name] = top # Pop it. - self.stack.pop() + stack.pop() elif name == 'super' and not value.startswith('='): # Get our correct target name @@ -757,17 +688,17 @@ class TemplateParser(object): # So we can properly put a response.write() in place. continuation = False len_parsed = 0 - for k in range(len(tokens)): + for k, token in enumerate(tokens): - tokens[k] = tokens[k].strip() - len_parsed += len(tokens[k]) + token = tokens[k] = token.strip() + len_parsed += len(token) - if tokens[k].startswith('='): - if tokens[k].endswith('\\'): + if token.startswith('='): + if token.endswith('\\'): continuation = True - tokens[k] = "\n%s(%s" % (self.writer, tokens[k][1:].strip()) + tokens[k] = "\n%s(%s" % (self.writer, token[1:].strip()) else: - tokens[k] = "\n%s(%s)" % (self.writer, tokens[k][1:].strip()) + tokens[k] = "\n%s(%s)" % (self.writer, token[1:].strip()) elif continuation: tokens[k] += ')' continuation = False @@ -912,7 +843,7 @@ def render(content = "hello world", # Add it to the context so we can use it. if not 'NOESCAPE' in context: - context['NOESCAPE'] = XML + context['NOESCAPE'] = NOESCAPE # save current response class if context and 'response' in context: diff --git a/gluon/tests/test_dal.py b/gluon/tests/test_dal.py index 9d5c085c..79e35c26 100644 --- a/gluon/tests/test_dal.py +++ b/gluon/tests/test_dal.py @@ -129,6 +129,26 @@ class TestFields(unittest.TestCase): ) self.assertEqual(db.t.insert(a=t0), 1) self.assertEqual(db().select(db.t.a)[0].a, t0) + + ## Row APIs + row = db().select(db.t.a)[0] + self.assertEqual(db.t[1].a,t0) + self.assertEqual(db.t['a'],db.t.a) + self.assertEqual(db.t(1).a,t0) + self.assertTrue(db.t(1,a=None)==None) + self.assertFalse(db.t(1,a=t0)==None) + self.assertEqual(row.a,t0) + self.assertEqual(row['a'],t0) + self.assertEqual(row['t.a'],t0) + self.assertEqual(row('t.a'),t0) + + ## Lazy and Virtual fields + db.t.b = Field.Virtual(lambda row: row.t.a) + db.t.c = Field.Lazy(lambda row: row.t.a) + row = db().select(db.t.a)[0] + self.assertEqual(row.b,t0) + self.assertEqual(row.c(),t0) + db.t.drop() db.define_table('t', Field('a', 'time', default='11:30')) t0 = datetime.time(10, 30, 55) @@ -369,6 +389,17 @@ class TestJoin(unittest.TestCase): db.t1.drop() db.t2.drop() + db.define_table('person',Field('name')) + id = db.person.insert(name="max") + self.assertEqual(id.name,'max') + db.define_table('dog',Field('name'),Field('owner','reference person')) + db.dog.insert(name='skipper',owner=1) + row = db(db.person.id==db.dog.owner).select().first() + self.assertEqual(row[db.person.name],'max') + self.assertEqual(row['person.name'],'max') + db.dog.drop() + self.assertEqual(len(db.person._referenced_by),0) + db.person.drop() class TestMinMaxSum(unittest.TestCase): diff --git a/gluon/tests/test_languages.py b/gluon/tests/test_languages.py index 7bf30d71..bcff8de4 100644 --- a/gluon/tests/test_languages.py +++ b/gluon/tests/test_languages.py @@ -17,6 +17,7 @@ import languages import tempfile import threading import logging +from storage import Storage try: import multiprocessing @@ -53,6 +54,39 @@ try: for result in results: self.assertTrue(result) + + class TestTranslations(unittest.TestCase): + + def setUp(self): + self.request = Storage() + self.request.folder = 'applications/welcome' + self.request.env = Storage() + self.request.env.http_accept_language = 'en' + + + def tearDown(self): + pass + + def test_plain(self): + T = languages.translator(self.request) + self.assertEqual(str(T('Hello World')), + 'Hello World') + self.assertEqual(str(T('Hello World## comment')), + 'Hello World') + self.assertEqual(str(T('%s %%{shop}', 1)), + '1 shop') + self.assertEqual(str(T('%s %%{shop}', 2)), + '2 shops') + self.assertEqual(str(T('%s %%{shop[0]}', 1)), + '1 shop') + self.assertEqual(str(T('%s %%{shop[0]}', 2)), + '2 shops') + self.assertEqual(str(T.M('**Hello World**')), + 'Hello World') + T.force('it') + self.assertEqual(str(T('Hello World')), + 'Salve Mondo') + except ImportError: logging.warning("Skipped test case, no multiprocessing module.") diff --git a/gluon/tools.py b/gluon/tools.py index ce086c9d..e51e3d33 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -31,6 +31,7 @@ from utils import web2py_uuid from fileutils import read_file, check_credentials from gluon import * from gluon.contrib.autolinks import expand_one +from gluon.dal import Row import serializers @@ -798,6 +799,141 @@ def addrow(form, a, b, c, style, _id, position=-1): class Auth(object): + + default_settings = { + 'hideerror': False, + 'password_min_length': 4, + 'cas_maps': None, + 'reset_password_requires_verification': False, + 'registration_requires_verification': False, + 'registration_requires_approval': False, + 'login_after_registration': False, + 'login_after_password_change': True, + 'alternate_requires_registration': False, + 'create_user_groups': "user_%(id)s", + 'everybody_group_id': None, + 'login_captcha': None, + 'register_captcha': None, + 'retrieve_username_captcha': None, + 'retrieve_password_captcha': None, + 'captcha': None, + 'expiration': 3600, # one hour + 'long_expiration': 3600*30*24, # one month + 'remember_me_form': True, + 'allow_basic_login': False, + 'allow_basic_login_only': False, + 'on_failed_authentication': lambda x: redirect(x), + 'formstyle': 'table3cols', + 'label_separator': ': ', + 'password_field': 'password', + 'table_user_name': 'auth_user', + 'table_group_name': 'auth_group', + 'table_membership_name': 'auth_membership', + 'table_permission_name': 'auth_permission', + 'table_event_name': 'auth_event', + 'table_cas_name': 'auth_cas', + 'table_user': None, + 'table_group': None, + 'table_membership': None, + 'table_permission': None, + 'table_event': None, + 'table_cas': None, + 'showid': False, + 'login_email_validate': True, + 'login_userfield': None, + 'logout_onlogout': None, + 'register_fields': None, + 'register_verify_password': True, + 'profile_fields': None, + 'email_case_sensitive': True, + 'username_case_sensitive': True, + } + # ## these are messages that can be customized + default_messages = { + 'login_button': 'Login', + 'register_button': 'Register', + 'password_reset_button': 'Request reset password', + 'password_change_button': 'Change password', + 'profile_save_button': 'Save profile', + 'submit_button': 'Submit', + 'verify_password': 'Verify Password', + 'delete_label': 'Check to delete', + 'function_disabled': 'Function disabled', + 'access_denied': 'Insufficient privileges', + 'registration_verifying': 'Registration needs verification', + 'registration_pending': 'Registration is pending approval', + 'login_disabled': 'Login disabled by administrator', + 'logged_in': 'Logged in', + 'email_sent': 'Email sent', + 'unable_to_send_email': 'Unable to send email', + 'email_verified': 'Email verified', + 'logged_out': 'Logged out', + 'registration_successful': 'Registration successful', + 'invalid_email': 'Invalid email', + 'unable_send_email': 'Unable to send email', + 'invalid_login': 'Invalid login', + 'invalid_user': 'Invalid user', + 'invalid_password': 'Invalid password', + 'is_empty': "Cannot be empty", + 'mismatched_password': "Password fields don't match", + 'verify_email': 'Click on the link %(link)s to verify your email', + 'verify_email_subject': 'Email verification', + 'username_sent': 'Your username was emailed to you', + 'new_password_sent': 'A new password was emailed to you', + 'password_changed': 'Password changed', + 'retrieve_username': 'Your username is: %(username)s', + 'retrieve_username_subject': 'Username retrieve', + 'retrieve_password': 'Your password is: %(password)s', + 'retrieve_password_subject': 'Password retrieve', + 'reset_password': \ + 'Click on the link %(link)s to reset your password', + 'reset_password_subject': 'Password reset', + 'invalid_reset_password': 'Invalid reset password', + 'profile_updated': 'Profile updated', + 'new_password': 'New password', + 'old_password': 'Old password', + 'group_description': 'Group uniquely assigned to user %(id)s', + 'register_log': 'User %(id)s Registered', + 'login_log': 'User %(id)s Logged-in', + 'login_failed_log': None, + 'logout_log': 'User %(id)s Logged-out', + 'profile_log': 'User %(id)s Profile updated', + 'verify_email_log': 'User %(id)s Verification email sent', + 'retrieve_username_log': 'User %(id)s Username retrieved', + 'retrieve_password_log': 'User %(id)s Password retrieved', + 'reset_password_log': 'User %(id)s Password reset', + 'change_password_log': 'User %(id)s Password changed', + 'add_group_log': 'Group %(group_id)s created', + 'del_group_log': 'Group %(group_id)s deleted', + 'add_membership_log': None, + 'del_membership_log': None, + 'has_membership_log': None, + 'add_permission_log': None, + 'del_permission_log': None, + 'has_permission_log': None, + 'impersonate_log': 'User %(id)s is impersonating %(other_id)s', + 'label_first_name': 'First name', + 'label_last_name': 'Last name', + 'label_username': 'Username', + 'label_email': 'E-mail', + 'label_password': 'Password', + 'label_registration_key': 'Registration key', + 'label_reset_password_key': 'Reset Password key', + 'label_registration_id': 'Registration identifier', + 'label_role': 'Role', + 'label_description': 'Description', + 'label_user_id': 'User ID', + 'label_group_id': 'Group ID', + 'label_name': 'Name', + 'label_table_name': 'Object or table name', + 'label_record_id': 'Record ID', + 'label_time_stamp': 'Timestamp', + 'label_client_ip': 'Client IP', + 'label_origin': 'Origin', + 'label_remember_me': "Remember me (for 30 days)", + 'verify_password_comment': 'please input your password again', + } + """ Class for authentication, authorization, role based access control. @@ -894,10 +1030,11 @@ class Auth(object): open(filename,'w').write(key) return key - def url(self, f=None, args=None, vars=None): + def url(self, f=None, args=None, vars=None, scheme=False): if args is None: args=[] if vars is None: vars={} - return URL(c=self.settings.controller, f=f, args=args, vars=vars) + return URL(c=self.settings.controller, + f=f, args=args, vars=vars,scheme=scheme) def here(self): return URL(args=current.request.args,vars=current.request.vars) @@ -933,221 +1070,67 @@ class Auth(object): else: self.user = None session.auth = None - settings = self.settings = Settings() - # ## what happens after login? self.next = current.request.vars._next if isinstance(self.next,(list,tuple)): self.next = self.next[0] - + url_index = URL(controller,'index') + url_login = URL(controller,function,args='login') # ## what happens after registration? - - settings.hideerror = False - settings.password_min_length = 4 - settings.cas_domains = [request.env.http_host] - settings.cas_provider = cas_provider - settings.cas_actions = {'login':'login', - 'validate':'validate', - 'servicevalidate':'serviceValidate', - 'proxyvalidate':'proxyValidate', - 'logout':'logout'} - settings.cas_maps = None - settings.extra_fields = {} - settings.actions_disabled = [] - settings.reset_password_requires_verification = False - settings.registration_requires_verification = False - settings.registration_requires_approval = False - settings.login_after_registration = False - settings.alternate_requires_registration = False - settings.create_user_groups = "user_%(id)s" - settings.everybody_group_id = None - - settings.controller = controller - settings.function = function - settings.login_url = self.url(function, args='login') - settings.logged_url = self.url(function, args='profile') - settings.download_url = self.url('download') - settings.mailer = (mailer==True) and Mail() or mailer - settings.login_captcha = None - settings.register_captcha = None - settings.retrieve_username_captcha = None - settings.retrieve_password_captcha = None - settings.captcha = None - settings.expiration = 3600 # one hour - settings.long_expiration = 3600*30*24 # one month - settings.remember_me_form = True - settings.allow_basic_login = False - settings.allow_basic_login_only = False - settings.on_failed_authorization = \ - self.url(function, args='not_authorized') - - settings.on_failed_authentication = lambda x: redirect(x) - - settings.formstyle = 'table3cols' - settings.label_separator = ': ' - - # ## table names to be used - - settings.password_field = 'password' - settings.table_user_name = 'auth_user' - settings.table_group_name = 'auth_group' - settings.table_membership_name = 'auth_membership' - settings.table_permission_name = 'auth_permission' - settings.table_event_name = 'auth_event' - settings.table_cas_name = 'auth_cas' - - # ## if none, they will be created, unless DAL(lazy_tables=True)!!! - - settings.table_user = None - settings.table_group = None - settings.table_membership = None - settings.table_permission = None - settings.table_event = None - settings.table_cas = None - - # ## - - settings.showid = False - - # ## these should be functions or lambdas - - settings.login_next = self.url('index') - settings.login_onvalidation = [] - settings.login_onaccept = [] - settings.login_methods = [self] - settings.login_form = self - settings.login_email_validate = True - settings.login_userfield = None - - settings.logout_next = self.url('index') - settings.logout_onlogout = None - - settings.register_next = self.url('index') - settings.register_onvalidation = [] - settings.register_onaccept = [] - settings.register_fields = None - settings.register_verify_password = True - - settings.verify_email_next = self.url(function, args='login') - settings.verify_email_onaccept = [] - - settings.profile_next = self.url('index') - settings.profile_onvalidation = [] - settings.profile_onaccept = [] - settings.profile_fields = None - settings.retrieve_username_next = self.url('index') - settings.retrieve_password_next = self.url('index') - settings.request_reset_password_next = self.url(function, args='login') - settings.reset_password_next = self.url(function, args='login') - - settings.change_password_next = self.url('index') - settings.change_password_onvalidation = [] - settings.change_password_onaccept = [] - - settings.retrieve_password_onvalidation = [] - settings.reset_password_onvalidation = [] - settings.reset_password_onaccept = [] - - settings.email_case_sensitive = True - settings.username_case_sensitive = True - - settings.hmac_key = hmac_key + + settings = self.settings = Settings() + settings.update(Auth.default_settings) + settings.update({ + 'cas_domains': [request.env.http_host], + 'cas_provider': cas_provider, + 'cas_actions': {'login':'login', + 'validate':'validate', + 'servicevalidate':'serviceValidate', + 'proxyvalidate':'proxyValidate', + 'logout':'logout'}, + 'extra_fields': {}, + 'actions_disabled': [], + 'controller': controller, + 'function': function, + 'login_url': url_login, + 'logged_url': URL(controller, function, args='profile'), + 'download_url': URL(controller,'download'), + 'mailer': (mailer==True) and Mail() or mailer, + 'on_failed_authorization': \ + URL(controller,function, args='not_authorized'), + 'login_next': url_index, + 'login_onvalidation': [], + 'login_onaccept': [], + 'login_methods': [self], + 'login_form': self, + 'logout_next': url_index, + 'logout_onlogout': None, + 'register_next': url_index, + 'register_onvalidation': [], + 'register_onaccept': [], + 'verify_email_next': url_login, + 'verify_email_onaccept': [], + 'profile_next': url_index, + 'profile_onvalidation': [], + 'profile_onaccept': [], + 'retrieve_username_next': url_index, + 'retrieve_password_next': url_index, + 'request_reset_password_next': url_login, + 'reset_password_next': url_index, + 'change_password_next': url_index, + 'change_password_onvalidation': [], + 'change_password_onaccept': [], + 'retrieve_password_onvalidation': [], + 'reset_password_onvalidation': [], + 'reset_password_onaccept': [], + 'hmac_key': hmac_key, + }) settings.lock_keys = True # ## these are messages that can be customized messages = self.messages = Messages(current.T) - messages.login_button = 'Login' - messages.register_button = 'Register' - messages.password_reset_button = 'Request reset password' - messages.password_change_button = 'Change password' - messages.profile_save_button = 'Save profile' - messages.submit_button = 'Submit' - messages.verify_password = 'Verify Password' - messages.delete_label = 'Check to delete' - messages.function_disabled = 'Function disabled' - messages.access_denied = 'Insufficient privileges' - messages.registration_verifying = 'Registration needs verification' - messages.registration_pending = 'Registration is pending approval' - messages.login_disabled = 'Login disabled by administrator' - messages.logged_in = 'Logged in' - messages.email_sent = 'Email sent' - messages.unable_to_send_email = 'Unable to send email' - messages.email_verified = 'Email verified' - messages.logged_out = 'Logged out' - messages.registration_successful = 'Registration successful' - messages.invalid_email = 'Invalid email' - messages.unable_send_email = 'Unable to send email' - messages.invalid_login = 'Invalid login' - messages.invalid_user = 'Invalid user' - messages.invalid_password = 'Invalid password' - messages.is_empty = "Cannot be empty" - messages.mismatched_password = "Password fields don't match" - messages.verify_email = \ - 'Click on the link ' + \ - URL('default','user',args='verify_email',scheme=True) + \ - '/%(key)s to verify your email' - messages.verify_email_subject = 'Email verification' - messages.username_sent = 'Your username was emailed to you' - messages.new_password_sent = 'A new password was emailed to you' - messages.password_changed = 'Password changed' - messages.retrieve_username = 'Your username is: %(username)s' - messages.retrieve_username_subject = 'Username retrieve' - messages.retrieve_password = 'Your password is: %(password)s' - messages.retrieve_password_subject = 'Password retrieve' - messages.reset_password = \ - 'Click on the link ' + \ - URL('default','user',args='reset_password',scheme=True) + \ - '/%(key)s to reset your password' - messages.reset_password_subject = 'Password reset' - messages.invalid_reset_password = 'Invalid reset password' - messages.profile_updated = 'Profile updated' - messages.new_password = 'New password' - messages.old_password = 'Old password' - messages.group_description = \ - 'Group uniquely assigned to user %(id)s' - - messages.register_log = 'User %(id)s Registered' - messages.login_log = 'User %(id)s Logged-in' - messages.login_failed_log = None - messages.logout_log = 'User %(id)s Logged-out' - messages.profile_log = 'User %(id)s Profile updated' - messages.verify_email_log = 'User %(id)s Verification email sent' - messages.retrieve_username_log = 'User %(id)s Username retrieved' - messages.retrieve_password_log = 'User %(id)s Password retrieved' - messages.reset_password_log = 'User %(id)s Password reset' - messages.change_password_log = 'User %(id)s Password changed' - messages.add_group_log = 'Group %(group_id)s created' - messages.del_group_log = 'Group %(group_id)s deleted' - messages.add_membership_log = None - messages.del_membership_log = None - messages.has_membership_log = None - messages.add_permission_log = None - messages.del_permission_log = None - messages.has_permission_log = None - messages.impersonate_log = 'User %(id)s is impersonating %(other_id)s' - - messages.label_first_name = 'First name' - messages.label_last_name = 'Last name' - messages.label_username = 'Username' - messages.label_email = 'E-mail' - messages.label_password = 'Password' - messages.label_registration_key = 'Registration key' - messages.label_reset_password_key = 'Reset Password key' - messages.label_registration_id = 'Registration identifier' - messages.label_role = 'Role' - messages.label_description = 'Description' - messages.label_user_id = 'User ID' - messages.label_group_id = 'Group ID' - messages.label_name = 'Name' - messages.label_table_name = 'Object or table name' - messages.label_record_id = 'Record ID' - messages.label_time_stamp = 'Timestamp' - messages.label_client_ip = 'Client IP' - messages.label_origin = 'Origin' - messages.label_remember_me = "Remember me (for 30 days)" - messages['T'] = current.T - messages.verify_password_comment = 'please input your password again' + messages.update(Auth.default_messages) messages.lock_keys = True # for "remember me" option @@ -1336,37 +1319,39 @@ class Auth(object): settings = self.settings request = current.request T = current.T - def lazy_user (auth = self): return auth.user_id reference_user = 'reference %s' % settings.table_user_name + def lazy_user (auth = self): + return auth.user_id def represent(id,record=None,s=settings): try: user = s.table_user(id) return '%(first_name)s %(last_name)s' % user - except: return id - self.signature = db.Table(self.db,'auth_signature', - Field('is_active','boolean', - default=True, - readable=False, writable=False, - label=T('Is Active')), - Field('created_on','datetime', - default=request.now, - writable=False, readable=False, - label=T('Created On')), - Field('created_by', - reference_user, - default=lazy_user, represent=represent, - writable=False, readable=False, - label=T('Created By')), - Field('modified_on','datetime', - update=request.now,default=request.now, - writable=False,readable=False, - label=T('Modified On')), - Field('modified_by', - reference_user,represent=represent, - default=lazy_user,update=lazy_user, - writable=False,readable=False, - label=T('Modified By'))) - + except: + return id + self.signature = db.Table( + self.db,'auth_signature', + Field('is_active','boolean', + default=True, + readable=False, writable=False, + label=T('Is Active')), + Field('created_on','datetime', + default=request.now, + writable=False, readable=False, + label=T('Created On')), + Field('created_by', + reference_user, + default=lazy_user, represent=represent, + writable=False, readable=False, + label=T('Created By')), + Field('modified_on','datetime', + update=request.now,default=request.now, + writable=False,readable=False, + label=T('Modified On')), + Field('modified_by', + reference_user,represent=represent, + default=lazy_user,update=lazy_user, + writable=False,readable=False, + label=T('Modified By'))) def define_tables(self, username=False, signature=None, migrate=True, fake_migrate=False): @@ -1396,8 +1381,7 @@ class Auth(object): elif isinstance(signature,self.db.Table): signature_list = [signature] else: - signature_list = signature - lazy_tables, db._lazy_tables = db._lazy_tables, False + signature_list = signature is_not_empty = IS_NOT_EMPTY(error_message=self.messages.is_empty) is_crypted = CRYPT(key=settings.hmac_key, min_length=settings.password_min_length) @@ -1600,7 +1584,6 @@ class Auth(object): actions=actions, maps=maps) - def log_event(self, description, vars=None, origin='auth'): """ usage: @@ -1667,6 +1650,11 @@ class Auth(object): return user def basic(self): + """ + perform basic login. + reads current.request.env.http_authorization + and returns basic_allowed,basic_accepted,user + """ if not self.settings.allow_basic_login: return (False,False,False) basic = current.request.env.http_authorization @@ -1675,11 +1663,23 @@ class Auth(object): (username, password) = base64.b64decode(basic[6:]).split(':') return (True, True, self.login_bare(username, password)) + def login_user(self,user): + """ + login the user = db.auth_user(id) + """ + # user=Storage(self.table_user()._filter_fields(user,id=True)) + current.session.auth = Storage( + user = user, + last_visit = current.request.now, + expiration = self.settings.expiration, + hmac_key = web2py_uuid()) + self.user = user + self.update_groups() + def login_bare(self, username, password): """ - logins user + logins user as specified by usernname (or email) and password """ - request = current.request session = current.session table_user = self.table_user() @@ -1694,12 +1694,7 @@ class Auth(object): if user and user.get(passfield,False): password = table_user[passfield].validate(password)[0] if not user.registration_key and password == user[passfield]: - user = Storage(table_user._filter_fields(user, id=True)) - session.auth = Storage(user=user, last_visit=request.now, - expiration=self.settings.expiration, - hmac_key = web2py_uuid()) - self.user = user - self.update_groups() + self.login_user(user) return user else: # user not in database try other login methods @@ -1738,15 +1733,15 @@ class Auth(object): renew=interactivelogin) service = session._cas_service del session._cas_service - if request.vars.has_key('warn') and not interactivelogin: + if 'warn' in request.vars and not interactivelogin: response.headers['refresh'] = "5;URL=%s"%service+"?ticket="+ticket return A("Continue to %s"%service, _href=service+"?ticket="+ticket) else: redirect(service+"?ticket="+ticket) - if self.is_logged_in() and not request.vars.has_key('renew'): + if self.is_logged_in() and not 'renew' in request.vars: return allow_access() - elif not self.is_logged_in() and request.vars.has_key('gateway'): + elif not self.is_logged_in() and 'gateway' in request.vars: redirect(service) def cas_onaccept(form, onaccept=onaccept): if not onaccept is DEFAULT: onaccept(form) @@ -1759,7 +1754,7 @@ class Auth(object): db, table = self.db, self.table_cas() current.response.headers['Content-Type']='text' ticket = request.vars.ticket - renew = True if request.vars.has_key('renew') else False + renew = 'renew' in request.vars row = table(ticket=ticket) success = False if row: @@ -1973,25 +1968,18 @@ class Auth(object): # process authenticated users if user: - user = Storage(table_user._filter_fields(user, id=True)) - + user = Row(table_user._filter_fields(user, id=True)) # process authenticated users # user wants to be logged in for longer - session.auth = Storage( - user = user, - last_visit = request.now, - expiration = request.vars.get("remember",False) and \ - self.settings.long_expiration or self.settings.expiration, - remember = request.vars.has_key("remember"), - hmac_key = web2py_uuid() - ) - - self.user = user + self.login_user(user) + session.auth.expiration = \ + request.vars.get('remember',False) and \ + self.settings.long_expiration or \ + self.settings.expiration + session.auth.remember = 'remember' in request.vars self.log_event(log, user) session.flash = self.messages.logged_in - self.update_groups() - # how to continue if self.settings.login_form == self: if accepted_form: @@ -2131,11 +2119,14 @@ class Auth(object): if self.settings.everybody_group_id: self.add_membership(self.settings.everybody_group_id, form.vars.id) if self.settings.registration_requires_verification: + link = self.url('user',args=('verify_email',key),scheme=True) + if not self.settings.mailer or \ - not self.settings.mailer.send(to=form.vars.email, - subject=self.messages.verify_email_subject, - message=self.messages.verify_email - % dict(key=key)): + not self.settings.mailer.send( + to=form.vars.email, + subject=self.messages.verify_email_subject, + message=self.messages.verify_email \ + % dict(key=key,link=link)): self.db.rollback() response.flash = self.messages.unable_send_email return form @@ -2149,13 +2140,10 @@ class Auth(object): if not self.settings.registration_requires_verification: table_user[form.vars.id] = dict(registration_key='') session.flash = self.messages.registration_successful - user = self.db(table_user[username] == form.vars[username]).select().first() - user = Storage(table_user._filter_fields(user, id=True)) - session.auth = Storage(user=user, last_visit=request.now, - expiration=self.settings.expiration, - hmac_key = web2py_uuid()) - self.user = user - self.update_groups() + user = self.db( + table_user[username] == form.vars[username] + ).select().first() + self.login_user(user) session.flash = self.messages.logged_in self.log_event(log, form.vars) callback(onaccept,form) @@ -2192,7 +2180,7 @@ class Auth(object): key = getarg(-1) table_user = self.table_user() - user = self.db(table_user.registration_key == key).select().first() + user = table_user(registration_key=key) if not user: redirect(self.settings.login_url) if self.settings.registration_requires_approval: @@ -2267,7 +2255,7 @@ class Auth(object): if form.accepts(request, session, formname='retrieve_username', dbio=False, onvalidation=onvalidation,hideerror=self.settings.hideerror): - user = self.db(table_user.email == form.vars.email).select().first() + user = table_user(email=form.vars.email) if not user: current.session.flash = \ self.messages.invalid_email @@ -2345,7 +2333,7 @@ class Auth(object): if form.accepts(request, session, formname='retrieve_password', dbio=False, onvalidation=onvalidation,hideerror=self.settings.hideerror): - user = self.db(table_user.email == form.vars.email).select().first() + user = table_user(email=form.vars.email) if not user: current.session.flash = \ self.messages.invalid_email @@ -2398,12 +2386,12 @@ class Auth(object): session = current.session if next is DEFAULT: - next = self.next or self.settings.reset_password_next + next = self.settings.reset_password_next try: key = request.vars.key or getarg(-1) t0 = int(key.split('-')[0]) if time.time()-t0 > 60*60*24: raise Exception - user = self.db(table_user.reset_password_key == key).select().first() + user = table_user(reset_password_key=key) if not user: raise Exception except Exception: session.flash = self.messages.invalid_reset_password @@ -2422,11 +2410,15 @@ class Auth(object): formstyle=self.settings.formstyle, separator=self.settings.label_separator ) - if form.accepts(request,session,hideerror=self.settings.hideerror): - user.update_record(**{passfield:str(form.vars.new_password), - 'registration_key':'', - 'reset_password_key':''}) + if form.accepts(request,session, + hideerror=self.settings.hideerror): + user.update_record( + **{passfield:str(form.vars.new_password), + 'registration_key':'', + 'reset_password_key':''}) session.flash = self.messages.password_changed + if self.settings.login_after_password_change: + self.login_user(user) redirect(next) return form @@ -2481,7 +2473,7 @@ class Auth(object): formname='reset_password', dbio=False, onvalidation=onvalidation, hideerror=self.settings.hideerror): - user = self.db(table_user.email == form.vars.email).select().first() + user = table_user(email=form.vars.email) if not user: session.flash = self.messages.invalid_email redirect(self.url(args=request.args)) @@ -2504,11 +2496,14 @@ class Auth(object): def email_reset_password(self,user): reset_password_key = str(int(time.time()))+'-' + web2py_uuid() + link = self.url('user', + args=('reset_password',reset_password_key), + scheme=True) if self.settings.mailer.send( to=user.email, subject=self.messages.reset_password_subject, message=self.messages.reset_password % \ - dict(key=reset_password_key)): + dict(key=reset_password_key,link=link)): user.update_record(reset_password_key=reset_password_key) return True return False @@ -2684,7 +2679,8 @@ class Auth(object): self.user = auth.user if self.settings.login_onaccept: form = Storage(dict(vars=self.user)) - self.settings.login_onaccept(form) + for callback in self.settings.login_onaccept: + callback(form) log = self.messages.impersonate_log self.log_event(log,dict(id=current_id, other_id=auth.user.id)) elif user_id in (0, '0') and self.is_impersonating(): @@ -3142,18 +3138,21 @@ class Auth(object): elif form.record and fieldname in form.record: new_record[fieldname]=form.record[fieldname] if fields: - for key,value in fields.items(): - new_record[key] = value + new_record.update(fields) id = archive_table.insert(**new_record) return id - def wiki(self,slug=None,env=None,manage_permissions=False,force_prefix=''): + + def wiki(self,slug=None,env=None,manage_permissions=False,force_prefix='', resolve=True): if not hasattr(self,'_wiki'): self._wiki = Wiki(self, manage_permissions=manage_permissions, force_prefix=force_prefix,env=env) else: self._wiki.env.update(env or {}) - return self._wiki.read(slug)['content'] if slug else self._wiki() + # if resolve is set to True, process request as wiki call + # resolve=False allows initial setup without wiki redirection + if resolve: + return self._wiki.read(slug)['content'] if slug else self._wiki() class Crud(object): @@ -3714,14 +3713,14 @@ def universal_caller(f, *a, **b): # There might be pos_args left, that are sent as named_values. Gather them as well. # If a argument already is populated with values we simply replaces them. for arg_name in pos_args[len(arg_dict):]: - if b.has_key(arg_name): + if arg_name in b: arg_dict[arg_name] = b[arg_name] if len(arg_dict) >= len(pos_args): # All the positional arguments is found. The function may now be called. # However, we need to update the arg_dict with the values from the named arguments as well. for arg_name in named_args: - if b.has_key(arg_name): + if arg_name in b: arg_dict[arg_name] = b[arg_name] return f(**arg_dict) @@ -4136,7 +4135,7 @@ class Service(object): prefix='pys', documentation = documentation, ns = True) - for method, (function, returns, args, doc) in procedures.items(): + for method, (function, returns, args, doc) in procedures.iteritems(): dispatcher.register_function(method, function, returns, args, doc) if request.env.request_method == 'POST': # Process normal Soap Operation @@ -4392,8 +4391,9 @@ class PluginManager(object): self.__dict__.clear() settings = self.__getattr__(plugin) settings.installed = True - [settings.update({key:value}) for key,value in defaults.items() \ - if not key in settings] + settings.update( + (k,v) for k,v in defaults.items() if not k in settings) + def __getattr__(self, key): if not key in self.__dict__: self.__dict__[key] = Storage() @@ -4494,32 +4494,48 @@ class Wiki(object): self.host = current.request.env.http_host perms = self.manage_permissions = manage_permissions db = auth.db - db.define_table( - 'wiki_page', - Field('slug', - requires=[IS_SLUG(),IS_NOT_IN_DB(db,'wiki_page.slug')], - readable=False,writable=False), - Field('title',unique=True), - Field('body','text',notnull=True), - Field('tags','list:string'), - Field('can_read','list:string',writable=perms,readable=perms, - default=[Wiki.everybody]), - Field('can_edit','list:string',writable=perms,readable=perms, - default=[Wiki.everybody]), - Field('changelog'), - Field('html','text',readable=False,writable=False,compute=render), - auth.signature,format='%(title)s') - db.define_table( - 'wiki_tag', - Field('name'), - Field('wiki_page',db.wiki_page), - auth.signature,format='%(name)s') - db.define_table( - 'wiki_media', - Field('wiki_page',db.wiki_page), - Field('title',required=True), - Field('file','upload',required=True), - auth.signature,format='%(title)s') + table_definitions = { + 'wiki_page':{ + 'args':[ + Field('slug', + requires=[IS_SLUG(), + IS_NOT_IN_DB(db,'wiki_page.slug')], + readable=False,writable=False), + Field('title',unique=True), + Field('body','text',notnull=True), + Field('tags','list:string'), + Field('can_read','list:string', + writable=perms, + readable=perms, + default=[Wiki.everybody]), + Field('can_edit', 'list:string', + writable=perms,readable=perms, + default=[Wiki.everybody]), + Field('changelog'), + Field('html','text',compute=render, + readable=False, writable=False), + auth.signature], + 'vars':{'format':'%(title)s'}}, + 'wiki_tag':{ + 'args':[ + Field('name'), + Field('wiki_page','reference wiki_page'), + auth.signature], + 'vars':{'format':'%(name)s'}}, + 'wiki_media':{ + 'args':[ + Field('wiki_page','reference wiki_page'), + Field('title',required=True), + Field('file','upload',required=True), + auth.signature], + 'vars':{'format':'%(title)s'}} + } + + # define only non-existent tables + for key, value in table_definitions.iteritems(): + if not key in db.tables(): + db.define_table(key, *value['args'], **value['vars']) + def update_tags_insert(page,id,db=db): for tag in page.tags or []: tag = tag.strip().lower()