Compare commits

...
232 Commits
Author SHA1 Message Date
mdipierro 4599dcd988 R-2.3.2 2012-12-17 09:00:46 -06:00
mdipierro 14bdfd3321 fixed issue 1227, entropy check with IS_STRONG, thanks Clavin Sim 2012-12-17 08:50:08 -06:00
mdipierro e7d14c028b fixed issue 1225, NEWINSTALL ignored 2012-12-17 08:46:33 -06:00
mdipierro 0207a17afa cursor point in share.js, issue 1123, thanks Nathan 2012-12-16 12:36:28 -06:00
mdipierro 73b049f361 added oneall login support, issue 1124, thanks Nathan 2012-12-16 12:34:08 -06:00
mdipierro 5695fe34f0 fixed example in examples from pull-request, thanks tpng 2012-12-14 14:28:31 -06:00
mdipierro f2e44f96d6 R-2.3.1 2012-12-14 09:22:09 -06:00
mdipierro 2ccc707059 modernizr 2.6.2 2012-12-14 09:21:00 -06:00
mdipierro 30490a0c5c fixed possible issue with share.js 2012-12-14 09:17:30 -06:00
mdipierro 4c1102026d upgraded bootstrap, jquery, and analytics 2012-12-14 08:24:58 -06:00
mdipierro 63b589170c fixed paths in admin debug.py, thanks Mariano 2012-12-13 18:09:11 -06:00
mdipierro 2b0d098027 CHANGELOG edits 2012-12-13 12:54:39 -06:00
mdipierro fcfaa63f33 edited CHANGELOG, 2.3.0 rc2 2012-12-13 11:53:30 -06:00
mdipierro f497aa7fcf fixed aes 2012-12-13 11:28:52 -06:00
mdipierro d91f7381e1 allow web shell working when https is required 2012-12-13 11:10:59 -06:00
mdipierro bad0af15f6 removed debug print statement, thanks Niphlod 2012-12-13 08:22:10 -06:00
mdipierro d7cc15c85d partially fixed issue 832, auth.requires raises 401 on ajax, thanks Paolo Valleri 2012-12-12 22:07:20 -06:00
mdipierro 1f1e65dcb5 fixed formstyle_bootstrap, thanks Anthony 2012-12-12 22:03:39 -06:00
mdipierro 930d4dcdd0 added NEWINSTALL to git, issue 1217, thanks dev.ldhughes 2012-12-12 21:49:27 -06:00
mdipierro b640820052 fixed ip4 client validation, issue 1218, thanks Joachim Breitsprecher 2012-12-12 21:47:55 -06:00
mdipierro be0003927a fixed css issue 1219, thanks Paolo 2012-12-12 21:46:09 -06:00
mdipierro 0015a265a9 analytics.js 2012-12-12 21:30:57 -06:00
mdipierro 12ff451f4b allow LOADing multiple grids, thanks Niphlod 2012-12-12 21:14:25 -06:00
mdipierro 63cefe0862 fixed typo in docstring, issue 1210, thanks francois.delpierre 2012-12-11 20:50:10 -06:00
mdipierro bf3a24e515 revised setup-web2py-nginx-uwsgi-ubuntu.sh, thanks Vinicious 2012-12-11 20:15:15 -06:00
mdipierro 4378a8a792 fixed typo in globals, issue 1213, thanks jkellas 2012-12-11 15:54:57 -06:00
mdipierro 1532cecb25 Added intro tutorial, thanks Michael Herman 2012-12-11 10:53:31 -06:00
mdipierro 22af4db51d sorting importing models was broken, now fixed, thanks Joel Samuelsson 2012-12-11 08:25:48 -06:00
mdipierro 523cb34119 fixed winservice problem 2012-12-10 21:32:36 -06:00
mdipierro 24b037c307 fixed problem with clear and session_hash 2012-12-09 14:29:37 -06:00
mdipierro bd933ca43d fixed issue 1208 (auth on GAE) by disabling virtual fields in auth.user on GAE 2012-12-08 18:31:41 -06:00
mdipierro 676b2ef54b fixed issue 1208 (auth on GAE) by disabling virtual fields in auth.user on GAE 2012-12-08 18:25:04 -06:00
mdipierro 353a66f44c fixed issue 1207, IS_IN_SET(list_of_ints), thanks Alan 2012-12-07 10:58:43 -06:00
mdipierro 689dfcd83e fixed problem CRYPT password comparsion, issue 1203, thanks Alan 2012-12-06 23:04:29 -06:00
mdipierro 8f7b82fdb3 fixed escaping of response.js, issue 1205, thanks max.morais.dmm 2012-12-06 23:02:09 -06:00
mdipierro c574a97cad regex simplification 2012-12-06 16:56:29 -06:00
mdipierro 5e7de996e0 fixed issue 1202, commas in attachments, thanks simonm3 2012-12-05 16:49:24 -06:00
mdipierro 52ba4bb0ea fixed issue 1187, custom widget hadnling error in case for nonzero formatter, thanks Maria Mitica 2012-12-05 16:34:55 -06:00
mdipierro c43aa3545f himBH>jQuery, thanks Niphlod 2012-12-05 15:33:30 -06:00
mdipierro 8e48a816f8 better paymenttech support, BSD license 2012-12-05 15:31:38 -06:00
mdipierro afef829571 fixed IS_STRONG **** issue, issue 1098 2012-12-05 15:24:15 -06:00
mdipierro f4e5de995c lazy sqlhtml_validators, fixed issue 931 2012-12-05 14:18:00 -06:00
mdipierro 70a4e06f18 fixed web2py_bootstrap.css, thanks Paolo 2012-12-05 13:53:46 -06:00
mdipierro f241c008d4 allow more customization of db._adapter.types 2012-12-05 11:57:18 -06:00
mdipierro 9920b7592d fixed issue 440, reference to primary keys 2012-12-05 11:35:23 -06:00
mdipierro fee2c667b3 db.define_table('person',Field('name'),Field.Virtual('namey',lambda row: row.person.name+'y')), fixed issue 374 2012-12-05 11:23:11 -06:00
mdipierro ebc9d98a87 fixed issue 265 2012-12-05 11:03:16 -06:00
mdipierro 06f5a32c48 db.thing(name='Cohen',_orderby=db.thing.name), thanks Yair 2012-12-05 09:01:03 -06:00
mdipierro 35cb9ee529 experimental support for MSSQL pagination 2012-12-04 18:30:36 -06:00
mdipierro f0e59ca617 paymentech.py 2012-12-04 10:56:30 -06:00
mdipierro 1bbfd80c24 2.3.0 rc1 2012-12-04 09:02:41 -06:00
mdipierro a9600faa9f uri='informi-se://... 2012-12-04 08:48:27 -06:00
mdipierro 6f39f96799 added interact.html to git 2012-12-04 08:32:26 -06:00
mdipierro b06df4740b fixed filename in dal storage, thanks Marin 2012-12-03 18:02:45 -06:00
mdipierro d354e4f767 possibly fixed issue 1169 2012-12-03 17:39:17 -06:00
mdipierro caef44d4f9 fixed escape->encodeURIComponent in autocomplete, issue 1198, thanks Dmitry 2012-12-03 17:11:18 -06:00
mdipierro f9eb2c5a0a check_reserved in welcome, thanks Marin 2012-12-03 16:30:13 -06:00
mdipierro 3a05be49f6 closeflash patch, thanks Paolo, issue 1191 2012-12-03 16:06:27 -06:00
mdipierro b92e169b69 MENU(li_first, li_last..), fixed issue 1200, thanks dev to null 2012-12-03 14:42:37 -06:00
mdipierro 882f42de8f better grid errors, issue 1135 2012-12-03 14:28:00 -06:00
mdipierro c8e64ac4f7 fixed problem with raw_args 2012-12-03 14:04:17 -06:00
mdipierro da1751dc1b fixed cronjobs broken in 4278, fixed issue 1190 2012-12-03 13:16:14 -06:00
mdipierro 304ae277fe improved heroku script 2012-12-03 11:01:11 -06:00
mdipierro 0e93162080 support for in and not in smart_query 2012-12-03 08:15:58 -06:00
mdipierro 6ced9dd235 auth.settings.login_onfail, thanks Yair 2012-12-02 08:27:17 -06:00
mdipierro e2da57f448 added missing form.html to examples 2012-12-01 16:39:31 -06:00
mdipierro d0047e6e5b removed test, lazy table do not suport self references 2012-11-30 14:30:49 -06:00
mdipierro 90955bdcab wiki(menugroups=['wiki_editor']) 2012-11-30 09:02:35 -06:00
mdipierro d2b4099cdb fixed error reporting in dal 2012-11-30 08:34:11 -06:00
mdipierro 1e7315d4a8 fixed problem with lazy tables and self references 2012-11-29 23:54:29 -06:00
mdipierro d7ace92c04 Allow for Field Validators to handle None values, fixed issue 1183, thanks Joe Barnhart 2012-11-29 22:35:20 -06:00
mdipierro 568c33d7d6 allow -R ...pyc, fixed issue 1186, thanks Corne.Dickens 2012-11-29 18:21:06 -06:00
mdipierro ef8f10c42d added missing fileutils, fixed issue 1193, thanks Yager 2012-11-29 17:13:30 -06:00
mdipierro fc7c4432e9 fixed issue 1197, Virtual Fields are stored in session 2012-11-29 17:05:27 -06:00
mdipierro 04a7d9a92d do not redirect after auth.logout() if next is None 2012-11-29 09:52:48 -06:00
mdipierro b83673f1c8 new router patch fixes runaway vulnerability, thanks Jonathan 2012-11-27 11:29:36 -06:00
mdipierro ba21ce887a fixed bug in getlist thanks roger 2012-11-27 10:17:22 -06:00
mdipierro 5764482acd style upload button 2012-11-27 10:11:52 -06:00
mdipierro 1b0e08cfa0 fixed issue 1174, cache folder in examples 2012-11-24 11:12:20 -06:00
mdipierro e59cb43b0b fixed issue 1174, cache folder in examples 2012-11-24 11:07:07 -06:00
mdipierro 2cbca7a43d fixed issue 1176, truncate on GAE+SQL 2012-11-24 10:58:44 -06:00
mdipierro d2dd3d0ac6 fixed issue 1179, welcome.w2p created if not exists 2012-11-24 10:48:27 -06:00
mdipierro 6324ed7a9c added .woff contenttype, fixed issue 1181, thanks Chris 2012-11-24 10:35:47 -06:00
mdipierro 23595c0608 rocket support for IPV6, thanks Chirs Winebrinner 2012-11-24 10:15:37 -06:00
mdipierro eebc3418f9 Merge branch 'master' of github.com:web2py/web2py 2012-11-24 10:09:48 -06:00
mdipierro 867caae3da Merge pull request #44 from cwinebrinner/rocket_ipv6_and_cleanup
explorigin/Rocket merged and IPv6 support added
2012-11-24 08:06:54 -08:00
mdipierro d0098a878a fixed router regex runaway, thanks Jonathan 2012-11-23 11:58:36 -06:00
mdipierro ee7db631ee fixed ldap security issue, thanks demetrio 2012-11-23 08:02:01 -06:00
Charles Winebrinner b388f41f80 Added IPv6 support for Rocket, refactored some code, and fixed some bugs. 2012-11-18 01:03:04 -06:00
Charles Winebrinner 9f5391bbc0 Merged explorigin/Rocket and brought web2py's rocket more in line with upstream. 2012-11-18 00:32:24 -06:00
Charles Winebrinner 22ca52a1cb Fixed a typo in utils.py. 2012-11-18 00:32:24 -06:00
Charles Winebrinner b56cfb372d PEP8'd rocket.py.footer (to be removed from rocket.py). 2012-11-18 00:32:24 -06:00
mdipierro c8367e257f better heroku script 2012-11-17 22:28:51 -06:00
mdipierro 62d37702a9 better heroku support 2012-11-17 22:14:42 -06:00
mdipierro 74fc2a2d85 added heroku support 2012-11-17 21:38:28 -06:00
mdipierro 0ac1298501 fixed broken session in recent trunk 2012-11-17 13:28:50 -06:00
mdipierro faf76ac715 fixed issue 1173, request.requires_https, thanks Maciej 2012-11-17 12:14:28 -06:00
mdipierro 3ece96ae08 fixed typo in response.updated, issue 1167, thanks dedirock 2012-11-17 12:06:39 -06:00
mdipierro e91cf7f6ac better list widget, thanks Howesc 2012-11-17 12:04:29 -06:00
mdipierro 019d3e07b5 fixed issue 1152, gae sql varchar limit, and fixed typo in fpdf 2012-11-17 11:46:46 -06:00
mdipierro e3046845bf fixed image_map in gluon/contrib/fpdf/html.py 2012-11-17 09:16:07 -06:00
mdipierro b8f52ed76a fixed broken HTT_HOST in routes_in 2012-11-17 08:59:55 -06:00
mdipierro 662abd29cb extra or {}, thanks villas 2012-11-16 16:24:13 -06:00
mdipierro 3560337b40 auth.wiki(extra) 2012-11-15 14:34:20 -06:00
mdipierro c7985e8881 patches for @service.jsonrpc and exportclasses, thanks niphlod 2012-11-15 13:40:04 -06:00
mdipierro a69bc44314 fixed generic.xml 2012-11-15 12:29:28 -06:00
mdipierro 651c92c175 do not create a new session if nothing in session file 2012-11-14 15:33:18 -06:00
mdipierro 7319574f30 fixed issue 1160, show button for linked tables even if referenced column is not readable 2012-11-14 15:00:04 -06:00
mdipierro b9821f1c21 fixed issue 1158, redirect client_side in auth forms embedded via LOAD, thanks PyCon support 2012-11-14 14:12:32 -06:00
mdipierro 52ca6af024 possible solution to issue 1154, onvalidation = dict(onsuccess= [...]) 2012-11-14 13:47:56 -06:00
mdipierro cc4d27c6d2 jQuery 1.8.2 2012-11-14 08:44:11 -06:00
mdipierro b687977663 fixed 2.5 issues with scheduler 2012-11-13 16:27:26 -06:00
mdipierro 3e85f5bf39 fixed CAS login for extra url fields, thanks efaisal 2012-11-09 14:11:37 -06:00
mdipierro 23165d9382 fixed issue 1144, start webservert at 0.0.0.0 2012-11-08 16:19:44 -06:00
mdipierro 1abc31895e HTML(doctype=''), issue 1140 2012-11-08 11:29:47 -06:00
mdipierro 6fc70fbc55 fixed issue 1143, grid/smartgrid GAE improvements, thanks Howesc 2012-11-08 10:05:46 -06:00
mdipierro bf86becc5e fies typo in dal, issue 1146, thanks guruyaya 2012-11-08 10:04:24 -06:00
mdipierro 510142ad2d typo in compileapp, issue 1149, thanks Corne 2012-11-08 10:02:46 -06:00
mdipierro 6eb361d8f7 possibly fixed issue 1151 2012-11-08 09:59:10 -06:00
mdipierro e56f588dea fixed issue 1147, belongs(None), thanks Marin 2012-11-06 14:26:28 -06:00
mdipierro 0ee551de71 grid buttons_placement and links_placement , thanks Niphlod 2012-11-06 10:36:45 -06:00
mdipierro 7dc40f68db changed in custom_import 2012-11-06 09:47:02 -06:00
mdipierro adb0c08933 improved scheduler, thanks Niphlod 2012-11-05 12:39:17 -06:00
mdipierro 2fea9495b3 fixed rss serializer again, thanks Charles Winebrinner 2012-11-04 20:45:25 -06:00
mdipierro 1f767c3497 fixed rss serializer again, thanks Charles Winebrinner 2012-11-04 19:55:15 -06:00
mdipierro 09bae08dfa fixed rss2 again 2012-11-04 19:29:18 -06:00
mdipierro 8a137691ff fixed problem in rss2.py 2012-11-04 18:12:41 -06:00
mdipierro 7de90f18cc adding missing views 2012-11-04 09:14:47 -06:00
mdipierro 859636e6e0 fixed issue 1136, prevent redirection loop, better form, usability as embedded widgets, thanks Alan 2012-11-03 11:54:46 -05:00
mdipierro a511682ce1 better google wallet, checks parameters 2012-11-01 22:01:57 -05:00
mdipierro 6a81420fc0 many scheduler improvements, thanks Niphlod 2012-11-01 21:35:53 -05:00
mdipierro fa019e8960 fixed issue 1124, create new auth.wiki page from slug model, thanks Nico 2012-11-01 21:33:06 -05:00
mdipierro b17358e761 better gluon.tools.Expose, thanks Richard 2012-11-01 21:09:09 -05:00
mdipierro c9b41a4343 fixed issue 1132, unicode in IS_IN_DB validator 2012-11-01 21:07:47 -05:00
mdipierro 8affdbdc86 fixed issue 1134, gae dal delete, thanks Howesc 2012-11-01 21:01:46 -05:00
mdipierro a61e388498 fixed issue 1130, prevent exception for virtual fields in forms, thanks hi21alt 2012-10-31 11:43:11 -05:00
mdipierro d72752f453 scripts/extract_sqlite_models.py, thanks Michele 2012-10-31 10:23:56 -05:00
mdipierro d67af48f29 allows to customize the A in a MENU, thanks ilvalle 2012-10-31 10:22:20 -05:00
mdipierro b18a2a7aa3 fixed issue 1117, snitize of unicode, thanks Bill 2012-10-31 10:02:08 -05:00
mdipierro 693dce0e6c fixed issue 1127, SQLTABLE column with virtual fields, thanks hi21alt 2012-10-31 09:52:43 -05:00
mdipierro e1cd36771e fixed issue 1129, recapcha message error, thanks Friedrich 2012-10-31 09:50:37 -05:00
mdipierro 12107da9bd allow to pass hidden to crud.update 2012-10-31 09:14:58 -05:00
Massimo 96eee74f56 fixed sync languages, thanks Yair 2012-10-30 11:09:50 -05:00
Massimo 2f881085ef fixed validator recent typo 2012-10-30 09:42:03 -05:00
mdipierro 7b2afa109e reverted changes about formatting None 2012-10-29 22:25:19 -05:00
mdipierro 8dae3f832d gluon/contrib/login_methods/dropbox_account.py, get client 2012-10-29 22:22:36 -05:00
mdipierro c61e0e11bb page and media preview in wiki, thanks Niphlod 2012-10-29 21:38:09 -05:00
mdipierro 04caa5f4e4 moved toolbar logic to dal, thanks Niphlod 2012-10-29 18:13:58 -05:00
mdipierro 6a13c33c70 added informix to list, thanks Christopher 2012-10-29 18:11:52 -05:00
mdipierro 4357edb1d4 if user_group_name is None, user_group_role is also None 2012-10-29 14:00:29 -05:00
mdipierro 9d7e009c0f csv can return a generator, thanks Jonathan 2012-10-29 11:36:04 -05:00
mdipierro 7549f77edc validator.formatter checks None 2012-10-29 10:09:07 -05:00
mdipierro 5ee2ab9b6b fixed redirection after change password, issue 1112, thanks Friedrich 2012-10-29 09:31:51 -05:00
mdipierro 54b98b4e05 fixed issue 1118, reload page when called by component, thanks Paolo 2012-10-29 09:28:19 -05:00
mdipierro 6e0e48e150 fixed toolbar issue 1111, thanks niphlod 2012-10-29 09:06:52 -05:00
mdipierro fe5a1c6a8d fixed issue 1120, bug introduced in latest utils.py import. thanks Yair 2012-10-29 08:59:54 -05:00
mdipierro 8332106754 fixed issue 1121, appadmin interface to cache, thanks Paolo 2012-10-29 08:57:43 -05:00
mdipierro aa149d2e7b fixed bug in sessions2trach.py, issue 1111, thanks Szimszon 2012-10-29 08:53:50 -05:00
mdipierro a5f883c2f0 following Joe and Jonathan's advice, None value is formatted 2012-10-28 12:01:09 -05:00
mdipierro 5953377060 better utils.py, thanks Niphlod 2012-10-27 14:37:40 -05:00
mdipierro 5a478302f4 removed redundant assignment, thanks Niphlod 2012-10-26 15:51:17 -05:00
mdipierro 1621825166 fixed scheduler bug, thanks Niphlod 2012-10-26 15:49:47 -05:00
mdipierro 6af2e859ac fixed commit mistake, thanks Nico 2012-10-25 17:23:05 -05:00
mdipierro fb22a8843e fixed issue 1096, thanks Howesc 2012-10-25 10:23:50 -05:00
mdipierro 529dda0e6d fixed issue 1104, thanks Paolo Valleri 2012-10-25 10:19:50 -05:00
mdipierro 35c893d47a fixed issue 1109 2012-10-25 10:11:51 -05:00
mdipierro 99e2397981 fixed issue 1113, thanks Nico 2012-10-25 10:07:39 -05:00
mdipierro b6d68f97d6 fixed issue 1114, thanks Friedrich 2012-10-25 10:04:04 -05:00
mdipierro 74024301a5 operators in grid are not translated, thanks Friedrich Weber 2012-10-25 10:02:40 -05:00
mdipierro 1f100bbe88 better pep8 in ldap_auth.py, thanks Gyuris 2012-10-25 08:47:36 -05:00
mdipierro c94c192e17 wiki edit menu pages conditional to login 2012-10-25 08:22:34 -05:00
mdipierro 0d9e5985e4 better sessions2trash.py, thanks Jim 2012-10-25 08:17:30 -05:00
Massimo b31bfdaaf5 fixed missing sys in languages 2012-10-24 16:04:32 -05:00
mdipierro 5f67edbf87 dal almost runs with python 3.3 but fails a test on 2.5 2012-10-23 11:30:02 -05:00
mdipierro 093e8b356e dal compiles with python 3.3 2012-10-23 11:13:29 -05:00
mdipierro 43d4c2831d template compiles with python 3.0 2012-10-23 10:45:17 -05:00
mdipierro 55a0dbeb86 languages.py closer to python 3.0 support 2012-10-23 10:28:46 -05:00
mdipierro 2f1f2dccc1 utils compiles with python 3 2012-10-23 10:17:23 -05:00
mdipierro a4cef60c49 reverted changs to utils 2012-10-23 10:13:17 -05:00
mdipierro 96ee377279 utils compiles with python 3 2012-10-23 10:11:33 -05:00
mdipierro 4152c72de5 aes python 3 compiles (but does work well?) 2012-10-23 09:54:07 -05:00
mdipierro ab066397b2 aes new raise compliant 2012-10-23 09:44:34 -05:00
mdipierro 8c514df120 reverted previous change but still problems with concurency multiple dbs in different folders in same app 2012-10-22 22:52:40 -05:00
mdipierro 0eab35842d THREAD_LOCAL folder not reset in dal 2012-10-22 22:49:35 -05:00
mdipierro 752bb7e048 portable languages 2012-10-22 22:21:11 -05:00
mdipierro 9e897dcc46 language changes 2012-10-22 22:14:40 -05:00
mdipierro 2bb3485827 minor fix in dal for rare condition 2012-10-22 18:50:18 -05:00
mdipierro 0be4abe9c2 minor fix in dal for rare condition 2012-10-22 15:07:38 -05:00
mdipierro 37bc09169f R-2.2.1 2012-10-21 10:54:13 -05:00
mdipierro 1cc2decfdd assign_task takes better care for group_names, thanks Niphlod 2012-10-21 09:23:26 -05:00
mdipierro e9eb1689e2 fixed a problem with capitalization in wiki 2012-10-20 19:38:54 -05:00
mdipierro 0f446833c0 assign_task takes better care for group_names, thanks Niphlod 2012-10-20 15:27:13 -05:00
mdipierro cb9c2a8ef9 fixed issue 1102, thanks howesc 2012-10-20 10:12:04 -05:00
mdipierro b37ed1c1e0 fixed issue 1109, thanks Niphlod 2012-10-20 10:11:08 -05:00
mdipierro b484955005 fixed issue 1100, thanks sherdim 2012-10-20 10:08:58 -05:00
mdipierro 654626d519 removed print statements from scheduler, thanks Niphlod 2012-10-20 10:03:57 -05:00
mdipierro ca0313c514 back button in mobile admin demo 2012-10-19 18:43:14 -05:00
mdipierro fb357eb241 fixed problem with new importer and custom import 2012-10-19 18:36:39 -05:00
mdipierro 1a83487221 populate fix and pep8 2012-10-19 14:59:30 -05:00
mdipierro 6cda7a29fc pep8 in scripts/*.py 2012-10-19 14:22:42 -05:00
mdipierro 17f495e9c5 fixed pep8 in apps 2012-10-19 14:13:37 -05:00
mdipierro dd32a90844 upgraded feedparer and PyRSS2Gen 2012-10-19 12:59:58 -05:00
mdipierro 4b2ba185ae many pep8 improvements 2012-10-19 12:33:53 -05:00
mdipierro b716df1a05 some pep8 changes (fixed spacing at end) 2012-10-19 10:37:07 -05:00
mdipierro d552eb2eeb fixed some pep8 stuff 2012-10-19 09:40:17 -05:00
mdipierro de2337dfe3 scheduler.queue_task, thank Niphlod 2012-10-18 18:20:51 -05:00
mdipierro e707cfc67c codemirror autoresize 2012-10-18 13:42:49 -05:00
mdipierro c3c5df6394 scheduler.queue_task(...), thanks Niphlod 2012-10-18 13:02:19 -05:00
mdipierro 72739ebb97 better openshift error 2012-10-17 17:00:50 -05:00
mdipierro 39c94b8dcf faster scheduler, thanks Niphlod 2012-10-17 16:01:29 -05:00
mdipierro 5af380223a remove excessive session saving with caching of mobile_agent 2012-10-17 14:33:52 -05:00
mdipierro 1ea379180a fixed appadmin bug and excessive session saving 2012-10-17 14:30:02 -05:00
mdipierro ca3d050a0b fixed problem with session in cookie, thanks Niphlod 2012-10-17 12:04:19 -05:00
mdipierro 161b2271b3 T.is_writable, thanks Fran 2012-10-17 09:13:48 -05:00
Massimo 013c94cdf6 inlined sluggify 2012-10-16 11:47:16 -05:00
Massimo addbb78151 customizable session cookie expriration 2012-10-16 11:23:41 -05:00
Massimo f6789eaf39 session cookie data no expires by default 2012-10-16 11:14:52 -05:00
Massimo c13b4f18f7 fixed auth.impersonating again, thanks Ricardo 2012-10-16 11:08:42 -05:00
Massimo 67840e9481 current.T.is_writable=False no languages write, thanks Fran 2012-10-16 10:54:33 -05:00
Massimo 41c40974a3 fixed issue 1092, thanks nicozanf 2012-10-16 10:34:36 -05:00
Massimo 9a6ce11f09 users can switch between sessions storage types 2012-10-16 10:25:28 -05:00
mdipierro d404e40508 improved session data in cookie 2012-10-16 07:44:22 -05:00
mdipierro b6a496aae5 improved session data in cookie 2012-10-16 07:10:33 -05:00
mdipierro ecaed07a3d fixed bug with auth.impersonate(0) 2012-10-16 06:19:39 -05:00
mdipierro 30ec8e645b sessions in secure cookies, session.connect(cookie_key='mypassword') 2012-10-16 06:15:45 -05:00
mdipierro 3a1ba53a4b reverting some test but session.__hash needs work 2012-10-15 21:49:43 -05:00
mdipierro ab95dfa7cd fixed problem with session __hash 2012-10-15 20:43:51 -05:00
mdipierro 6b9ebb6dc5 fixed issue with storing Row in session 2012-10-15 19:39:25 -05:00
mdipierro e2e843d2ed more languages patches, thanks Vladyslav 2012-10-15 16:28:51 -05:00
mdipierro d5381d7b36 fixed make pip 2012-10-15 14:48:45 -05:00
mdipierro f7c0f0341b who page 2012-10-15 14:44:04 -05:00
mdipierro 9f7fd68728 better markmin with links in links, thanks Vladyslav 2012-10-15 07:43:23 -05:00
236 changed files with 12144 additions and 8192 deletions

No files matched your search

+37
View File
@@ -1,3 +1,40 @@
## 2.3.1 - 2.3.2
- new virtual fields syntax:
``db.define_table('person',Field('name'),Field.Virtual('namey',lambda row: row.person.name+'y'))``
- db.thing(name='Cohen',_orderby=db.thing.name), thanks Yair
- made many modules Python 3.3 friendly (compile but not tested)
- better welcome css, thanks Paolo
- jQuery 1.8.3
- Bootstrap 2.2.2
- Modernizr 2.6.2 (custom full options)
- integration with analyitics.js (0.2.0)
- better scheduler, thanks Niphlod
- page and media preview in wiki, thanks Niphlod
- create new auth.wiki page from slug model, thanks Nico
- conditional menus with auth.wiki(menugroups=['wiki_editor'])
- better security in grid/smartgrid
- allow LOADing multiple grids, thanks Niphlod
- auth.settings.login_onfail, thanks Yair
- better handling of session files for speed
- added heroku support (experimental)
- added rocket support for IPV6, thanks Chirs Winebrinner
- more customizable menus with MENU(li_first, li_last..)
- added support for paymentech (gluon/contrib/paymentech.py)
- fixed broken cron
- fixed possible xss with share.js
- many bug fixes. Closed more than 50 tickets since 2.2.1
## 2.2.1
- session.connect(cookie_key='secret', compression_level=9) stores sessions in cookies
- T.is_writable = False prevents T from dynamically updating langauge files
- all code is more PEP8 compliant
- better custom_importer behaviour (now works per app, is smalled and faster)
- fixed some bugs
- upgraded feedparser.py and rss2.py
- codemirror has autoresize
## 2.1.0
- overall faster web2py
+5 -4
View File
@@ -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.1.1 ('`date +%Y-%m-%d\ %H:%M:%S`') stable' > VERSION
echo 'Version 2.3.2 ('`date +%Y-%m-%d\ %H:%M:%S`') stable' > VERSION
### rm -f all junk files
make clean
### clean up baisc apps
@@ -43,6 +43,8 @@ src:
rm -f applications/admin/uploads/*
rm -f applications/welcome/uploads/*
rm -f applications/examples/uploads/*
### make epydoc
make epydoc
### make welcome layout and appadmin the default
cp applications/welcome/views/appadmin.html applications/admin/views
cp applications/welcome/views/appadmin.html applications/examples/views
@@ -54,7 +56,6 @@ src:
cd ..; zip -r web2py/web2py_src.zip web2py/gluon/*.py web2py/gluon/contrib/* web2py/splashlogo.gif web2py/*.py web2py/README.markdown web2py/LICENSE web2py/CHANGELOG web2py/NEWINSTALL web2py/VERSION web2py/Makefile web2py/epydoc.css web2py/epydoc.conf web2py/app.example.yaml web2py/logging.example.conf web2py_exe.conf web2py/queue.example.yaml MANIFEST.in w2p_apps w2p_clone w2p_run startweb2py web2py/scripts/*.sh web2py/scripts/*.py web2py/applications/admin web2py/applications/examples/ web2py/applications/welcome web2py/applications/__init__.py web2py/site-packages/__init__.py web2py/gluon/tests/*.sh web2py/gluon/tests/*.py
mdp:
make epydoc
make src
make app
make win
@@ -130,5 +131,5 @@ pip:
# after upload clean Web2py sources with rm -R ./dist
# http://guide.python-distribute.org/creation.html
python setup.py sdist
python setup.py register
python setup.py sdist upload
sudo python setup.py register
sudo python setup.py sdist upload
+1
View File
@@ -0,0 +1 @@
+1 -1
View File
@@ -1 +1 @@
Version 2.1.1 (2012-10-15 06:40:52) stable
Version 2.3.2 (2012-12-17 08:59:58) stable
-10
View File
@@ -1,10 +0,0 @@
+68 -49
View File
@@ -9,13 +9,18 @@ License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
This file is based, although a rewrite, on MIT-licensed code from the Bottle web framework.
"""
import os, sys, optparse, urllib
import os
import sys
import optparse
import urllib
path = os.path.dirname(os.path.abspath(__file__))
os.chdir(path)
sys.path = [path]+[p for p in sys.path if not p==path]
sys.path = [path] + [p for p in sys.path if not p == path]
import gluon.main
from gluon.fileutils import read_file, write_file
class Servers:
@staticmethod
def cgi(app, address=None, **options):
@@ -23,33 +28,35 @@ class Servers:
CGIHandler().run(app) # Just ignore host and port here
@staticmethod
def flup(app,address, **options):
def flup(app, address, **options):
import flup.server.fcgi
flup.server.fcgi.WSGIServer(app, bindAddress=address).run()
@staticmethod
def wsgiref(app,address,**options): # pragma: no cover
def wsgiref(app, address, **options): # pragma: no cover
from wsgiref.simple_server import make_server, WSGIRequestHandler
class QuietHandler(WSGIRequestHandler):
def log_request(*args, **kw): pass
def log_request(*args, **kw):
pass
options['handler_class'] = QuietHandler
srv = make_server(address[0],address[1],app,**options)
srv = make_server(address[0], address[1], app, **options)
srv.serve_forever()
@staticmethod
def cherrypy(app,address, **options):
def cherrypy(app, address, **options):
from cherrypy import wsgiserver
server = wsgiserver.CherryPyWSGIServer(address, app)
server.start()
@staticmethod
def rocket(app,address, **options):
def rocket(app, address, **options):
from gluon.rocket import CherryPyWSGIServer
server = CherryPyWSGIServer(address, app)
server.start()
@staticmethod
def rocket_with_repoze_profiler(app,address, **options):
def rocket_with_repoze_profiler(app, address, **options):
from gluon.rocket import CherryPyWSGIServer
from repoze.profile.profiler import AccumulatingProfileMiddleware
from gluon.settings import global_settings
@@ -59,44 +66,46 @@ class Servers:
log_filename='wsgi.prof',
discard_first_request=True,
flush_at_shutdown=True,
path = '/__profile__'
path='/__profile__'
)
server = CherryPyWSGIServer(address, wrapped)
server.start()
@staticmethod
def paste(app,address,**options):
def paste(app, address, **options):
from paste import httpserver
from paste.translogger import TransLogger
httpserver.serve(app, host=address[0], port=address[1], **options)
@staticmethod
def fapws(app,address, **options):
def fapws(app, address, **options):
import fapws._evwsgi as evwsgi
from fapws import base
evwsgi.start(address[0],str(address[1]))
evwsgi.start(address[0], str(address[1]))
evwsgi.set_base_module(base)
def app(environ, start_response):
environ['wsgi.multiprocess'] = False
return app(environ, start_response)
evwsgi.wsgi_cb(('',app))
evwsgi.wsgi_cb(('', app))
evwsgi.run()
@staticmethod
def gevent(app,address, **options):
from gevent import monkey; monkey.patch_all()
def gevent(app, address, **options):
from gevent import monkey
monkey.patch_all()
from gevent import pywsgi
from gevent.pool import Pool
pywsgi.WSGIServer(address, app, spawn = 'workers' in options and Pool(int(options.workers)) or 'default').serve_forever()
pywsgi.WSGIServer(address, app, spawn='workers' in options and Pool(
int(options.workers)) or 'default').serve_forever()
@staticmethod
def bjoern(app,address, **options):
def bjoern(app, address, **options):
import bjoern
bjoern.run(app, *address)
@staticmethod
def tornado(app,address, **options):
def tornado(app, address, **options):
import tornado.wsgi
import tornado.httpserver
import tornado.ioloop
@@ -106,7 +115,7 @@ class Servers:
tornado.ioloop.IOLoop.instance().start()
@staticmethod
def twisted(app,address, **options):
def twisted(app, address, **options):
from twisted.web import server, wsgi
from twisted.python.threadpool import ThreadPool
from twisted.internet import reactor
@@ -118,42 +127,44 @@ class Servers:
reactor.run()
@staticmethod
def diesel(app,address, **options):
def diesel(app, address, **options):
from diesel.protocols.wsgi import WSGIApplication
app = WSGIApplication(app, port=address[1])
app.run()
@staticmethod
def gunicorn(app,address, **options):
def gunicorn(app, address, **options):
from gunicorn.app.base import Application
config = {'bind': "%s:%d" % address}
config.update(options)
sys.argv = ['anyserver.py']
class GunicornApplication(Application):
def init(self, parser, opts, args):
return config
def load(self):
return app
g = GunicornApplication()
g.run()
@staticmethod
def eventlet(app,address, **options):
def eventlet(app, address, **options):
from eventlet import wsgi, listen
wsgi.server(listen(address), app)
@staticmethod
def mongrel2(app,address,**options):
def mongrel2(app, address, **options):
import uuid
sys.path.append(os.path.abspath(os.path.dirname(__file__)))
from mongrel2 import handler
conn = handler.Connection(str(uuid.uuid4()),
"tcp://127.0.0.1:9997",
"tcp://127.0.0.1:9996")
mongrel2_handler(app,conn,debug=False)
mongrel2_handler(app, conn, debug=False)
def run(servername,ip,port,softcron=True,logging=False,profiler=None):
def run(servername, ip, port, softcron=True, logging=False, profiler=None):
if logging:
application = gluon.main.appfactory(wsgiapp=gluon.main.wsgibase,
logfilename='httpserver.log',
@@ -163,9 +174,10 @@ def run(servername,ip,port,softcron=True,logging=False,profiler=None):
if softcron:
from gluon.settings import global_settings
global_settings.web2py_crontype = 'soft'
getattr(Servers,servername)(application,(ip,int(port)))
getattr(Servers, servername)(application, (ip, int(port)))
def mongrel2_handler(application,conn,debug=False):
def mongrel2_handler(application, conn, debug=False):
"""
Based on :
https://github.com/berry/Mongrel2-WSGI-Handler/blob/master/wsgi-handler.py
@@ -190,15 +202,18 @@ def mongrel2_handler(application,conn,debug=False):
# and responses. Unless I have missed something.
while True:
if debug: print "WAITING FOR REQUEST"
if debug:
print "WAITING FOR REQUEST"
# receive a request
req = conn.recv()
if debug: print "REQUEST BODY: %r\n" % req.body
if debug:
print "REQUEST BODY: %r\n" % req.body
if req.is_disconnect():
if debug: print "DISCONNECT"
continue #effectively ignore the disconnect from the client
if debug:
print "DISCONNECT"
continue # effectively ignore the disconnect from the client
# Set a couple of environment attributes a.k.a. header attributes
# that are a must according to PEP 333
@@ -217,11 +232,13 @@ def mongrel2_handler(application,conn,debug=False):
environ['QUERY_STRING'] = environ['URI'].split('?')[1]
else:
environ['QUERY_STRING'] = ''
if environ.has_key('Content-Length'):
environ['CONTENT_LENGTH'] = environ['Content-Length'] # necessary for POST to work with Django
if 'Content-Length' in environ:
environ['CONTENT_LENGTH'] = environ[
'Content-Length'] # necessary for POST to work with Django
environ['wsgi.input'] = req.body
if debug: print "ENVIRON: %r\n" % environ
if debug:
print "ENVIRON: %r\n" % environ
# SimpleHandler needs file-like stream objects for
# requests, errors and responses
@@ -230,7 +247,8 @@ def mongrel2_handler(application,conn,debug=False):
respIO = StringIO.StringIO()
# execute the application
handler = SimpleHandler(reqIO, respIO, errIO, environ, multithread = False, multiprocess = False)
handler = SimpleHandler(reqIO, respIO, errIO, environ,
multithread=False, multiprocess=False)
handler.run(application)
# Get the response and filter out the response (=data) itself,
@@ -254,11 +272,15 @@ def mongrel2_handler(application,conn,debug=False):
errors = errIO.getvalue()
# return the response
if debug: print "RESPONSE: %r\n" % response
if debug:
print "RESPONSE: %r\n" % response
if errors:
if debug: print "ERRORS: %r" % errors
if debug:
print "ERRORS: %r" % errors
data = "%s\r\n\r\n%s" % (data, errors)
conn.reply_http(req, data, code = code, status = status, headers = headers)
conn.reply_http(
req, data, code=code, status=status, headers=headers)
def main():
usage = "python anyserver.py -s tornado -i 127.0.0.1 -p 8000 -l -P"
@@ -278,7 +300,7 @@ def main():
default=False,
dest='profiler',
help='profiler filename')
servers = ', '.join(x for x in dir(Servers) if not x[0]=='_')
servers = ', '.join(x for x in dir(Servers) if not x[0] == '_')
parser.add_option('-s',
'--server',
default='rocket',
@@ -300,13 +322,10 @@ def main():
dest='workers',
help='number of workers number')
(options, args) = parser.parse_args()
print 'starting %s on %s:%s...' % (options.server,options.ip,options.port)
run(options.server,options.ip,options.port,logging=options.logging,profiler=options.profiler)
print 'starting %s on %s:%s...' % (
options.server, options.ip, options.port)
run(options.server, options.ip, options.port,
logging=options.logging, profiler=options.profiler)
if __name__=='__main__':
if __name__ == '__main__':
main()
@@ -2,8 +2,3 @@ def webapp_add_wsgi_middleware(app):
from google.appengine.ext.appstats import recording
app = recording.appstats_wsgi_middleware(app)
return app
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+62 -45
View File
@@ -23,7 +23,7 @@ remote_addr = request.env.remote_addr
try:
hosts = (http_host, socket.gethostname(),
socket.gethostbyname(http_host),
'::1','127.0.0.1','::ffff:127.0.0.1')
'::1', '127.0.0.1', '::ffff:127.0.0.1')
except:
hosts = (http_host, )
@@ -32,10 +32,10 @@ if request.env.http_x_forwarded_for or request.is_https:
elif (remote_addr not in hosts) and (remote_addr != "127.0.0.1"):
raise HTTP(200, T('appadmin is disabled because insecure channel'))
if (request.application=='admin' and not session.authorized) or \
(request.application!='admin' and not gluon.fileutils.check_credentials(request)):
if (request.application == 'admin' and not session.authorized) or \
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
redirect(URL('admin', 'default', 'index',
vars=dict(send=URL(args=request.args,vars=request.vars))))
vars=dict(send=URL(args=request.args, vars=request.vars))))
ignore_rw = True
response.view = 'appadmin.html'
@@ -95,24 +95,23 @@ def get_query(request):
return None
def query_by_table_type(tablename,db,request=request):
keyed = hasattr(db[tablename],'_primarykey')
def query_by_table_type(tablename, db, request=request):
keyed = hasattr(db[tablename], '_primarykey')
if keyed:
firstkey = db[tablename][db[tablename]._primarykey[0]]
cond = '>0'
if firstkey.type in ['string', 'text']:
cond = '!=""'
qry = '%s.%s.%s%s' % (request.args[0], request.args[1], firstkey.name, cond)
qry = '%s.%s.%s%s' % (
request.args[0], request.args[1], firstkey.name, cond)
else:
qry = '%s.%s.id>0' % tuple(request.args[:2])
return qry
# ##########################################################
# ## list all databases and tables
# ###########################################################
def index():
return dict(databases=databases)
@@ -127,7 +126,7 @@ def insert():
form = SQLFORM(db[table], ignore_rw=ignore_rw)
if form.accepts(request.vars, session):
response.flash = T('new record inserted')
return dict(form=form,table=db[table])
return dict(form=form, table=db[table])
# ##########################################################
@@ -138,7 +137,8 @@ def insert():
def download():
import os
db = get_database(request)
return response.download(request,db)
return response.download(request, db)
def csv():
import gluon.contenttype
@@ -150,18 +150,19 @@ def csv():
return None
response.headers['Content-disposition'] = 'attachment; filename=%s_%s.csv'\
% tuple(request.vars.query.split('.')[:2])
return str(db(query,ignore_common_filters=True).select())
return str(db(query, ignore_common_filters=True).select())
def import_csv(table, file):
table.import_from_csv_file(file)
def select():
import re
db = get_database(request)
dbname = request.args[0]
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
if len(request.args)>1 and hasattr(db[request.args[1]],'_primarykey'):
if len(request.args) > 1 and hasattr(db[request.args[1]], '_primarykey'):
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>.+)')
if request.vars.query:
match = regex.match(request.vars.query)
@@ -192,21 +193,23 @@ def select():
session.last_query = request.vars.query
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
_name='query', _value=request.vars.query or '',
requires=IS_NOT_EMPTY(error_message=T("Cannot be empty")))), TR(T('Update:'),
requires=IS_NOT_EMPTY(
error_message=T("Cannot be empty")))), TR(T('Update:'),
INPUT(_name='update_check', _type='checkbox',
value=False), INPUT(_style='width:400px',
_name='update_fields', _value=request.vars.update_fields
or '')), TR(T('Delete:'), INPUT(_name='delete_check',
_class='delete', _type='checkbox', value=False), ''),
TR('', '', INPUT(_type='submit', _value=T('submit')))),
_action=URL(r=request,args=request.args))
_action=URL(r=request, args=request.args))
tb = None
if form.accepts(request.vars, formname=None):
regex = re.compile(request.args[0] + '\.(?P<table>\w+)\..+')
match = regex.match(form.vars.query.strip())
if match:
table = match.group('table')
try:
tb = None
nrows = db(query).count()
if form.vars.update_check and form.vars.update_fields:
db(query).update(**eval_in_global_env('dict(%s)'
@@ -217,21 +220,23 @@ def select():
response.flash = T('%s %%{row} deleted', nrows)
nrows = db(query).count()
if orderby:
rows = db(query,ignore_common_filters=True).select(limitby=(start, stop), orderby=eval_in_global_env(orderby))
rows = db(query, ignore_common_filters=True).select(limitby=(
start, stop), orderby=eval_in_global_env(orderby))
else:
rows = db(query,ignore_common_filters=True).select(limitby=(start, stop))
rows = db(query, ignore_common_filters=True).select(
limitby=(start, stop))
except Exception, e:
import traceback
tb = traceback.format_exc()
(rows, nrows) = ([], 0)
response.flash = DIV(T('Invalid Query'),PRE(str(e)))
response.flash = DIV(T('Invalid Query'), PRE(str(e)))
# begin handle upload csv
csv_table = table or request.vars.table
if csv_table:
formcsv = FORM(str(T('or import from csv file'))+" ",
INPUT(_type='file',_name='csvfile'),
INPUT(_type='hidden',_value=csv_table,_name='table'),
INPUT(_type='submit',_value=T('import')))
formcsv = FORM(str(T('or import from csv file')) + " ",
INPUT(_type='file', _name='csvfile'),
INPUT(_type='hidden', _value=csv_table, _name='table'),
INPUT(_type='submit', _value=T('import')))
else:
formcsv = None
if formcsv and formcsv.process().accepted:
@@ -240,7 +245,7 @@ def select():
request.vars.csvfile.file)
response.flash = T('data uploaded')
except Exception, e:
response.flash = DIV(T('unable to parse csv file'),PRE(str(e)))
response.flash = DIV(T('unable to parse csv file'), PRE(str(e)))
# end handle upload csv
return dict(
@@ -251,8 +256,8 @@ def select():
nrows=nrows,
rows=rows,
query=request.vars.query,
formcsv = formcsv,
tb = tb,
formcsv=formcsv,
tb=tb,
)
@@ -263,14 +268,16 @@ def select():
def update():
(db, table) = get_table(request)
keyed = hasattr(db[table],'_primarykey')
keyed = hasattr(db[table], '_primarykey')
record = None
if keyed:
key = [f for f in request.vars if f in db[table]._primarykey]
if key:
record = db(db[table][key[0]] == request.vars[key[0]], ignore_common_filters=True).select().first()
record = db(db[table][key[0]] == request.vars[key[
0]], ignore_common_filters=True).select().first()
else:
record = db(db[table].id == request.args(2),ignore_common_filters=True).select().first()
record = db(db[table].id == request.args(
2), ignore_common_filters=True).select().first()
if not record:
qry = query_by_table_type(table, db)
@@ -280,9 +287,10 @@ def update():
if keyed:
for k in db[table]._primarykey:
db[table][k].writable=False
db[table][k].writable = False
form = SQLFORM(db[table], record, deletable=True, delete_label=T('Check to delete'),
form = SQLFORM(
db[table], record, deletable=True, delete_label=T('Check to delete'),
ignore_rw=ignore_rw and not keyed,
linkto=URL('select',
args=request.args[:1]), upload=URL(r=request,
@@ -293,7 +301,7 @@ def update():
qry = query_by_table_type(table, db)
redirect(URL('select', args=request.args[:1],
vars=dict(query=qry)))
return dict(form=form,table=db[table])
return dict(form=form, table=db[table])
# ##########################################################
@@ -304,11 +312,15 @@ def update():
def state():
return dict()
def ccache():
form = FORM(
P(TAG.BUTTON(T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")),
P(TAG.BUTTON(T("Clear RAM"), _type="submit", _name="ram", _value="ram")),
P(TAG.BUTTON(T("Clear DISK"), _type="submit", _name="disk", _value="disk")),
P(TAG.BUTTON(
T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")),
P(TAG.BUTTON(
T("Clear RAM"), _type="submit", _name="ram", _value="ram")),
P(TAG.BUTTON(
T("Clear DISK"), _type="submit", _name="disk", _value="disk")),
)
if form.accepts(request.vars, session):
@@ -332,11 +344,16 @@ def ccache():
redirect(URL(r=request))
try:
from guppy import hpy; hp=hpy()
from guppy import hpy
hp = hpy()
except ImportError:
hp = False
import shelve, os, copy, time, math
import shelve
import os
import copy
import time
import math
from gluon import portalocker
ram = {
@@ -379,11 +396,13 @@ def ccache():
if value[0] < ram['oldest']:
ram['oldest'] = value[0]
ram['keys'].append((key, GetInHMS(time.time() - value[0])))
locker = open(os.path.join(request.folder,
'cache/cache.lock'), 'a')
folder = os.path.join(request.folder,'cache')
if not os.path.exists(folder):
os.mkdir(folder)
locker = open(os.path.join(folder, 'cache.lock'), 'a')
portalocker.lock(locker, portalocker.LOCK_EX)
disk_storage = shelve.open(os.path.join(request.folder, 'cache/cache.shelve'))
disk_storage = shelve.open(
os.path.join(folder, 'cache.shelve'))
try:
for key, value in disk_storage.items():
if isinstance(value, dict):
@@ -414,7 +433,8 @@ def ccache():
total['misses'] = ram['misses'] + disk['misses']
total['keys'] = ram['keys'] + disk['keys']
try:
total['ratio'] = total['hits'] * 100 / (total['hits'] + total['misses'])
total['ratio'] = total['hits'] * 100 / (total['hits'] +
total['misses'])
except (KeyError, ZeroDivisionError):
total['ratio'] = 0
@@ -440,6 +460,3 @@ def ccache():
return dict(form=form, total=total,
ram=ram, disk=disk, object_stats=hp != False)
+24 -11
View File
@@ -5,35 +5,39 @@ import gluon.contrib.shell
import gluon.dal
import gluon.html
import gluon.validators
import code, thread
import code
import thread
from gluon.debug import communicate, web_debugger, qdb_debugger
import pydoc
if DEMO_MODE or MULTI_USER_MODE:
session.flash = T('disabled in demo mode')
redirect(URL('default','site'))
redirect(URL('default', 'site'))
FE = 10 ** 9
FE=10**9
def index():
app = request.args(0) or 'admin'
reset()
# read buffer
data = communicate()
return dict(app=app,data=data)
return dict(app=app, data=data)
def callback():
app = request.args[0]
command = request.vars.statement
session['debug_commands:'+app].append(command)
session['debug_commands:' + app].append(command)
output = communicate(command)
k = len(session['debug_commands:'+app]) - 1
k = len(session['debug_commands:' + app]) - 1
return '[%i] %s%s\n' % (k + 1, command, output)
def reset():
app = request.args(0) or 'admin'
session['debug_commands:'+app] = []
session['debug_commands:' + app] = []
return 'done'
@@ -50,7 +54,7 @@ def interact():
filename = web_debugger.filename
lineno = web_debugger.lineno
if filename:
lines = dict([(i+1, l) for (i, l) in enumerate(
lines = dict([(i + 1, l) for (i, l) in enumerate(
[l.strip("\n").strip("\r") for l
in open(filename).readlines()])])
filename = os.path.basename(filename)
@@ -81,37 +85,43 @@ def interact():
f_globals=f_globals, f_locals=f_locals,
exception=web_debugger.exception_info)
def step():
web_debugger.do_step()
redirect(URL("interact"))
def next():
web_debugger.do_next()
redirect(URL("interact"))
def cont():
web_debugger.do_continue()
redirect(URL("interact"))
def ret():
web_debugger.do_return()
redirect(URL("interact"))
def stop():
web_debugger.do_quit()
redirect(URL("interact"))
def execute():
app = request.args[0]
command = request.vars.statement
session['debug_commands:'+app].append(command)
session['debug_commands:' + app].append(command)
try:
output = web_debugger.do_exec(command)
if output is None:
output = ""
except Exception, e:
output = T("Exception %s") % str(e)
k = len(session['debug_commands:'+app]) - 1
k = len(session['debug_commands:' + app]) - 1
return '[%i] %s%s\n' % (k + 1, command, output)
@@ -166,6 +176,8 @@ def toggle_breakpoint():
try:
filename = os.path.join(request.env['applications_parent'],
'applications', request.vars.filename)
# normalize path name: replace slashes, references, etc...
filename = os.path.normpath(os.path.normcase(filename))
if not request.vars.data:
# ace send us the line number!
lineno = int(request.vars.sel_start) + 1
@@ -182,6 +194,8 @@ def toggle_breakpoint():
if lineno is not None:
for bp in qdb_debugger.do_list_breakpoint():
no, bp_filename, bp_lineno, temporary, enabled, hits, cond = bp
# normalize path name: replace slashes, references, etc...
bp_filename = os.path.normpath(os.path.normcase(bp_filename))
if filename == bp_filename and lineno == bp_lineno:
err = qdb_debugger.do_clear_breakpoint(filename, lineno)
response.flash = T("Removed Breakpoint on %s at line %s", (
@@ -198,4 +212,3 @@ def toggle_breakpoint():
except Exception, e:
session.flash = str(e)
return response.json({'ok': ok, 'lineno': lineno})
File diff suppressed because it is too large. Load diff
+40 -33
View File
@@ -9,85 +9,92 @@ try:
import shutil
from gluon.fileutils import read_file, write_file
except:
session.flash='sorry, only on Unix systems'
redirect(URL(request.application,'default','site'))
session.flash = 'sorry, only on Unix systems'
redirect(URL(request.application, 'default', 'site'))
if MULTI_USER_MODE and not is_manager():
session.flash = 'Not Authorized'
redirect(URL('default','site'))
redirect(URL('default', 'site'))
forever = 10 ** 8
forever=10**8
def kill():
p = cache.ram('gae_upload',lambda:None,forever)
if not p or p.poll()!=None:
p = cache.ram('gae_upload', lambda: None, forever)
if not p or p.poll() is not None:
return 'oops'
os.kill(p.pid, signal.SIGKILL)
cache.ram('gae_upload',lambda:None,-1)
cache.ram('gae_upload', lambda: None, -1)
class EXISTS(object):
def __init__(self, error_message='file not found'):
self.error_message = error_message
def __call__(self, value):
if os.path.exists(value):
return (value,None)
return (value,self.error_message)
return (value, None)
return (value, self.error_message)
def deploy():
regex = re.compile('^\w+$')
apps = sorted(file for file in os.listdir(apath(r=request)) if regex.match(file))
apps = sorted(
file for file in os.listdir(apath(r=request)) if regex.match(file))
form = SQLFORM.factory(
Field('appcfg',default=GAE_APPCFG,label=T('Path to appcfg.py'),
Field('appcfg', default=GAE_APPCFG, label=T('Path to appcfg.py'),
requires=EXISTS(error_message=T('file not found'))),
Field('google_application_id',requires=IS_MATCH('[\w\-]+'),label=T('Google Application Id')),
Field('applications','list:string',
requires=IS_IN_SET(apps,multiple=True),
Field('google_application_id', requires=IS_MATCH(
'[\w\-]+'), label=T('Google Application Id')),
Field('applications', 'list:string',
requires=IS_IN_SET(apps, multiple=True),
label=T('web2py apps to deploy')),
Field('email',requires=IS_EMAIL(),label=T('GAE Email')),
Field('password','password',requires=IS_NOT_EMPTY(),label=T('GAE Password')))
cmd = output = errors= ""
if form.accepts(request,session):
Field('email', requires=IS_EMAIL(), label=T('GAE Email')),
Field('password', 'password', requires=IS_NOT_EMPTY(), label=T('GAE Password')))
cmd = output = errors = ""
if form.accepts(request, session):
try:
kill()
except:
pass
ignore_apps = [item for item in apps \
ignore_apps = [item for item in apps
if not item in form.vars.applications]
regex = re.compile('\(applications/\(.*')
yaml = apath('../app.yaml', r=request)
if not os.path.exists(yaml):
example = apath('../app.example.yaml', r=request)
shutil.copyfile(example,yaml)
shutil.copyfile(example, yaml)
data = read_file(yaml)
data = re.sub('application:.*','application: %s' % form.vars.google_application_id,data)
data = regex.sub('(applications/(%s)/.*)|' % '|'.join(ignore_apps),data)
data = re.sub('application:.*', 'application: %s' %
form.vars.google_application_id, data)
data = regex.sub(
'(applications/(%s)/.*)|' % '|'.join(ignore_apps), data)
write_file(yaml, data)
path = request.env.applications_parent
cmd = '%s --email=%s --passin update %s' % \
(form.vars.appcfg, form.vars.email, path)
p = cache.ram('gae_upload',
lambda s=subprocess,c=cmd:s.Popen(c, shell=True,
lambda s=subprocess, c=cmd: s.Popen(c, shell=True,
stdin=s.PIPE,
stdout=s.PIPE,
stderr=s.PIPE, close_fds=True),-1)
p.stdin.write(form.vars.password+'\n')
stderr=s.PIPE, close_fds=True), -1)
p.stdin.write(form.vars.password + '\n')
fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
fcntl.fcntl(p.stderr.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
return dict(form=form,command=cmd)
return dict(form=form, command=cmd)
def callback():
p = cache.ram('gae_upload',lambda:None,forever)
if not p or p.poll()!=None:
p = cache.ram('gae_upload', lambda: None, forever)
if not p or p.poll() is not None:
return '<done/>'
try:
output = p.stdout.read()
except:
output=''
output = ''
try:
errors = p.stderr.read()
except:
errors=''
return (output+errors).replace('\n','<br/>')
errors = ''
return (output + errors).replace('\n', '<br/>')
+17 -16
View File
@@ -2,10 +2,10 @@ from gluon.fileutils import read_file, write_file
if DEMO_MODE or MULTI_USER_MODE:
session.flash = T('disabled in demo mode')
redirect(URL('default','site'))
redirect(URL('default', 'site'))
if not have_mercurial:
session.flash=T("Sorry, could not find mercurial installed")
redirect(URL('default','design',args=request.args(0)))
session.flash = T("Sorry, could not find mercurial installed")
redirect(URL('default', 'design', args=request.args(0)))
_hgignore_content = """\
syntax: glob
@@ -22,6 +22,7 @@ sessions/*
errors/*
"""
def hg_repo(path):
import os
uio = ui.ui()
@@ -37,13 +38,14 @@ def hg_repo(path):
write_file(hgignore, _hgignore_content)
return repo
def commit():
app = request.args(0)
path = apath(app, r=request)
repo = hg_repo(path)
form = FORM('Comment:',INPUT(_name='comment',requires=IS_NOT_EMPTY()),
INPUT(_type='submit',_value=T('Commit')))
if form.accepts(request.vars,session):
form = FORM('Comment:', INPUT(_name='comment', requires=IS_NOT_EMPTY()),
INPUT(_type='submit', _value=T('Commit')))
if form.accepts(request.vars, session):
oldid = repo[repo.lookup('.')]
addremove(repo)
repo.commit(text=form.vars.comment)
@@ -51,34 +53,33 @@ def commit():
response.flash = 'no changes'
try:
files = TABLE(*[TR(file) for file in repo[repo.lookup('.')].files()])
changes = TABLE(TR(TH('revision'),TH('description')))
changes = TABLE(TR(TH('revision'), TH('description')))
for change in repo.changelog:
ctx=repo.changectx(change)
ctx = repo.changectx(change)
revision, description = ctx.rev(), ctx.description()
changes.append(TR(A(revision,_href=URL('revision',
args=(app,revision))),
changes.append(TR(A(revision, _href=URL('revision',
args=(app, revision))),
description))
except:
files = []
changes = []
return dict(form=form,files=files,changes=changes,repo=repo)
return dict(form=form, files=files, changes=changes, repo=repo)
def revision():
app = request.args(0)
path = apath(app, r=request)
repo = hg_repo(path)
revision = request.args(1)
ctx=repo.changectx(revision)
form=FORM(INPUT(_type='submit',_value=T('Revert')))
ctx = repo.changectx(revision)
form = FORM(INPUT(_type='submit', _value=T('Revert')))
if form.accepts(request.vars):
hg.update(repo, revision)
session.flash = "reverted to revision %s" % ctx.rev()
redirect(URL('default','design',args=app))
redirect(URL('default', 'design', args=app))
return dict(
files=ctx.files(),
rev=str(ctx.rev()),
desc=ctx.description(),
form=form
)
+25 -16
View File
@@ -1,29 +1,36 @@
import os
from distutils import dir_util
try:
from distutils import dir_util
except ImportError:
session.flash = T('requires distutils, but not installed')
redirect(URL('default', 'site'))
try:
from git import *
except ImportError:
session.flash = T('requires python-git, but not installed')
redirect(URL('default','site'))
redirect(URL('default', 'site'))
def deploy():
apps = sorted(file for file in os.listdir(apath(r=request)))
form = SQLFORM.factory(
Field('osrepo',default='/tmp',label=T('Path to local openshift repo root.'),
Field(
'osrepo', default='/tmp', label=T('Path to local openshift repo root.'),
requires=EXISTS(error_message=T('directory not found'))),
Field('osname',default='web2py',label=T('WSGI reference name')),
Field('applications','list:string',
requires=IS_IN_SET(apps,multiple=True),
Field('osname', default='web2py', label=T('WSGI reference name')),
Field('applications', 'list:string',
requires=IS_IN_SET(apps, multiple=True),
label=T('web2py apps to deploy')))
cmd = output = errors= ""
if form.accepts(request,session):
cmd = output = errors = ""
if form.accepts(request, session):
try:
kill()
except:
pass
ignore_apps = [item for item in apps if not item in form.vars.applications]
ignore_apps = [
item for item in apps if not item in form.vars.applications]
regex = re.compile('\(applications/\(.*')
w2p_origin = os.getcwd()
osrepo = form.vars.osrepo
@@ -34,23 +41,25 @@ def deploy():
assert repo.bare == False
for i in form.vars.applications:
appsrc = os.path.join(apath(r=request),i)
appdest = os.path.join(osrepo,'wsgi',osname,'applications',i)
dir_util.copy_tree(appsrc,appdest)
appsrc = os.path.join(apath(r=request), i)
appdest = os.path.join(osrepo, 'wsgi', osname, 'applications', i)
dir_util.copy_tree(appsrc, appdest)
#shutil.copytree(appsrc,appdest)
index.add(['wsgi/'+osname+'/applications/'+i])
index.add(['wsgi/' + osname + '/applications/' + i])
new_commit = index.commit("Deploy from Web2py IDE")
origin = repo.remotes.origin
origin.push
origin.push()
#Git code ends here
return dict(form=form,command=cmd)
return dict(form=form, command=cmd)
class EXISTS(object):
def __init__(self, error_message='file not found'):
self.error_message = error_message
def __call__(self, value):
if os.path.exists(value):
return (value,None)
return (value,self.error_message)
return (value, None)
return (value, self.error_message)
@@ -1,10 +1,10 @@
response.files=response.files[:3]
response.menu=[]
response.files = response.files[:3]
response.menu = []
def index():
return locals()
def about():
return locals()
+17 -14
View File
@@ -1,25 +1,29 @@
import sys
import cStringIO
import gluon.contrib.shell
import code, thread
import code
import thread
from gluon.shell import env
if DEMO_MODE or MULTI_USER_MODE:
session.flash = T('disabled in demo mode')
redirect(URL('default','site'))
redirect(URL('default', 'site'))
FE = 10 ** 9
FE=10**9
def index():
app = request.args(0) or 'admin'
reset()
return dict(app=app)
def callback():
app = request.args[0]
command = request.vars.statement
escape = command[:1]!='!'
history = session['history:'+app] = session.get('history:'+app,gluon.contrib.shell.History())
escape = command[:1] != '!'
history = session['history:' + app] = session.get(
'history:' + app, gluon.contrib.shell.History())
if not escape:
command = command[1:]
if command == '%reset':
@@ -27,21 +31,20 @@ def callback():
return '*** reset ***'
elif command[0] == '%':
try:
command=session['commands:'+app][int(command[1:])]
command = session['commands:' + app][int(command[1:])]
except ValueError:
return ''
session['commands:'+app].append(command)
environ=env(app,True)
output = gluon.contrib.shell.run(history,command,environ)
k = len(session['commands:'+app]) - 1
session['commands:' + app].append(command)
environ = env(app, True, extra_request=dict(is_https=request.is_https))
output = gluon.contrib.shell.run(history, command, environ)
k = len(session['commands:' + app]) - 1
#output = PRE(output)
#return TABLE(TR('In[%i]:'%k,PRE(command)),TR('Out[%i]:'%k,output))
return 'In [%i] : %s%s\n' % (k + 1, command, output)
def reset():
app = request.args(0) or 'admin'
session['commands:'+app] = []
session['history:'+app] = gluon.contrib.shell.History()
session['commands:' + app] = []
session['history:' + app] = gluon.contrib.shell.History()
return 'done'
+5 -5
View File
@@ -2,10 +2,12 @@ import os
from gluon.settings import global_settings, read_file
#
def index():
app = request.args(0)
return dict(app=app)
def profiler():
"""
to use the profiler start web2py with -F profiler.log
@@ -19,13 +21,11 @@ def profiler():
else:
size = 0
if os.path.exists(filename):
data = read_file('profiler.log','rb')
if size<len(data):
data = read_file('profiler.log', 'rb')
if size < len(data):
data = data[size:]
else:
size=0
size = 0
size += len(data)
response.cookies[KEY] = size
return data
@@ -33,7 +33,7 @@ def list_apps():
@service.jsonrpc
def list_files(app, pattern='.*\.py$'):
files = listdir(apath('%s/' % app, r=request), pattern)
return [x.replace('\\','/') for x in files]
return [x.replace('\\', '/') for x in files]
@service.jsonrpc
@@ -43,7 +43,7 @@ def read_file(filename, b64=False):
try:
data = f.read()
if not b64:
data = data.replace('\r','')
data = data.replace('\r', '')
else:
data = base64.b64encode(data)
finally:
@@ -82,6 +82,7 @@ def install(app_name, filename, data, overwrite=True):
return installed
@service.jsonrpc
def attach_debugger(host='localhost', port=6000, authkey='secret password'):
import gluon.contrib.qdb as qdb
@@ -124,7 +125,7 @@ def detach_debugger():
gluon.debug.qdb_debugger = None
return True
def call():
session.forget()
return service()
+305 -258
View File
@@ -1,64 +1,73 @@
# -*- coding: utf-8 -*-
import os, uuid, re, pickle, urllib, glob
import os
import uuid
import re
import pickle
import urllib
import glob
from gluon.admin import app_create, plugin_install
from gluon.fileutils import abspath, read_file, write_file
def reset(session):
session.app={
'name':'',
'params':[('title','My New App'),
('subtitle','powered by web2py'),
('author','you'),
('author_email','you@example.com'),
('keywords',''),
('description',''),
('layout_theme','Default'),
('database_uri','sqlite://storage.sqlite'),
('security_key',str(uuid.uuid4())),
('email_server','localhost'),
('email_sender','you@example.com'),
('email_login',''),
('login_method','local'),
('login_config',''),
('plugins',[])],
'tables':['auth_user'],
'table_auth_user':['username','first_name',
'last_name','email','password'],
'pages':['index','error'],
'page_index':'# Welcome to my new app',
'page_error':'# Error: the document does not exist',
session.app = {
'name': '',
'params': [('title', 'My New App'),
('subtitle', 'powered by web2py'),
('author', 'you'),
('author_email', 'you@example.com'),
('keywords', ''),
('description', ''),
('layout_theme', 'Default'),
('database_uri', 'sqlite://storage.sqlite'),
('security_key', str(uuid.uuid4())),
('email_server', 'localhost'),
('email_sender', 'you@example.com'),
('email_login', ''),
('login_method', 'local'),
('login_config', ''),
('plugins', [])],
'tables': ['auth_user'],
'table_auth_user': ['username', 'first_name',
'last_name', 'email', 'password'],
'pages': ['index', 'error'],
'page_index': '# Welcome to my new app',
'page_error': '# Error: the document does not exist',
}
if not session.app: reset(session)
if not session.app:
reset(session)
def listify(x):
if not isinstance(x,(list,tuple)):
if not isinstance(x, (list, tuple)):
return x and [x] or []
return x
def clean(name):
return re.sub('\W+','_',name.strip().lower())
return re.sub('\W+', '_', name.strip().lower())
def index():
response.view='wizard/step.html'
response.view = 'wizard/step.html'
reset(session)
apps=os.listdir(os.path.join(request.folder,'..'))
form=SQLFORM.factory(Field('name',requires=[IS_NOT_EMPTY(),
apps = os.listdir(os.path.join(request.folder, '..'))
form = SQLFORM.factory(Field('name', requires=[IS_NOT_EMPTY(),
IS_ALPHANUMERIC()]))
if form.accepts(request.vars):
app = form.vars.name
session.app['name'] = app
if MULTI_USER_MODE and db(db.app.name==app)\
(db.app.owner!=auth.user.id).count():
if MULTI_USER_MODE and db(db.app.name == app)(db.app.owner != auth.user.id).count():
session.flash = 'App belongs already to other user'
elif app in apps:
meta = os.path.normpath(\
meta = os.path.normpath(
os.path.join(os.path.normpath(request.folder),
'..',app,'wizard.metadata'))
'..', app, 'wizard.metadata'))
if os.path.exists(meta):
try:
metafile = open(meta,'rb')
metafile = open(meta, 'rb')
try:
session.app = pickle.load(metafile)
finally:
@@ -67,14 +76,14 @@ def index():
except:
session.flash = T("The app exists, was NOT created by wizard, continue to overwrite!")
redirect(URL('step1'))
return dict(step='Start',form=form)
return dict(step='Start', form=form)
def step1():
from gluon.contrib.simplejson import loads
import urllib
if not session.themes:
url=LAYOUTS_APP+'/default/layouts.json'
url = LAYOUTS_APP + '/default/layouts.json'
try:
data = urllib.urlopen(url).read()
session.themes = ['Default'] + loads(data)['layouts']
@@ -82,145 +91,158 @@ def step1():
session.themes = ['Default']
themes = session.themes
if not session.plugins:
url = PLUGINS_APP+'/default/plugins.json'
url = PLUGINS_APP + '/default/plugins.json'
try:
data = urllib.urlopen(url).read()
session.plugins = loads(data)['plugins']
except:
session.plugins = []
plugins = [x.split('.')[2] for x in session.plugins]
response.view='wizard/step.html'
response.view = 'wizard/step.html'
params = dict(session.app['params'])
form=SQLFORM.factory(
Field('title',default=params.get('title',None),
form = SQLFORM.factory(
Field('title', default=params.get('title', None),
requires=IS_NOT_EMPTY()),
Field('subtitle',default=params.get('subtitle',None)),
Field('author',default=params.get('author',None)),
Field('author_email',default=params.get('author_email',None)),
Field('keywords',default=params.get('keywords',None)),
Field('description','text',
default=params.get('description',None)),
Field('layout_theme',requires=IS_IN_SET(themes),
default=params.get('layout_theme',themes[0])),
Field('database_uri',default=params.get('database_uri',None)),
Field('security_key',default=params.get('security_key',None)),
Field('email_server',default=params.get('email_server',None)),
Field('email_sender',default=params.get('email_sender',None)),
Field('email_login',default=params.get('email_login',None)),
Field('login_method',requires=IS_IN_SET(('local','janrain')),
default=params.get('login_method','local')),
Field('login_config',default=params.get('login_config',None)),
Field('plugins','list:string',requires=IS_IN_SET(plugins,multiple=True)))
Field('subtitle', default=params.get('subtitle', None)),
Field('author', default=params.get('author', None)),
Field(
'author_email', default=params.get('author_email', None)),
Field('keywords', default=params.get('keywords', None)),
Field('description', 'text',
default=params.get('description', None)),
Field('layout_theme', requires=IS_IN_SET(themes),
default=params.get('layout_theme', themes[0])),
Field(
'database_uri', default=params.get('database_uri', None)),
Field(
'security_key', default=params.get('security_key', None)),
Field(
'email_server', default=params.get('email_server', None)),
Field(
'email_sender', default=params.get('email_sender', None)),
Field('email_login', default=params.get('email_login', None)),
Field('login_method', requires=IS_IN_SET(('local', 'janrain')),
default=params.get('login_method', 'local')),
Field(
'login_config', default=params.get('login_config', None)),
Field('plugins', 'list:string', requires=IS_IN_SET(plugins, multiple=True)))
if form.accepts(request.vars):
session.app['params']=[(key,form.vars.get(key,None))
for key,value in session.app['params']]
session.app['params'] = [(key, form.vars.get(key, None))
for key, value in session.app['params']]
redirect(URL('step2'))
return dict(step='1: Setting Parameters',form=form)
return dict(step='1: Setting Parameters', form=form)
def step2():
response.view='wizard/step.html'
form=SQLFORM.factory(Field('table_names','list:string',
response.view = 'wizard/step.html'
form = SQLFORM.factory(Field('table_names', 'list:string',
default=session.app['tables']))
if form.accepts(request.vars):
table_names = [clean(t) for t in listify(form.vars.table_names) \
table_names = [clean(t) for t in listify(form.vars.table_names)
if t.strip()]
if [t for t in table_names if t.startswith('auth_') and \
not t=='auth_user']:
if [t for t in table_names if t.startswith('auth_') and
not t == 'auth_user']:
form.error.table_names = \
T('invalid table names (auth_* tables already defined)')
else:
session.app['tables']=table_names
session.app['tables'] = table_names
for table in session.app['tables']:
if not 'table_'+table in session.app:
session.app['table_'+table]=['name']
if not table=='auth_user':
name = table+'_manage'
if not 'table_' + table in session.app:
session.app['table_' + table] = ['name']
if not table == 'auth_user':
name = table + '_manage'
if not name in session.app['pages']:
session.app['pages'].append(name)
session.app['page_'+name] = \
session.app['page_' + name] = \
'## Manage %s\n\n{{=form}}' % (table)
if session.app['tables']:
redirect(URL('step3',args=0))
redirect(URL('step3', args=0))
else:
redirect(URL('step4'))
return dict(step='2: Tables',form=form)
return dict(step='2: Tables', form=form)
def step3():
response.view='wizard/step.html'
n=int(request.args(0) or 0)
m=len(session.app['tables'])
if n>=m: redirect(URL('step2'))
table=session.app['tables'][n]
form=SQLFORM.factory(Field('field_names','list:string',
default=session.app.get('table_'+table,[])))
response.view = 'wizard/step.html'
n = int(request.args(0) or 0)
m = len(session.app['tables'])
if n >= m:
redirect(URL('step2'))
table = session.app['tables'][n]
form = SQLFORM.factory(Field('field_names', 'list:string',
default=session.app.get('table_' + table, [])))
if form.accepts(request.vars) and form.vars.field_names:
fields=listify(form.vars.field_names)
if table=='auth_user':
for field in ['first_name','last_name','username','email','password']:
fields = listify(form.vars.field_names)
if table == 'auth_user':
for field in ['first_name', 'last_name', 'username', 'email', 'password']:
if not field in fields:
fields.append(field)
session.app['table_'+table]=[t.strip().lower()
session.app['table_' + table] = [t.strip().lower()
for t in listify(form.vars.field_names)
if t.strip()]
try:
tables=sort_tables(session.app['tables'])
tables = sort_tables(session.app['tables'])
except RuntimeError:
response.flash=T('invalid circular reference')
response.flash = T('invalid circular reference')
else:
if n<m-1:
redirect(URL('step3',args=n+1))
if n < m - 1:
redirect(URL('step3', args=n + 1))
else:
redirect(URL('step4'))
return dict(step='3: Fields for table "%s" (%s of %s)' \
% (table,n+1,m),table=table,form=form)
return dict(step='3: Fields for table "%s" (%s of %s)'
% (table, n + 1, m), table=table, form=form)
def step4():
response.view='wizard/step.html'
form=SQLFORM.factory(Field('pages','list:string',
response.view = 'wizard/step.html'
form = SQLFORM.factory(Field('pages', 'list:string',
default=session.app['pages']))
if form.accepts(request.vars):
session.app['pages']=[clean(t)
session.app['pages'] = [clean(t)
for t in listify(form.vars.pages)
if t.strip()]
if session.app['pages']:
redirect(URL('step5',args=0))
redirect(URL('step5', args=0))
else:
redirect(URL('step6'))
return dict(step='4: Pages',form=form)
return dict(step='4: Pages', form=form)
def step5():
response.view='wizard/step.html'
n=int(request.args(0) or 0)
m=len(session.app['pages'])
if n>=m: redirect(URL('step4'))
page=session.app['pages'][n]
markmin_url='http://web2py.com/examples/static/markmin.html'
form=SQLFORM.factory(Field('content','text',
default=session.app.get('page_'+page,[]),
response.view = 'wizard/step.html'
n = int(request.args(0) or 0)
m = len(session.app['pages'])
if n >= m:
redirect(URL('step4'))
page = session.app['pages'][n]
markmin_url = 'http://web2py.com/examples/static/markmin.html'
form = SQLFORM.factory(Field('content', 'text',
default=session.app.get('page_' + page, []),
comment=A('use markmin',
_href=markmin_url,_target='_blank')),
_href=markmin_url, _target='_blank')),
formstyle='table2cols')
if form.accepts(request.vars):
session.app['page_'+page]=form.vars.content
if n<m-1:
redirect(URL('step5',args=n+1))
session.app['page_' + page] = form.vars.content
if n < m - 1:
redirect(URL('step5', args=n + 1))
else:
redirect(URL('step6'))
return dict(step='5: View for page "%s" (%s of %s)' % (page,n+1,m),form=form)
return dict(step='5: View for page "%s" (%s of %s)' % (page, n + 1, m), form=form)
def step6():
response.view='wizard/step.html'
response.view = 'wizard/step.html'
params = dict(session.app['params'])
app = session.app['name']
form=SQLFORM.factory(
Field('generate_model','boolean',default=True),
Field('generate_controller','boolean',default=True),
Field('generate_views','boolean',default=True),
Field('generate_menu','boolean',default=True),
Field('apply_layout','boolean',default=True),
Field('erase_database','boolean',default=True),
Field('populate_database','boolean',default=True))
form = SQLFORM.factory(
Field('generate_model', 'boolean', default=True),
Field('generate_controller', 'boolean', default=True),
Field('generate_views', 'boolean', default=True),
Field('generate_menu', 'boolean', default=True),
Field('apply_layout', 'boolean', default=True),
Field('erase_database', 'boolean', default=True),
Field('populate_database', 'boolean', default=True))
if form.accepts(request.vars):
if DEMO_MODE:
session.flash = T('Application cannot be generated in demo mode')
@@ -228,159 +250,173 @@ def step6():
create(form.vars)
session.flash = 'Application %s created' % app
redirect(URL('generated'))
return dict(step='6: Generate app "%s"' % app,form=form)
return dict(step='6: Generate app "%s"' % app, form=form)
def generated():
return dict(app=session.app['name'])
def sort_tables(tables):
import re
regex = re.compile('(%s)' % '|'.join(tables))
is_auth_user = 'auth_user' in tables
d={}
d = {}
for table in tables:
d[table]=[]
d[table] = []
for field in session.app['table_%s' % table]:
d[table]+=regex.findall(field)
tables=[]
d[table] += regex.findall(field)
tables = []
if is_auth_user:
tables.append('auth_user')
def append(table,trail=[]):
def append(table, trail=[]):
if table in trail:
raise RuntimeError
for t in d[table]:
# if not t==table: (problem, no dropdown for self references)
append(t,trail=trail+[table])
append(t, trail=trail + [table])
if not table in tables:
tables.append(table)
for table in d: append(table)
for table in d:
append(table)
return tables
def make_table(table,fields):
rawtable=table
if table!='auth_user': table='t_'+table
s=''
s+='\n'+'#'*40+'\n'
s+="db.define_table('%s',\n" % table
first_field='id'
def make_table(table, fields):
rawtable = table
if table != 'auth_user':
table = 't_' + table
s = ''
s += '\n' + '#' * 40 + '\n'
s += "db.define_table('%s',\n" % table
first_field = 'id'
for field in fields:
items=[x.lower() for x in field.split()]
items = [x.lower() for x in field.split()]
has = {}
keys = []
for key in ['notnull','unique','integer','double','boolean','float',
'boolean', 'date','time','datetime','text','wiki',
'html','file','upload','image','true',
'hidden','readonly','writeonly','multiple',
'notempty','required']:
for key in ['notnull', 'unique', 'integer', 'double', 'boolean', 'float',
'boolean', 'date', 'time', 'datetime', 'text', 'wiki',
'html', 'file', 'upload', 'image', 'true',
'hidden', 'readonly', 'writeonly', 'multiple',
'notempty', 'required']:
if key in items[1:]:
keys.append(key)
has[key] = True
tables = session.app['tables']
refs = [t for t in tables if t in items]
items = items[:1] + [x for x in items[1:] \
items = items[:1] + [x for x in items[1:]
if not x in keys and not x in tables]
barename = name = '_'.join(items)
if table[:2]=='t_': name='f_'+name
if first_field=='id': first_field=name
if table[:2] == 't_': name = 'f_' + name
if first_field == 'id':
first_field = name
### determine field type
ftype='string'
deftypes={'integer':'integer','double':'double','boolean':'boolean',
'float':'double','bool':'boolean',
'date':'date','time':'time','datetime':'datetime',
'text':'text','file':'upload','image':'upload',
'upload':'upload','wiki':'text', 'html':'text'}
for key,t in deftypes.items():
ftype = 'string'
deftypes = {'integer': 'integer', 'double': 'double', 'boolean': 'boolean',
'float': 'double', 'bool': 'boolean',
'date': 'date', 'time': 'time', 'datetime': 'datetime',
'text': 'text', 'file': 'upload', 'image': 'upload',
'upload': 'upload', 'wiki': 'text', 'html': 'text'}
for key, t in deftypes.items():
if key in has:
ftype = t
if refs:
key = refs[0]
if not key=='auth_user': key='t_'+key
if not key == 'auth_user':
key = 't_' + key
if 'multiple' in has:
ftype='list:reference %s' % key
ftype = 'list:reference %s' % key
else:
ftype='reference %s' % key
if ftype=='string' and 'multiple' in has:
ftype='list:string'
elif ftype=='integer' and 'multiple' in has:
ftype='list:integer'
elif name=='password':
ftype='password'
s+=" Field('%s', type='%s'" % (name, ftype)
ftype = 'reference %s' % key
if ftype == 'string' and 'multiple' in has:
ftype = 'list:string'
elif ftype == 'integer' and 'multiple' in has:
ftype = 'list:integer'
elif name == 'password':
ftype = 'password'
s += " Field('%s', type='%s'" % (name, ftype)
### determine field attributes
if 'notnull' in has or 'notempty' in has or 'required' in has:
s+=', notnull=True'
s += ', notnull=True'
if 'unique' in has:
s+=', unique=True'
if ftype=='boolean' and 'true' in has:
s+=",\n default=True"
s += ', unique=True'
if ftype == 'boolean' and 'true' in has:
s += ",\n default=True"
### determine field representation
elif 'wiki' in has:
s+=",\n represent=lambda x, row: MARKMIN(x)"
s+=",\n comment='WIKI (markmin)'"
s += ",\n represent=lambda x, row: MARKMIN(x)"
s += ",\n comment='WIKI (markmin)'"
elif 'html' in has:
s+=",\n represent=lambda x, row: XML(x,sanitize=True)"
s+=",\n comment='HTML (sanitized)'"
s += ",\n represent=lambda x, row: XML(x,sanitize=True)"
s += ",\n comment='HTML (sanitized)'"
### determine field access
if name=='password' or 'writeonly' in has:
s+=",\n readable=False"
if name == 'password' or 'writeonly' in has:
s += ",\n readable=False"
elif 'hidden' in has:
s+=",\n writable=False, readable=False"
s += ",\n writable=False, readable=False"
elif 'readonly' in has:
s+=",\n writable=False"
s += ",\n writable=False"
### make up a label
s+=",\n label=T('%s')),\n" % \
s += ",\n label=T('%s')),\n" % \
' '.join(x.capitalize() for x in barename.split('_'))
if table=='auth_user':
s+=" Field('created_on','datetime',default=request.now,\n"
s+=" label=T('Created On'),writable=False,readable=False),\n"
s+=" Field('modified_on','datetime',default=request.now,\n"
s+=" label=T('Modified On'),writable=False,readable=False,\n"
s+=" update=request.now),\n"
s+=" Field('registration_key',default='',\n"
s+=" writable=False,readable=False),\n"
s+=" Field('reset_password_key',default='',\n"
s+=" writable=False,readable=False),\n"
s+=" Field('registration_id',default='',\n"
s+=" writable=False,readable=False),\n"
if table == 'auth_user':
s += " Field('created_on','datetime',default=request.now,\n"
s += " label=T('Created On'),writable=False,readable=False),\n"
s += " Field('modified_on','datetime',default=request.now,\n"
s += " label=T('Modified On'),writable=False,readable=False,\n"
s += " update=request.now),\n"
s += " Field('registration_key',default='',\n"
s += " writable=False,readable=False),\n"
s += " Field('reset_password_key',default='',\n"
s += " writable=False,readable=False),\n"
s += " Field('registration_id',default='',\n"
s += " writable=False,readable=False),\n"
elif 'auth_user' in session.app['tables']:
s+=" auth.signature,\n"
s+=" format='%("+first_field+")s',\n"
s+=" migrate=settings.migrate)\n\n"
if table=='auth_user':
s+="""
db.auth_user.first_name.requires = IS_NOT_EMPTY(error_message=auth.messages.is_empty)
db.auth_user.last_name.requires = IS_NOT_EMPTY(error_message=auth.messages.is_empty)
db.auth_user.password.requires = CRYPT(key=auth.settings.hmac_key, min_length=4)
s += " auth.signature,\n"
s += " format='%(" + first_field + ")s',\n"
s += " migrate=settings.migrate)\n\n"
if table == 'auth_user':
s += """
db.auth_user.first_name.requires = IS_NOT_EMPTY(
error_message=auth.messages.is_empty)
db.auth_user.last_name.requires = IS_NOT_EMPTY(
error_message=auth.messages.is_empty)
db.auth_user.password.requires = CRYPT(
key=auth.settings.hmac_key, min_length=4)
db.auth_user.username.requires = IS_NOT_IN_DB(db, db.auth_user.username)
db.auth_user.email.requires = (IS_EMAIL(error_message=auth.messages.invalid_email),
db.auth_user.email.requires = (
IS_EMAIL(error_message=auth.messages.invalid_email),
IS_NOT_IN_DB(db, db.auth_user.email))
"""
else:
s+="db.define_table('%s_archive',db.%s,Field('current_record','reference %s',readable=False,writable=False))\n" % (table,table,table)
s += "db.define_table('%s_archive',db.%s,Field('current_record','reference %s',readable=False,writable=False))\n" % (table, table, table)
return s
def fix_db(filename):
params = dict(session.app['params'])
content = read_file(filename,'rb')
content = read_file(filename, 'rb')
if 'auth_user' in session.app['tables']:
auth_user = make_table('auth_user',session.app['table_auth_user'])
auth_user = make_table('auth_user', session.app['table_auth_user'])
content = content.replace('sqlite://storage.sqlite',
params['database_uri'])
content = content.replace('auth.define_tables()',\
auth_user+'auth.define_tables(migrate = settings.migrate)')
content = content.replace('auth.define_tables()',
auth_user + 'auth.define_tables(migrate = settings.migrate)')
content += """
mail.settings.server = settings.email_server
mail.settings.sender = settings.email_sender
mail.settings.login = settings.email_login
"""
if params['login_method']=='janrain':
content+="""
if params['login_method'] == 'janrain':
content += """
from gluon.contrib.login_methods.rpx_account import RPXAccount
auth.settings.actions_disabled=['register','change_password','request_reset_password']
auth.settings.actions_disabled=['register','change_password',
'request_reset_password']
auth.settings.login_form = RPXAccount(request,
api_key = settings.login_config.split(':')[-1],
domain = settings.login_config.split(':')[0],
@@ -388,14 +424,15 @@ auth.settings.login_form = RPXAccount(request,
"""
write_file(filename, content, 'wb')
def make_menu(pages):
s=''
s+='response.title = settings.title\n'
s+='response.subtitle = settings.subtitle\n'
s+="response.meta.author = '%(author)s <%(author_email)s>' % settings\n"
s+='response.meta.keywords = settings.keywords\n'
s+='response.meta.description = settings.description\n'
s+='response.menu = [\n'
s = ''
s += 'response.title = settings.title\n'
s += 'response.subtitle = settings.subtitle\n'
s += "response.meta.author = '%(author)s <%(author_email)s>' % settings\n"
s += 'response.meta.keywords = settings.keywords\n'
s += 'response.meta.description = settings.description\n'
s += 'response.menu = [\n'
for page in pages:
if not page.startswith('error'):
if page.endswith('_manage'):
@@ -403,65 +440,70 @@ def make_menu(pages):
else:
page_name = page
page_name = ' '.join(x.capitalize() for x in page_name.split('_'))
s+="(T('%s'),URL('default','%s')==URL(),URL('default','%s'),[]),\n" \
% (page_name,page,page)
s+=']'
s += "(T('%s'),URL('default','%s')==URL(),URL('default','%s'),[]),\n" \
% (page_name, page, page)
s += ']'
return s
def make_page(page,contents):
if 'auth_user' in session.app['tables'] and not page in ('index','error'):
s="@auth.requires_login()\ndef %s():\n" % page
def make_page(page, contents):
if 'auth_user' in session.app['tables'] and not page in ('index', 'error'):
s = "@auth.requires_login()\ndef %s():\n" % page
else:
s="def %s():\n" % page
items = page.rsplit('_',1)
if items[0] in session.app['tables'] and len(items)==2 and items[1]=='manage':
s+=" form = SQLFORM.smartgrid(db.t_%s,onupdate=auth.archive)\n" % items[0]
s+=" return locals()\n\n"
s = "def %s():\n" % page
items = page.rsplit('_', 1)
if items[0] in session.app['tables'] and len(items) == 2 and items[1] == 'manage':
s += " form = SQLFORM.smartgrid(db.t_%s,onupdate=auth.archive)\n" % items[0]
s += " return locals()\n\n"
else:
s+=" return dict()\n\n"
s += " return dict()\n\n"
return s
def make_view(page,contents):
s="{{extend 'layout.html'}}\n\n"
s+=str(MARKMIN(contents))
def make_view(page, contents):
s = "{{extend 'layout.html'}}\n\n"
s += str(MARKMIN(contents))
return s
def populate(tables):
s = 'from gluon.contrib.populate import populate\n'
s+= 'if db(db.auth_user).isempty():\n'
s += 'if db(db.auth_user).isempty():\n'
for table in sort_tables(tables):
t=table=='auth_user' and 'auth_user' or 't_'+table
s+=" populate(db.%s,10)\n" % t
t = table == 'auth_user' and 'auth_user' or 't_' + table
s += " populate(db.%s,10)\n" % t
return s
def create(options):
if DEMO_MODE:
session.flash = T('disabled in demo mode')
redirect(URL('step6'))
params = dict(session.app['params'])
app = session.app['name']
if app_create(app,request,force=True,key=params['security_key']):
if app_create(app, request, force=True, key=params['security_key']):
if MULTI_USER_MODE:
db.app.insert(name=app,owner=auth.user.id)
db.app.insert(name=app, owner=auth.user.id)
else:
session.flash = 'Failure to create application'
redirect(URL('step6'))
### save metadata in newapp/wizard.metadata
try:
meta = os.path.join(request.folder,'..',app,'wizard.metadata')
file=open(meta,'wb')
pickle.dump(session.app,file)
meta = os.path.join(request.folder, '..', app, 'wizard.metadata')
file = open(meta, 'wb')
pickle.dump(session.app, file)
file.close()
except IOError:
session.flash = 'Failure to write wizard metadata'
redirect(URL('step6'))
### apply theme
if options.apply_layout and params['layout_theme']!='Default':
if options.apply_layout and params['layout_theme'] != 'Default':
try:
fn = 'web2py.plugin.layout_%s.w2p' % params['layout_theme']
theme = urllib.urlopen(LAYOUTS_APP+'/static/plugin_layouts/plugins/'+fn)
theme = urllib.urlopen(
LAYOUTS_APP + '/static/plugin_layouts/plugins/' + fn)
plugin_install(app, theme, request, fn)
except:
session.flash = T("unable to download layout")
@@ -469,55 +511,58 @@ def create(options):
### apply plugins
for plugin in params['plugins']:
try:
plugin_name = 'web2py.plugin.'+plugin+'.w2p'
stream = urllib.urlopen(PLUGINS_APP+'/static/'+plugin_name)
plugin_name = 'web2py.plugin.' + plugin + '.w2p'
stream = urllib.urlopen(PLUGINS_APP + '/static/' + plugin_name)
plugin_install(app, stream, request, plugin_name)
except Exception, e:
session.flash = T("unable to download plugin: %s" % plugin)
### write configuration file into newapp/models/0.py
model = os.path.join(request.folder,'..',app,'models','0.py')
model = os.path.join(request.folder, '..', app, 'models', '0.py')
file = open(model, 'wb')
try:
file.write("from gluon.storage import Storage\n")
file.write("settings = Storage()\n\n")
file.write("settings.migrate = True\n")
for key,value in session.app['params']:
file.write("settings.%s = %s\n" % (key,repr(value)))
for key, value in session.app['params']:
file.write("settings.%s = %s\n" % (key, repr(value)))
finally:
file.close()
### write configuration file into newapp/models/menu.py
if options.generate_menu:
model = os.path.join(request.folder,'..',app,'models','menu.py')
file = open(model,'wb')
model = os.path.join(request.folder, '..', app, 'models', 'menu.py')
file = open(model, 'wb')
try:
file.write(make_menu(session.app['pages']))
finally:
file.close()
### customize the auth_user table
model = os.path.join(request.folder,'..',app,'models','db.py')
model = os.path.join(request.folder, '..', app, 'models', 'db.py')
fix_db(model)
### create newapp/models/db_wizard.py
if options.generate_model:
model = os.path.join(request.folder,'..',app,'models','db_wizard.py')
file = open(model,'wb')
model = os.path.join(
request.folder, '..', app, 'models', 'db_wizard.py')
file = open(model, 'wb')
try:
file.write('### we prepend t_ to tablenames and f_ to fieldnames for disambiguity\n\n')
tables = sort_tables(session.app['tables'])
for table in tables:
if table=='auth_user': continue
file.write(make_table(table,session.app['table_'+table]))
if table == 'auth_user':
continue
file.write(make_table(table, session.app['table_' + table]))
finally:
file.close()
model = os.path.join(request.folder,'..',app,
'models','db_wizard_populate.py')
if os.path.exists(model): os.unlink(model)
model = os.path.join(request.folder, '..', app,
'models', 'db_wizard_populate.py')
if os.path.exists(model):
os.unlink(model)
if options.populate_database and session.app['tables']:
file = open(model,'wb')
file = open(model, 'wb')
try:
file.write(populate(session.app['tables']))
finally:
@@ -525,8 +570,9 @@ def create(options):
### create newapp/controllers/default.py
if options.generate_controller:
controller = os.path.join(request.folder,'..',app,'controllers','default.py')
file = open(controller,'wb')
controller = os.path.join(
request.folder, '..', app, 'controllers', 'default.py')
file = open(controller, 'wb')
try:
file.write("""# -*- coding: utf-8 -*-
### required - do no delete
@@ -536,23 +582,24 @@ def call(): return service()
### end requires
""")
for page in session.app['pages']:
file.write(make_page(page,session.app.get('page_'+page,'')))
file.write(
make_page(page, session.app.get('page_' + page, '')))
finally:
file.close()
### create newapp/views/default/*.html
if options.generate_views:
for page in session.app['pages']:
view = os.path.join(request.folder,'..',app,'views','default',page+'.html')
file = open(view,'wb')
view = os.path.join(
request.folder, '..', app, 'views', 'default', page + '.html')
file = open(view, 'wb')
try:
file.write(make_view(page,session.app.get('page_'+page,'')))
file.write(
make_view(page, session.app.get('page_' + page, '')))
finally:
file.close()
if options.erase_database:
path = os.path.join(request.folder,'..',app,'databases','*')
path = os.path.join(request.folder, '..', app, 'databases', '*')
for file in glob.glob(path):
os.unlink(file)
+3 -5
View File
@@ -1,10 +1,10 @@
EXPIRATION_MINUTES=60
DIGITS=('0','1','2','3','4','5','6','7','8','9')
import os, time, stat, cPickle, logging
path=os.path.join(request.folder,'sessions')
path = os.path.join(request.folder,'sessions')
if not os.path.exists(path):
os.mkdir(path)
now=time.time()
now = time.time()
for filename in os.listdir(path):
fullpath=os.path.join(path,filename)
if os.path.isfile(fullpath) and filename.startswith(DIGITS):
@@ -18,6 +18,4 @@ for filename in os.listdir(path):
if (now - filetime) > expiration:
os.unlink(fullpath)
except:
logging.exception('failure to check %s'%fullpath)
logging.exception('failure to check %s' % fullpath)
+6 -1
View File
@@ -34,10 +34,12 @@
'App does not exist or your are not authorized': 'Додаток не існує, або ви не авторизовані',
'appadmin': 'Aдм.панель',
'appadmin is disabled because insecure channel': "адмін.панель відключено через використання ненадійного каналу зв'язку",
'Application': 'Додаток (Application)',
'application "%s" uninstalled': 'додаток "%s" вилучено',
'application %(appname)s installed with md5sum: %(digest)s': 'додаток %(appname)s встановлено з md5sum: %(digest)s',
'Application cannot be generated in demo mode': 'В демо-режимі генерувати додатки не можна',
'application compiled': 'додаток скомпільовано',
'Application exists already': 'Додаток вже існує',
'application is compiled and cannot be designed': 'додаток скомпільований. налаштування змінювати не можна',
'Application name:': 'Назва додатку:',
'are not used': 'не використовуються',
@@ -160,6 +162,7 @@
'Error snapshot': 'Розгорнутий знімок стану (Error snapshot)',
'Error ticket': 'Позначка (ticket) про помилку',
'Errors': 'Помилки',
'Errors in form, please check it out.': 'Помилка у формі, будь-ласка перевірте її.',
'Exception %(extype)s: %(exvalue)s': 'Виключення %(extype)s: %(exvalue)s',
'Exception %s': 'Виключення %s',
'Exception instance attributes': 'Атрибути примірника класу Exception (виключення)',
@@ -388,6 +391,7 @@
'There are no models': 'Моделей, наразі, нема',
'There are no modules': 'Модулів поки що нема',
'There are no plugins': 'Жодної втулки, наразі, не встановлено',
'There are no private files': 'Приватних файлів поки що нема',
'There are no static files': 'Статичних файлів, наразі, нема',
'There are no translators': 'Перекладів нема',
'There are no translators, only default language is supported': 'Перекладів нема, підтримується тільки мова оригіналу',
@@ -418,6 +422,7 @@
'Traceback': 'Стек викликів (Traceback)',
'Translation strings for the application': 'Пари рядків <оригінал>:<переклад> для вибраної мови',
'try something like': 'спробуйте щось схоже на',
'Try the mobile interface': 'Спробуйте мобільний інтерфейс',
'try view': 'дивитись результат',
'Type PDB debugger command in here and hit Return (Enter) to execute it.': 'наберіть тут будь-які команди ладнача PDB і натисніть клавішу [Return] ([Enter]), щоб запустити їх на виконання.',
'Type python statement in here and hit Return (Enter) to execute it.': 'Наберіть тут будь-які вирази Python і натисніть клавішу [Return] ([Enter]), щоб запустити їх на виконання.',
@@ -463,7 +468,7 @@
'Views': 'Відображення (Views)',
'views': 'відображення',
'WARNING:': 'ПОПЕРЕДЖЕННЯ:',
'Web Framework': 'Web Framework',
'Web Framework': 'Веб-каркас (Web Framework)',
'web2py apps to deploy': 'Готові до розгортання додатки web2py',
'web2py Debugger': 'Ладнач web2py',
'web2py downgrade': 'повернення на попередню версію web2py',
+1 -3
View File
@@ -1,7 +1,7 @@
EXPIRATION = 60 * 60 # logout after 60 minutes of inactivity
CHECK_VERSION = True
WEB2PY_URL = 'http://web2py.com'
WEB2PY_VERSION_URL = WEB2PY_URL+'/examples/default/version'
WEB2PY_VERSION_URL = WEB2PY_URL + '/examples/default/version'
###########################################################################
# Preferences for EditArea
@@ -78,5 +78,3 @@ PLUGINS_APP = 'http://web2py.com/plugins'
# set the language
if 'adminLanguage' in request.cookies and not (request.cookies['adminLanguage'] is None):
T.force(request.cookies['adminLanguage'].value)
-2
View File
@@ -28,5 +28,3 @@ from gluon.languages import findT, update_all_languages
from gluon.myregex import *
from gluon.restricted import *
from gluon.compileapp import compile_application, remove_compiled_application
+25 -19
View File
@@ -1,4 +1,6 @@
import base64, os, time
import base64
import os
import time
from gluon import portalocker
from gluon.admin import apath
from gluon.fileutils import read_file
@@ -24,7 +26,8 @@ elif not request.is_local and not DEMO_MODE:
try:
_config = {}
port = int(request.env.server_port or 0)
restricted(read_file(apath('../parameters_%i.py' % port, request)), _config)
restricted(
read_file(apath('../parameters_%i.py' % port, request)), _config)
if not 'password' in _config or not _config['password']:
raise HTTP(200, T('admin disabled because no admin password'))
@@ -38,7 +41,8 @@ except IOError:
raise HTTP(200,
T('admin disabled because not supported on google app engine'))
else:
raise HTTP(200, T('admin disabled because unable to access password file'))
raise HTTP(
200, T('admin disabled because unable to access password file'))
def verify_password(password):
@@ -50,7 +54,7 @@ def verify_password(password):
elif _config['password'].startswith('pam_user:'):
session.pam_user = _config['password'][9:].strip()
import gluon.contrib.pam
return gluon.contrib.pam.authenticate(session.pam_user,password)
return gluon.contrib.pam.authenticate(session.pam_user, password)
else:
return _config['password'] == CRYPT()(password)[0]
@@ -63,6 +67,7 @@ deny_file = os.path.join(request.folder, 'private', 'hosts.deny')
allowed_number_of_attempts = 5
expiration_failed_logins = 3600
def read_hosts_deny():
import datetime
hosts = {}
@@ -83,28 +88,30 @@ def read_hosts_deny():
f.close()
return hosts
def write_hosts_deny(denied_hosts):
f = open(deny_file, 'w')
portalocker.lock(f, portalocker.LOCK_EX)
for key, val in denied_hosts.items():
if time.time()-val[1] < expiration_failed_logins:
if time.time() - val[1] < expiration_failed_logins:
line = '%s %s %s\n' % (key, val[0], val[1])
f.write(line)
portalocker.unlock(f)
f.close()
def login_record(success=True):
denied_hosts = read_hosts_deny()
val = (0,0)
val = (0, 0)
if success and request.client in denied_hosts:
del denied_hosts[request.client]
elif not success and not request.is_local:
val = denied_hosts.get(request.client,(0,0))
if time.time()-val[1]<expiration_failed_logins \
val = denied_hosts.get(request.client, (0, 0))
if time.time() - val[1] < expiration_failed_logins \
and val[0] >= allowed_number_of_attempts:
return val[0] # locked out
time.sleep(2**val[0])
val = (val[0]+1,int(time.time()))
time.sleep(2 ** val[0])
val = (val[0] + 1, int(time.time()))
denied_hosts[request.client] = val
write_hosts_deny(denied_hosts)
return val[0]
@@ -124,9 +131,9 @@ if session.authorized:
session.last_time = t0
if request.vars.is_mobile in ('true','false','auto'):
if request.vars.is_mobile in ('true', 'false', 'auto'):
session.is_mobile = request.vars.is_mobile or 'auto'
if request.controller=='default' and request.function=='index':
if request.controller == 'default' and request.function == 'index':
if not request.vars.is_mobile:
session.is_mobile = 'auto'
if not session.is_mobile:
@@ -141,14 +148,14 @@ else:
if request.controller == "webservices":
basic = request.env.http_authorization
if not basic or not basic[:6].lower() == 'basic ':
raise HTTP(401,"Wrong credentials")
raise HTTP(401, "Wrong credentials")
(username, password) = base64.b64decode(basic[6:]).split(':')
if not verify_password(password) or MULTI_USER_MODE:
time.sleep(10)
raise HTTP(403,"Not authorized")
raise HTTP(403, "Not authorized")
elif not session.authorized and not \
(request.controller+'/'+request.function in
('default/index','default/user','plugin_jqmobile/index','plugin_jqmobile/about')):
(request.controller + '/' + request.function in
('default/index', 'default/user', 'plugin_jqmobile/index', 'plugin_jqmobile/about')):
if request.env.query_string:
query_string = '?' + request.env.query_string
@@ -165,7 +172,6 @@ elif session.authorized and \
request.function == 'index':
redirect(URL(request.application, 'default', 'site'))
if request.controller=='appadmin' and DEMO_MODE:
if request.controller == 'appadmin' and DEMO_MODE:
session.flash = 'Appadmin disabled in demo mode'
redirect(URL('default','sites'))
redirect(URL('default', 'sites'))
+16 -12
View File
@@ -2,37 +2,41 @@
import os
def A_button(*a,**b):
def A_button(*a, **b):
b['_data-role'] = 'button'
b['_data-inline'] = 'true'
return A(*a,**b)
return A(*a, **b)
def button(href, label):
if is_mobile:
ret = A_button(SPAN(label), _href=href)
else:
ret = A(SPAN(label),_class='button',_href=href)
ret = A(SPAN(label), _class='button', _href=href)
return ret
def button_enable(href, app):
if os.path.exists(os.path.join(apath(app,r=request),'DISABLED')):
label = SPAN(T('Enable'),_style='color:red')
if os.path.exists(os.path.join(apath(app, r=request), 'DISABLED')):
label = SPAN(T('Enable'), _style='color:red')
else:
label = SPAN(T('Disable'),_style='color:green')
id = 'enable_'+app
return A(label,_class='button',_id=id,callback=href,target=id)
label = SPAN(T('Disable'), _style='color:green')
id = 'enable_' + app
return A(label, _class='button', _id=id, callback=href, target=id)
def sp_button(href, label):
if request.user_agent().is_mobile:
ret = A_button(SPAN(label), _href=href)
else:
ret = A(SPAN(label),_class='button special',_href=href)
ret = A(SPAN(label), _class='button special', _href=href)
return ret
def helpicon():
return IMG(_src=URL('static', 'images/help.png'), _alt='help')
def searchbox(elementid):
return TAG[''](LABEL(IMG(_id="search_start",_src=URL('static', 'images/search.png'), _alt=T('filter')), _class='icon', _for=elementid), ' ', INPUT(_id=elementid, _type='text', _size=12))
return TAG[''](LABEL(IMG(_id="search_start", _src=URL('static', 'images/search.png'), _alt=T('filter')), _class='icon', _for=elementid), ' ', INPUT(_id=elementid, _type='text', _size=12))
+13 -11
View File
@@ -4,9 +4,12 @@
if MULTI_USER_MODE:
db = DAL('sqlite://storage.sqlite') # if not, use SQLite or other DB
from gluon.tools import *
auth = Auth(globals(),db) # authentication/authorization
crud = Crud(globals(),db) # for CRUD helpers using auth
service = Service(globals()) # for json, xml, jsonrpc, xmlrpc, amfrpc
auth = Auth(
globals(), db) # authentication/authorization
crud = Crud(
globals(), db) # for CRUD helpers using auth
service = Service(
globals()) # for json, xml, jsonrpc, xmlrpc, amfrpc
plugins = PluginManager()
mail = auth.settings.mailer
@@ -15,26 +18,25 @@ if MULTI_USER_MODE:
mail.settings.login = EMAIL_LOGIN
auth.settings.extra_fields['auth_user'] = \
[Field('is_manager','boolean',default=False,writable=False)]
[Field('is_manager', 'boolean', default=False, writable=False)]
auth.define_tables() # creates all needed tables
auth.settings.registration_requires_verification = False
auth.settings.registration_requires_approval = True
auth.settings.reset_password_requires_verification = True
db.define_table('app',Field('name'),Field('owner',db.auth_user))
db.define_table('app', Field('name'), Field('owner', db.auth_user))
if not session.authorized and MULTI_USER_MODE:
if auth.user and not request.function=='user':
if auth.user and not request.function == 'user':
session.authorized = True
elif not request.function=='user':
redirect(URL('default','user/login'))
elif not request.function == 'user':
redirect(URL('default', 'user/login'))
def is_manager():
if not MULTI_USER_MODE:
return True
elif auth.user and (auth.user.id==1 or auth.user.is_manager):
elif auth.user and (auth.user.id == 1 or auth.user.is_manager):
return True
else:
return False
+9 -10
View File
@@ -7,31 +7,30 @@ _c = request.controller
_f = request.function
response.title = '%s %s' % (_f, '/'.join(request.args))
response.subtitle = 'admin'
response.menu = [(T('Site'), _f == 'site', URL(_a,'default','site'))]
response.menu = [(T('Site'), _f == 'site', URL(_a, 'default', 'site'))]
if request.vars.app or request.args:
_t = request.vars.app or request.args[0]
response.menu.append((T('Edit'), _c == 'default' and _f == 'design',
URL(_a,'default','design',args=_t)))
URL(_a, 'default', 'design', args=_t)))
response.menu.append((T('About'), _c == 'default' and _f == 'about',
URL(_a,'default','about',args=_t,)))
URL(_a, 'default', 'about', args=_t,)))
response.menu.append((T('Errors'), _c == 'default' and _f == 'errors',
URL(_a,'default','errors',args=_t)))
URL(_a, 'default', 'errors', args=_t)))
response.menu.append((T('Versioning'),
_c == 'mercurial' and _f == 'commit',
URL(_a,'mercurial','commit',args=_t)))
URL(_a, 'mercurial', 'commit', args=_t)))
if not session.authorized:
response.menu = [(T('Login'), True, URL('site'))]
else:
response.menu.append((T('Logout'), False,
URL(_a,'default',f='logout')))
URL(_a, 'default', f='logout')))
response.menu.append((T('Debug'), False,
URL(_a, 'debug','interact')))
URL(_a, 'debug', 'interact')))
if os.path.exists('applications/examples'):
response.menu.append((T('Help'), False, URL('examples','default','index')))
response.menu.append(
(T('Help'), False, URL('examples', 'default', 'index')))
else:
response.menu.append((T('Help'), False, 'http://web2py.com/examples'))
@@ -1,5 +1,4 @@
response.files.append(URL('static','plugin_multiselect/jquery.multi-select.js'))
response.files.append(URL('static','plugin_multiselect/multi-select.css'))
response.files.append(URL('static','plugin_multiselect/start.js'))
response.files.append(
URL('static', 'plugin_multiselect/jquery.multi-select.js'))
response.files.append(URL('static', 'plugin_multiselect/multi-select.css'))
response.files.append(URL('static', 'plugin_multiselect/start.js'))
-1
View File
@@ -1,2 +1 @@
+6 -2
View File
@@ -61,7 +61,7 @@ input[type=text],input[type=password],select{width:300px; margin-right:5px}
border-top:1px #DEDEDE solid;
}
.header {
// background:<fill here for header image>;
/* background:<fill here for header image>; */
}
@@ -115,6 +115,10 @@ div.flash {
z-index:2000;
}
div.flash #closeflash{color:inherit; float:right; margin-left:15px;}
.ie-lte7 div.flash #closeflash
{color:expression(this.parentNode.currentStyle['color']);float:none;position:absolute;right:4px;}
div.flash:hover { opacity:0.25; }
div.error_wrapper {display:block}
@@ -182,7 +186,7 @@ div.error {
* will look better with the declarations below
* if needed to remove base.css consider keeping these following lines in some css file.
*/
// .web2py_table {border:1px solid #ccc}
/* .web2py_table {border:1px solid #ccc} */
.web2py_paginator {}
.web2py_grid {width:100%}
.web2py_grid table {width:100%}
+2 -2
View File
@@ -1,2 +1,2 @@
/*! jQuery v@1.8.0 jquery.com | jquery.org/license */
(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bX(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bV.length;while(e--){b=bV[e]+c;if(b in a)return b}return d}function bY(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function bZ(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bY(c)&&(e[f]=p._data(c,"olddisplay",cb(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b$(a,b,c){var d=bO.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function b_(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bU[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bU[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bU[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bU[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bU[e]+"Width"))||0));return f}function ca(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bP.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+b_(a,b,c||(f?"border":"content"),e)+"px"}function cb(a){if(bR[a])return bR[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bR[a]=c,c}function ch(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||cd.test(a)?d(a,e):ch(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ch(a+"["+e+"]",b[e],c,d);else d(a,b)}function cy(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cz(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cu;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cz(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cz(a,c,d,e,"*",g)),h}function cA(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((fLine truncated
/*! jQuery v1.8.3 jquery.com | jquery.org/license */
(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r<i;r++)v.event.add(t,n,u[n][r])}o.data&&(o.data=v.extend({},o.data))}function Ot(e,t){var n;if(t.nodeType!==1)return;t.clearAttributes&&t.clearAttributes(),t.mergeAttributes&&t.mergeAttributes(e),n=t.nodeName.toLowerCase(),n==="object"?(t.parentNode&&(t.outerHTML=e.outerHTML),v.support.html5Clone&&e.innerHTML&&!v.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):n==="input"&&Et.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):n==="option"?t.selected=e.defaultSelected:n==="input"||n==="textarea"?t.defaultValue=e.defaultValue:n==="script"&&t.text!==e.text&&(t.text=e.text),t.removeAttribute(v.expando)}function Mt(e){return typeof e.getElementsByTagName!="undefined"?e.getElementsByTagName("*"):typeof e.querySelectorAll!="undefined"?e.querySelectorAll("*"):[]}function _t(e){Et.test(e.type)&&(e.defaultChecked=e.checked)}function Qt(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Jt.length;while(i--){t=Jt[i]+n;if(t in e)return t}return r}function Gt(e,t){return e=t||e,v.css(e,"display")==="none"||!v.contains(e.ownerDocument,e)}function Yt(e,t){var n,r,i=[],s=0,o=e.length;for(;s<o;s++){n=e[s];if(!n.style)continue;i[s]=v._data(n,"olddisplay"),t?(!i[s]&&n.style.display==="none"&&(n.style.display=""),n.style.display===""&&Gt(n)&&(i[s]=v._data(n,"olddisplay",nn(n.nodeName)))):(r=Dt(n,"display"),!i[s]&&r!=="none"&&v._data(n,"olddisplay",r))}for(s=0;s<o;s++){n=e[s];if(!n.style)continue;if(!t||n.style.display==="none"||n.style.display==="")n.style.display=t?i[s]||"":"none"}return e}function Zt(e,t,n){var r=Rt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function en(e,t,n,r){var i=n===(r?"border":"content")?4:t==="width"?1:0,s=0;for(;i<4;i+=2)n==="margin"&&(s+=v.css(e,n+$t[i],!0)),r?(n==="content"&&(s-=parseFloat(Dt(e,"padding"+$t[i]))||0),n!=="margin"&&(s-=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0)):(s+=parseFloat(Dt(e,"padding"+$t[i]))||0,n!=="padding"&&(s+=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0));return s}function tn(e,t,n){var r=t==="width"?e.offsetWidth:e.offsetHeight,i=!0,s=v.support.boxSizing&&v.css(e,"boxSizing")==="border-box";if(r<=0||r==null){r=Dt(e,t);if(r<0||r==null)r=e.style[t];if(Ut.test(r))return r;i=s&&(v.support.boxSizingReliable||r===e.style[t]),r=parseFloat(r)||0}return r+en(e,t,n||(s?"border":"content"),i)+"px"}function nn(e){if(Wt[e])return Wt[e];var t=v("<"+e+">").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write("<!doctype html><html><body>"),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u<a;u++)r=o[u],s=/^\+/.test(r),s&&(r=r.substr(1)||"*"),i=e[r]=e[r]||[],i[s?"unshift":"push"](n)}}function kn(e,n,r,i,s,o){s=s||n.dataTypes[0],o=o||{},o[s]=!0;var u,a=e[s],f=0,l=a?a.length:0,c=e===Sn;for(;f<l&&(c||!u);f++)u=a[f](n,r,i),typeof u=="string"&&(!c||o[u]?u=t:(n.dataTypes.unshift(u),u=kn(e,n,r,i,u,o)));return(c||!u)&&!o["*"]&&(u=kn(e,n,r,i,"*",o)),u}function Ln(e,n){var r,i,s=v.ajaxSettings.flatOptions||{};for(r in n)n[r]Line truncated
@@ -1,4 +1,4 @@
/* Modernizr 2.0.6 (Custom Build) | MIT & BSD
* Build: http://www.modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-iepp-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
* Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-flexboxlegacy-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
*/
;window.Modernizr=function(a,b,c){function H(){e.input=function(a){for(var b=0,c=a.length;b<c;b++)t[a[b]]=a[b]in l;return t}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)l.setAttribute("type",f=a[d]),e=l.type!=="text",e&&(l.value=m,l.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&l.style.WebkitAppearance!==c?(g.appendChild(l),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(l,null).WebkitAppearance!=="textfield"&&l.offsetHeight!==0,g.removeChild(l)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=l.checkValidity&&l.checkValidity()===!1:/^color$/.test(f)?(g.appendChild(l),g.offsetWidth,e=l.value!=m,g.removeChild(l)):e=l.value!=m)),s[a[d]]=!!e;return s}("search tel url email datetime date month week time datetime-local number range color".split(" "))}function F(a,b){var c=a.charAt(0).toUpperCase()+a.substr(1),d=(a+" "+p.join(c+" ")+c).split(" ");return E(d,b)}function E(a,b){for(var d in a)if(k[a[d]]!==c)return b=="pfx"?a[d]:!0;return!1}function D(a,b){return!!~(""+a).indexOf(b)}function C(a,b){return typeof a===b}function B(a,b){return A(o.join(a+";")+(b||""))}function A(a){k.cssText=a}var d="2.0.6",e={},f=!0,g=b.documentElement,h=b.head||b.getElementsByTagName("head")[0],i="modernizr",j=b.createElement(i),k=j.style,l=b.createElement("input"),m=":)",n=Object.prototype.toString,o=" -webkit- -moz- -o- -ms- -khtml- ".split(" "),p="Webkit Moz O ms Khtml".split(" "),q={svg:"http://www.w3.org/2000/svg"},r={},s={},t={},u=[],v=function(a,c,d,e){var f,h,j,k=b.createElement("div");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:i+(d+1),k.appendChild(j);f=["&shy;","<style>",a,"</style>"].join(""),k.id=i,k.innerHTML+=f,g.appendChild(k),h=c(k,a),k.parentNode.removeChild(k);return!!h},w=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=C(e[d],"function"),C(e[d],c)||(e[d]=c),e.removeAttribute(d))),e=null;return f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),x,y={}.hasOwnProperty,z;!C(y,c)&&!C(y.call,c)?z=function(a,b){return y.call(a,b)}:z=function(a,b){return b in a&&C(a.constructor.prototype[b],c)};var G=function(c,d){var f=c.join(""),g=d.length;v(f,function(c,d){var f=b.styleSheets[b.styleSheets.length-1],h=f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"",i=c.childNodes,j={};while(g--)j[i[g].id]=i[g];e.touch="ontouchstart"in a||j.touch.offsetTop===9,e.csstransforms3d=j.csstransforms3d.offsetLeft===9,e.generatedcontent=j.generatedcontent.offsetHeight>=1,e.fontface=/src/i.test(h)&&h.indexOf(d.split(" ")[0])===0},g,d)}(['@font-face {font-family:"font";src:url("https://")}',["@media (",o.join("touch-enabled),("),i,")","{#touch{top:9px;position:absolute}}"].join(""),["@media (",o.join("transform-3d),("),i,")","{#csstransforms3d{left:9px;position:absolute}}"].join(""),['#generatedcontent:after{content:"',m,'";visibility:hidden}'].join("")],["fontface","touch","csstransforms3d","generatedcontent"]);r.flexbox=function(){function c(a,b,c,d){a.style.cssText=o.join(b+":"+c+";")+(d||"")}function a(a,b,c,d){b+=":",a.style.cssText=(b+o.join(c+";"+b)).slice(0,-b.length)+(d||"")}var d=b.createElement("div"),e=b.createElement("div");a(d,"display","box","width:42px;padding:0;"),c(e,"box-flex","1","width:10px;"),d.appendChild(e),g.appendChild(d);var f=e.offsetWidth===42;d.removeChild(e),g.removeChild(d);return f},r.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},r.canvastext=function(){return!!e.canvas&&!!C(b.createElement("canvas").getContext("2d").fillText,"function")},r.webgl=function(){return!!a.WebGLRenderingContext},r.touch=function(){return e.touch},r.geolocation=function(){return!!navigator.geolocation},r.postmessage=function(){return!!a.postMessage},r.websqldatabase=function(){var b=!!a.openDatabase;return b},r.indexedDB=function(){for(var b=-1,c=p.length;++b<c;)if(a[p[b].toLowerCase()+"IndexedDB"])return!0;return!!a.indexedDB},r.hashchange=function(){return w("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},r.history=function(){return!!a.history&&!!history.pushState},r.draganddrop=function(){return w("dragstart")&&w("drop")},r.websockets=function(){for(var b=-1,c=p.length;++b<c;)if(a[p[b]+"WebSocket"])return!0;return"WebSocket"in a},r.rgba=function(){A("background-color:rgba(150,255,150,.5)");return D(k.backgroundColor,"rgba")},r.hsla=function(){A("background-color:hsla(120,40%,100%,.5)");return D(k.backgroundColor,"rgba")||D(k.backgroundColor,"hsla")},r.multiplebgs=function(){A("background:url(https://),url(https://),red url(https://)");return/(url\s*\(.*?){3}/.test(k.background)},r.backgroundsize=function(){return F("backgroundSize")},r.borderimage=function(){return F("borderImage")},r.borderradiLine truncated
;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)u[c[d]]=c[d]in k;return u.list&&(u.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),u}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)k.setAttribute("type",f=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&k.style.WebkitAppearance!==c?(g.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,g.removeChild(k)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=k.checkValidity&&k.checkValidity()===!1:e=k.value!=l)),t[a[d]]=!!e;return t}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m={}.toString,n=" -webkit- -moz- -o- -ms- ".split(" "),o="Webkit Moz O ms",p=o.split(" "),q=o.toLowerCase().split(" "),r={svg:"http://www.w3.org/2000/svg"},s={},t={},u={},v=[],w=v.slice,x,y=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.flexboxlegacy=function(){return J("boxDirection")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){retuLine truncated
+10 -4
View File
@@ -55,7 +55,7 @@ function web2py_event_handlers() {
jQuery(function() {
var flash = jQuery('.flash');
flash.hide();
if(flash.html()) flash.append('<span style="float:right;">&times;</span>').slideDown();
if(flash.html()) flash.append('<span id="closeflash">&times;</span>').slideDown();
web2py_ajax_init(document);
web2py_event_handlers();
});
@@ -102,15 +102,20 @@ function web2py_ajax_page(method, action, data, target) {
web2py_ajax_init('#'+target);
if(command)
eval(decodeURIComponent(command));
if(flash)
jQuery('.flash').html(decodeURIComponent(flash)).slideDown();
if(flash) {
jQuery('.flash')
.html(decodeURIComponent(flash))
.append('<span id="closeflash">&times;</span>')
.slideDown();
}
}
});
}
function web2py_component(action, target, timeout, times){
jQuery(function(){
var element = jQuery("#" + target).get(0);
var jelement = jQuery("#" + target);
var element = jelement.get(0);
var statement = "jQuery('#" + target + "').get(0).reload();";
element.reload = function (){
// Continue if times is Infinity or
@@ -119,6 +124,7 @@ function web2py_component(action, target, timeout, times){
web2py_ajax_page('get', action, null, target);} }; // reload
// Method to check timing limit
element.reload_check = function (){
if (jelement.hasClass('w2p_component_stop')) {return false;}
if (this.reload_counter == Infinity){return true;}
else {
if (!isNaN(this.reload_counter)){
@@ -0,0 +1,246 @@
{{extend 'layout.html'}}
{{block sectionclass}}debug{{end}}
<style type="text/css">
.prompt, #output {
width: 45em;
height: 1em;
border: 1px solid #CCCCCC;
font-size: 10pt;
margin: 0.5em;
padding: 0.5em;
padding-right: 0em;
overflow: auto;
wrap: hard;
}
#output {
height:150px;overflow:auto;
}
#toolbar {
margin-left: 0.5em;
padding-left: 0.5em;
}
#caret {
width: 2.5em;
margin-right: 0px;
padding-right: 0px;
border-right: 0px;
float: left;
}
#statement {
width: 43em;
margin-left: 1em;
padding-left: 0px;
border-left: 0px;
background-position: top right;
background-repeat: no-repeat;
}
.processing {
background-image: url("{{=URL('static','images/spinner.gif')}}");
}
#ajax-status {
font-weight: bold;
}
.message {
color: #8AD;
font-weight: bold;
font-style: italic;
}
.error {
color: #F44;
}
.username {
font-weight: bold;
}
</style>
<script src="{{=URL('static', 'js/autoscroll.js')}}"></script>
<div class="applist f60">
<div class="applist_inner">
<h2>{{=T("web2py online debugger")}}</h2>
{{if filename:}}
<h3>{{=T("Interaction at %s line %s") % (filename, lineno)}}</h3>
{{if exception:}}
<h3 class="exception">{{=T("Exception %s", exception['title'])}}</h3>
{{pass}}
<h5>{{=T("Code listing")}}</h5>
{{if lines:}}
<pre>{{=CODE('\n'.join([x[1] for x in sorted(lines.items(),key=lambda x: x[0])]),
language='python', link=None, counter=min(lines.keys()),
highlight_line=lineno, context_lines=10)}}</pre>
{{pass}}
<div class="help">
<ul>
<li>{{=T("Your application will be blocked until you click an action button (next, step, continue, etc.)")}}</li>
<li>{{=T("Your can inspect variables using the console bellow")}}</li>
</ul>
</div>
<h3>{{=T("Interactive console")}}</h3>
<textarea id="output" readonly="readonly">{{=data}}</textarea>
<form id="form" action="{{=URL(r=request,f='execute',args=app)}}" method="get">
<div id="shellwrapper">
<div id="caret">&gt;&gt;&gt;</div>
<div id="autoscroll" style="cursor:pointer;float:right;">autoscroll</div>
<div class="tooltip">
<textarea class="prompt" name="statement" id="statement"></textarea>
<span>{{=T("Type python statement in here and hit Return (Enter) to execute it.")}}</span>
</div>
</div>
</form>
{{elif request.env.get('wsgi_multiprocess') or not request.env.get('wsgi_multithread'):}}
<h3 class="not_paused">{{=T("Unsupported webserver working mode: %s", request.env.get('server_software', ''))}}</h3>
<div class="help">
<li><b>{{=T("WARNING:")}} </b>{{=T("This debugger may not work properly if you don't have a threaded webserver or you're using multiple daemon processes.")}}</li>
<li>{{=T("In development, use the default Rocket webserver that is currently supported by this debugger.")}}</li>
<li>{{=T("On production, you'll have to configure your webserver to use one process and multiple threads to use this debugger.")}}</li>
</ul>
</div>
{{#=BEAUTIFY(request.env)}}
{{else:}}
<h3 class="not_paused">{{=T("No Interaction yet")}}</h3>
<div class="help">
<ul>
<li>{{=T("You need to set up and reach a")}} {{=A(T("breakpoint"), _href=URL('breakpoints'))}} {{=T('to use the debugger!')}}</li>
<li>{{=T('To emulate a breakpoint programatically, write:')}}
{{=CODE("from gluon.debug import dbg\n"
"dbg.set_trace() # stop here!\n",
counter=None)}}</li>
<li>{{=T('Please')}} {{=A(T("refresh"), _href=URL('interact'))}} {{=T('this page to see if a breakpoint was hit and debug interaction is required.')}}</li>
</ul>
</div>
{{pass}}
</div>
</div>
<div class="sidebar fl60">
<div class="sidebar_inner controls">
<span class="pwdchange">
{{if filename:}}
{{=sp_button(URL('step'), T("step"))}}
{{=sp_button(URL('next'), T("next"))}}
{{=sp_button(URL('ret'), T("return"))}}
{{=sp_button(URL('cont'), T("continue"))}}
{{=sp_button(URL('stop'), T("stop"))}}
{{pass}}
{{=button(URL('breakpoints'), T("breakpoints"))}}
</span>
{{if exception:}}
<div class="box">
<h3>{{=T('Exception %(extype)s: %(exvalue)s', dict(extype=exception['extype'], exvalue=exception['exvalue']))}}</h3>
<div class="formfield">
{{=CODE((exception['request']), counter=None)}}
</div>
</div>
{{pass}}
<div class="box">
<h3>{{=T('Locals##debug')}}</h3>
<div class="formfield">
{{=BEAUTIFY(f_locals)}}
</div>
</div>
<div class="box">
<h3>{{=T('Globals##debug')}}</h3>
<div class="formfield">
{{=BEAUTIFY(f_globals)}}
</div>
</div>
</div>
</div>
<script type="text/javascript">
var bShellScrolling=0
jQuery(document).ready(function(){
jQuery('#statement').focus();
jQuery('#statement').keyup(function(event){
var t=jQuery(this),
s=t.val(),
o=jQuery('#output'),
RETURN = 38;
if(s=='\n') t.val('');
if(s.length>1 && s.substr(s.length-1,1)=='\n' && s.substr(s.length-2,1)!=':' &&
(s.indexOf(':\n ')<0 || s.substr(s.length-2,1)=='\n')) {
t.val('');
jQuery.post("{{=URL(r=request,f='execute',args=app)}}",
{statement:s},function(data){o.html(o.html()+data).attr('scrollTop',o.attr('scrollHeight'));});
} else { };
if(event.keyCode==RETURN){
var i=s.length
if(i==0){
var s=o.find('table:last pre:first').text();
bShellScrolling=o.find('table').length;
}else if(bShellScrolling){
var i=bShellScrolling
if(i<1){
return
}else{
i--
var s=o.find('table:nth-child('+(i)+') pre:first').text();
bShellScrolling=i
}
}else if(s.indexOf('\n')<0){
var oo=o.find('tr:first-child pre:contains("'+s+'")')
if(oo.length==0){
return
}else if(oo.length==1){
s=oo.text();
}else{
sVar=oo.text();
o.html(o.html()+'<dd>'+s+' ?</dd><dt>'+sVar+'</dt>').attr('scrollTop',o.attr('scrollHeight'))
return
}
}else{
//multistring expr
return;
}
// if(s.slice(s.length-1)=='\n'){
s=s.slice(0,s.length-1)
// }
t.val(s);
}
if(bShellScrolling && event.keyCode==40){
var i=bShellScrolling
i++
var s=o.find('table:nth-child('+i+') tr:first-child pre').text();
if(s){
s=s.slice(0,s.length-1)
t.val(s);
bShellScrolling=i
}else{
bShellScrolling=0
t.val('')
}
};
if(bShellScrolling && (event.keyCode==37 || event.keyCode==39)){
bShellScrolling=0;
};
if(event.keyCode==27){
bShellScrolling=0;
t.val('');
};
});
});
</script>
+2 -1
View File
@@ -134,7 +134,7 @@ jQuery(document).ready(function(){
<textarea style="width: auto; height:400px;direction:ltr;" rows="58" cols="100" -amy-enabled="true" id="body" name="data">{{=data}}</textarea>
<script>window.eamy = eamy;</script>
{{elif TEXT_EDITOR == 'codemirror':}}
<textarea style="width: auto; height:400px;direction:ltr;" id="body" name="data">{{=data}}</textarea>
<textarea style="width: auto; height:auto; direction:ltr;" id="body" name="data">{{=data}}</textarea>
<script>
function isFullScreen(instance) {
return /\bCodeMirror-fullscreen\b/.test(instance.getWrapperElement().className);
@@ -197,6 +197,7 @@ jQuery(document).ready(function(){
document.getElementById("body"),cm_opts);
var hlLine = editor.setLineClass(0, "activeline");
window.mirror = editor;
jQuery(function(){jQuery('.CodeMirror-scroll').css("height","auto").css("overflow-x","auto");});
</script>
{{elif TEXT_EDITOR == 'ace':}}
<div id="editor" style="height: 500px; width: auto; position: relative">{{=data}}</div>
@@ -9,6 +9,13 @@
body {
background: url('{{=URL('static','plugin_jqmobile/images/iphone.jpg')}}') no-repeat white;
}
#back {
z-index: 1000;
padding: 10px;
position: absolute;
top: 0;
right: 0;
}
iframe {
position: absolute;
margin-left: 320px;
@@ -35,6 +42,7 @@
</head>
<body>
<iframe src="{{=URL('default','index',vars=dict(is_mobile='true'))}}"></iframe>
<div id="back"><a href="{{=URL('default','index',vars=dict(is_mobile='false'))}}">Back</a></div>
<div id="about">
<h1><a href="http://web2py.com">web2py</a> plugin</h1>
<h2>for <a href="http://jquerymobile.com/">jQuery Mobile</a></h2>
+2 -2
View File
@@ -66,7 +66,7 @@
<div id="wrapper">
<textarea id="output" readonly="readonly">web2py Shell {{=request.env.web2py_version}}</textarea>
<form id="form" action="{{=URL(r=request,f='callback',args=app)}}" method="get">
<form id="form" action="{{=URL('callback',args=app)}}" method="get">
<div id="shellwrapper">
<div id="caret">&gt;&gt;&gt;</div>
<div class="tooltip">
@@ -103,7 +103,7 @@ jQuery(document).ready(function(){
if(s.length>1 && s.substr(s.length-1,1)=='\n' && s.substr(s.length-2,1)!=':' &&
(s.indexOf(':\n ')<0 || s.substr(s.length-2,1)=='\n')) {
t.val('');
jQuery.post("{{=URL(r=request,f='callback',args=app)}}",
jQuery.post("{{=URL('callback',args=app)}}",
{statement:s},function(data){o.html(o.html()+data).attr('scrollTop',o.attr('scrollHeight'));});
} else { };
if(event.keyCode==RETURN){
+1
View File
@@ -0,0 +1 @@
@@ -18,6 +18,3 @@ def flash():
def fade():
return dict()
+62 -45
View File
@@ -23,7 +23,7 @@ remote_addr = request.env.remote_addr
try:
hosts = (http_host, socket.gethostname(),
socket.gethostbyname(http_host),
'::1','127.0.0.1','::ffff:127.0.0.1')
'::1', '127.0.0.1', '::ffff:127.0.0.1')
except:
hosts = (http_host, )
@@ -32,10 +32,10 @@ if request.env.http_x_forwarded_for or request.is_https:
elif (remote_addr not in hosts) and (remote_addr != "127.0.0.1"):
raise HTTP(200, T('appadmin is disabled because insecure channel'))
if (request.application=='admin' and not session.authorized) or \
(request.application!='admin' and not gluon.fileutils.check_credentials(request)):
if (request.application == 'admin' and not session.authorized) or \
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
redirect(URL('admin', 'default', 'index',
vars=dict(send=URL(args=request.args,vars=request.vars))))
vars=dict(send=URL(args=request.args, vars=request.vars))))
ignore_rw = True
response.view = 'appadmin.html'
@@ -95,24 +95,23 @@ def get_query(request):
return None
def query_by_table_type(tablename,db,request=request):
keyed = hasattr(db[tablename],'_primarykey')
def query_by_table_type(tablename, db, request=request):
keyed = hasattr(db[tablename], '_primarykey')
if keyed:
firstkey = db[tablename][db[tablename]._primarykey[0]]
cond = '>0'
if firstkey.type in ['string', 'text']:
cond = '!=""'
qry = '%s.%s.%s%s' % (request.args[0], request.args[1], firstkey.name, cond)
qry = '%s.%s.%s%s' % (
request.args[0], request.args[1], firstkey.name, cond)
else:
qry = '%s.%s.id>0' % tuple(request.args[:2])
return qry
# ##########################################################
# ## list all databases and tables
# ###########################################################
def index():
return dict(databases=databases)
@@ -127,7 +126,7 @@ def insert():
form = SQLFORM(db[table], ignore_rw=ignore_rw)
if form.accepts(request.vars, session):
response.flash = T('new record inserted')
return dict(form=form,table=db[table])
return dict(form=form, table=db[table])
# ##########################################################
@@ -138,7 +137,8 @@ def insert():
def download():
import os
db = get_database(request)
return response.download(request,db)
return response.download(request, db)
def csv():
import gluon.contenttype
@@ -150,18 +150,19 @@ def csv():
return None
response.headers['Content-disposition'] = 'attachment; filename=%s_%s.csv'\
% tuple(request.vars.query.split('.')[:2])
return str(db(query,ignore_common_filters=True).select())
return str(db(query, ignore_common_filters=True).select())
def import_csv(table, file):
table.import_from_csv_file(file)
def select():
import re
db = get_database(request)
dbname = request.args[0]
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
if len(request.args)>1 and hasattr(db[request.args[1]],'_primarykey'):
if len(request.args) > 1 and hasattr(db[request.args[1]], '_primarykey'):
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>.+)')
if request.vars.query:
match = regex.match(request.vars.query)
@@ -192,21 +193,23 @@ def select():
session.last_query = request.vars.query
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
_name='query', _value=request.vars.query or '',
requires=IS_NOT_EMPTY(error_message=T("Cannot be empty")))), TR(T('Update:'),
requires=IS_NOT_EMPTY(
error_message=T("Cannot be empty")))), TR(T('Update:'),
INPUT(_name='update_check', _type='checkbox',
value=False), INPUT(_style='width:400px',
_name='update_fields', _value=request.vars.update_fields
or '')), TR(T('Delete:'), INPUT(_name='delete_check',
_class='delete', _type='checkbox', value=False), ''),
TR('', '', INPUT(_type='submit', _value=T('submit')))),
_action=URL(r=request,args=request.args))
_action=URL(r=request, args=request.args))
tb = None
if form.accepts(request.vars, formname=None):
regex = re.compile(request.args[0] + '\.(?P<table>\w+)\..+')
match = regex.match(form.vars.query.strip())
if match:
table = match.group('table')
try:
tb = None
nrows = db(query).count()
if form.vars.update_check and form.vars.update_fields:
db(query).update(**eval_in_global_env('dict(%s)'
@@ -217,21 +220,23 @@ def select():
response.flash = T('%s %%{row} deleted', nrows)
nrows = db(query).count()
if orderby:
rows = db(query,ignore_common_filters=True).select(limitby=(start, stop), orderby=eval_in_global_env(orderby))
rows = db(query, ignore_common_filters=True).select(limitby=(
start, stop), orderby=eval_in_global_env(orderby))
else:
rows = db(query,ignore_common_filters=True).select(limitby=(start, stop))
rows = db(query, ignore_common_filters=True).select(
limitby=(start, stop))
except Exception, e:
import traceback
tb = traceback.format_exc()
(rows, nrows) = ([], 0)
response.flash = DIV(T('Invalid Query'),PRE(str(e)))
response.flash = DIV(T('Invalid Query'), PRE(str(e)))
# begin handle upload csv
csv_table = table or request.vars.table
if csv_table:
formcsv = FORM(str(T('or import from csv file'))+" ",
INPUT(_type='file',_name='csvfile'),
INPUT(_type='hidden',_value=csv_table,_name='table'),
INPUT(_type='submit',_value=T('import')))
formcsv = FORM(str(T('or import from csv file')) + " ",
INPUT(_type='file', _name='csvfile'),
INPUT(_type='hidden', _value=csv_table, _name='table'),
INPUT(_type='submit', _value=T('import')))
else:
formcsv = None
if formcsv and formcsv.process().accepted:
@@ -240,7 +245,7 @@ def select():
request.vars.csvfile.file)
response.flash = T('data uploaded')
except Exception, e:
response.flash = DIV(T('unable to parse csv file'),PRE(str(e)))
response.flash = DIV(T('unable to parse csv file'), PRE(str(e)))
# end handle upload csv
return dict(
@@ -251,8 +256,8 @@ def select():
nrows=nrows,
rows=rows,
query=request.vars.query,
formcsv = formcsv,
tb = tb,
formcsv=formcsv,
tb=tb,
)
@@ -263,14 +268,16 @@ def select():
def update():
(db, table) = get_table(request)
keyed = hasattr(db[table],'_primarykey')
keyed = hasattr(db[table], '_primarykey')
record = None
if keyed:
key = [f for f in request.vars if f in db[table]._primarykey]
if key:
record = db(db[table][key[0]] == request.vars[key[0]], ignore_common_filters=True).select().first()
record = db(db[table][key[0]] == request.vars[key[
0]], ignore_common_filters=True).select().first()
else:
record = db(db[table].id == request.args(2),ignore_common_filters=True).select().first()
record = db(db[table].id == request.args(
2), ignore_common_filters=True).select().first()
if not record:
qry = query_by_table_type(table, db)
@@ -280,9 +287,10 @@ def update():
if keyed:
for k in db[table]._primarykey:
db[table][k].writable=False
db[table][k].writable = False
form = SQLFORM(db[table], record, deletable=True, delete_label=T('Check to delete'),
form = SQLFORM(
db[table], record, deletable=True, delete_label=T('Check to delete'),
ignore_rw=ignore_rw and not keyed,
linkto=URL('select',
args=request.args[:1]), upload=URL(r=request,
@@ -293,7 +301,7 @@ def update():
qry = query_by_table_type(table, db)
redirect(URL('select', args=request.args[:1],
vars=dict(query=qry)))
return dict(form=form,table=db[table])
return dict(form=form, table=db[table])
# ##########################################################
@@ -304,11 +312,15 @@ def update():
def state():
return dict()
def ccache():
form = FORM(
P(TAG.BUTTON(T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")),
P(TAG.BUTTON(T("Clear RAM"), _type="submit", _name="ram", _value="ram")),
P(TAG.BUTTON(T("Clear DISK"), _type="submit", _name="disk", _value="disk")),
P(TAG.BUTTON(
T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")),
P(TAG.BUTTON(
T("Clear RAM"), _type="submit", _name="ram", _value="ram")),
P(TAG.BUTTON(
T("Clear DISK"), _type="submit", _name="disk", _value="disk")),
)
if form.accepts(request.vars, session):
@@ -332,11 +344,16 @@ def ccache():
redirect(URL(r=request))
try:
from guppy import hpy; hp=hpy()
from guppy import hpy
hp = hpy()
except ImportError:
hp = False
import shelve, os, copy, time, math
import shelve
import os
import copy
import time
import math
from gluon import portalocker
ram = {
@@ -379,11 +396,13 @@ def ccache():
if value[0] < ram['oldest']:
ram['oldest'] = value[0]
ram['keys'].append((key, GetInHMS(time.time() - value[0])))
locker = open(os.path.join(request.folder,
'cache/cache.lock'), 'a')
folder = os.path.join(request.folder,'cache')
if not os.path.exists(folder):
os.mkdir(folder)
locker = open(os.path.join(folder, 'cache.lock'), 'a')
portalocker.lock(locker, portalocker.LOCK_EX)
disk_storage = shelve.open(os.path.join(request.folder, 'cache/cache.shelve'))
disk_storage = shelve.open(
os.path.join(folder, 'cache.shelve'))
try:
for key, value in disk_storage.items():
if isinstance(value, dict):
@@ -414,7 +433,8 @@ def ccache():
total['misses'] = ram['misses'] + disk['misses']
total['keys'] = ram['keys'] + disk['keys']
try:
total['ratio'] = total['hits'] * 100 / (total['hits'] + total['misses'])
total['ratio'] = total['hits'] * 100 / (total['hits'] +
total['misses'])
except (KeyError, ZeroDivisionError):
total['ratio'] = 0
@@ -440,6 +460,3 @@ def ccache():
return dict(form=form, total=total,
ram=ram, disk=disk, object_stats=hp != False)
@@ -1,25 +1,24 @@
import time
def cache_in_ram():
"""cache the output of the lambda function in ram"""
t = cache.ram('time', lambda : time.ctime(), time_expire=5)
t = cache.ram('time', lambda: time.ctime(), time_expire=5)
return dict(time=t, link=A('click to reload', _href=URL(r=request)))
def cache_on_disk():
"""cache the output of the lambda function on disk"""
t = cache.disk('time', lambda : time.ctime(), time_expire=5)
t = cache.disk('time', lambda: time.ctime(), time_expire=5)
return dict(time=t, link=A('click to reload', _href=URL(r=request)))
def cache_in_ram_and_disk():
"""cache the output of the lambda function on disk and in ram"""
t = cache.ram('time', lambda : cache.disk('time', lambda : \
t = cache.ram('time', lambda: cache.disk('time', lambda:
time.ctime(), time_expire=5), time_expire=5)
return dict(time=t, link=A('click to reload', _href=URL(r=request)))
@@ -47,5 +46,3 @@ def cache_controller_and_view():
t = time.ctime()
d = dict(time=t, link=A('click to reload', _href=URL(r=request)))
return response.render(d)
+19 -4
View File
@@ -9,68 +9,83 @@ response.description = T('web2py Web Framework')
session.forget()
cache_expire = not request.is_local and 300 or 0
@cache('index', time_expire=cache_expire)
def index():
return response.render()
@cache('what', time_expire=cache_expire)
def what():
import urllib;
import urllib
try:
images = XML(urllib.urlopen('http://web2py.com/poweredby/default/images').read())
images = XML(urllib.urlopen(
'http://web2py.com/poweredby/default/images').read())
except:
images = []
return response.render(images=images)
@cache('download', time_expire=cache_expire)
def download():
return response.render()
@cache('who', time_expire=cache_expire)
def who():
return response.render()
@cache('support', time_expire=cache_expire)
def support():
return response.render()
@cache('documentation', time_expire=cache_expire)
def documentation():
return response.render()
@cache('usergroups', time_expire=cache_expire)
def usergroups():
return response.render()
def contact():
redirect(URL('default','usergroups'))
redirect(URL('default', 'usergroups'))
@cache('videos', time_expire=cache_expire)
def videos():
return response.render()
def security():
redirect('http://www.web2py.com/book/default/chapter/01#security')
def api():
redirect('http://web2py.com/book/default/chapter/04#API')
@cache('license', time_expire=cache_expire)
def license():
import os
filename = os.path.join(request.env.gluon_parent, 'LICENSE')
return response.render(dict(license=MARKMIN(read_file(filename))))
def version():
return 'Version %s.%s.%s (%s) %s' % request.env.web2py_version
@cache('examples', time_expire=cache_expire)
def examples():
return response.render()
@cache('changelog', time_expire=cache_expire)
def changelog():
import os
filename = os.path.join(request.env.gluon_parent, 'CHANGELOG')
return response.render(dict(changelog=MARKMIN(read_file(filename))))
@@ -1,6 +1,3 @@
def form():
""" a simple entry form with various types of objects """
@@ -23,6 +20,3 @@ def form():
else:
response.flash = 'please fill the form'
return dict(form=form, vars=form.vars)
@@ -1,4 +1,3 @@
session.forget()
response.menu = [['home', False, '/%s/default/index'
@@ -77,6 +76,3 @@ def vars():
doc=doc,
attributes=attributes,
)
@@ -20,6 +20,3 @@ def basic():
['basic', True, URL('basic')]]
response.flash = 'you clicked on basic'
return dict(message='you clicked on basic')
@@ -1,6 +1,3 @@
def counter():
""" every time you reload, it increases the session.counter """
@@ -8,6 +5,3 @@ def counter():
session.counter = 0
session.counter += 1
return dict(counter=session.counter)
@@ -1,3 +1,4 @@
def hello1():
""" simple page without template """
@@ -99,12 +100,11 @@ def rss_aggregator():
pubDate=datetime.datetime.now()) for entry in
d.entries])
response.headers['Content-Type'] = 'application/rss+xml'
return rss2.dumps(rss)
return rss.to_xml(encoding='utf-8')
def ajaxwiki():
default="""
default = """
# section
## subsection
@@ -129,12 +129,12 @@ Quoted text
3 | 0 | 0
---------
"""
form = FORM(TEXTAREA(_id='text',_name='text',value=default),
form = FORM(TEXTAREA(_id='text', _name='text', value=default),
INPUT(_type='button',
_value='markmin',
_onclick="ajax('ajaxwiki_onclick',['text'],'html')"))
return dict(form=form, html=DIV(_id='html'))
def ajaxwiki_onclick():
return MARKMIN(request.vars.text).xml()
@@ -1,10 +1,11 @@
from gluon.contrib.spreadsheet import Sheet
def callback():
return cache.ram('sheet1',lambda:None,None).process(request)
return cache.ram('sheet1', lambda: None, None).process(request)
def index():
sheet = cache.ram('sheet1',lambda:Sheet(10,10,URL('callback')),0)
sheet = cache.ram('sheet1', lambda: Sheet(10, 10, URL('callback')), 0)
#sheet.cell('r0c3',value='=r0c0+r0c1+r0c2',readonly=True)
return dict(sheet=sheet)
@@ -1,6 +1,3 @@
def variables():
return dict(a=10, b=20)
@@ -31,6 +28,3 @@ def xml():
def beautify():
return dict(message=BEAUTIFY(request))
+19 -24
View File
@@ -1,49 +1,44 @@
def group_feed_reader(group,mode='div',counter='5'):
def group_feed_reader(group, mode='div', counter='5'):
"""parse group feeds"""
url = "http://groups.google.com/group/%s/feed/rss_v2_0_topics.xml?num=%s" %\
(group,counter)
(group, counter)
from gluon.contrib import feedparser
g = feedparser.parse(url)
if mode == 'div':
html = XML(TAG.BLOCKQUOTE(UL(*[LI(A(entry['title']+' - ' +\
entry['author'][entry['author'].rfind('('):],\
_href=entry['link'],_target='_blank'))\
for entry in g['entries'] ]),\
_class="boxInfo",\
html = XML(TAG.BLOCKQUOTE(UL(*[LI(A(entry['title'] + ' - ' +
entry['author'][
entry['author'].rfind('('):],
_href=entry['link'], _target='_blank'))
for entry in g['entries']]),
_class="boxInfo",
_style="padding-bottom:5px;"))
else:
html = XML(UL(*[LI(A(entry['title']+' - ' +\
entry['author'][entry['author'].rfind('('):],\
_href=entry['link'],_target='_blank'))\
for entry in g['entries'] ]))
html = XML(UL(*[LI(A(entry['title'] + ' - ' +
entry['author'][entry['author'].rfind('('):],
_href=entry['link'], _target='_blank'))
for entry in g['entries']]))
return html
def code_feed_reader(project,mode='div'):
def code_feed_reader(project, mode='div'):
"""parse code feeds"""
url = "http://code.google.com/feeds/p/%s/hgchanges/basic" % project
from gluon.contrib import feedparser
g = feedparser.parse(url)
if mode == 'div':
html = XML(DIV(UL(*[LI(A(entry['title'],_href=entry['link'],\
_target='_blank'))\
for entry in g['entries'][0:5]]),\
_class="boxInfo",\
html = XML(DIV(UL(*[LI(A(entry['title'], _href=entry['link'],
_target='_blank'))
for entry in g['entries'][0:5]]),
_class="boxInfo",
_style="padding-bottom:5px;"))
else:
html = XML(UL(*[LI(A(entry['title'],_href=entry['link'],\
_target='_blank'))\
html = XML(UL(*[LI(A(entry['title'], _href=entry['link'],
_target='_blank'))
for entry in g['entries'][0:5]]))
return html
+16 -15
View File
@@ -2,18 +2,19 @@ import gluon.template
markmin_dict = dict(
code_python=lambda code: str(CODE(code)),
template=lambda \
code:gluon.template.render(code,context=globals()),
sup=lambda \
code:'<sup style="font-size:0.5em;">%s</sup>'%code,
br=lambda n:'<br>'*int(n),
groupdates=lambda group:group_feed_reader(group),
)
template=lambda
code: gluon.template.render(code, context=globals()),
sup=lambda
code: '<sup style="font-size:0.5em;">%s</sup>' % code,
br=lambda n: '<br>' * int(n),
groupdates=lambda group: group_feed_reader(group),
)
def get_content(b=None,\
c=request.controller,\
f=request.function,\
l='en',\
def get_content(b=None,
c=request.controller,
f=request.function,
l='en',
format='markmin'):
"""Gets and renders the file in
<app>/private/content/<lang>/<controller>/<function>/<block>.<format>
@@ -21,20 +22,20 @@ def get_content(b=None,\
def openfile():
import os
path = os.path.join(request.folder,'private','content',l,c,f,b+'.'+format)
path = os.path.join(
request.folder, 'private', 'content', l, c, f, b + '.' + format)
return open(path)
try:
openedfile = openfile()
except Exception, IOError:
l='en'
l = 'en'
openedfile = openfile()
if format == 'markmin':
html = MARKMIN(str(T(openedfile.read())),markmin_dict)
html = MARKMIN(str(T(openedfile.read())), markmin_dict)
else:
html = str(T(openedfile.read()))
openedfile.close()
return html
+9 -9
View File
@@ -1,17 +1,19 @@
# -*- coding: utf-8 -*-
response.menu = [
(T('Home'),False,URL('default','index')),
(T('About'),False,URL('default','what')),
(T('Download'),False,URL('default','download')),
(T('Docs & Resources'),False,URL('default','documentation')),
(T('Support'),False,URL('default','support')),
(T('Contributors'),False,URL('default','who'))]
(T('Home'), False, URL('default', 'index')),
(T('About'), False, URL('default', 'what')),
(T('Download'), False, URL('default', 'download')),
(T('Docs & Resources'), False, URL('default', 'documentation')),
(T('Support'), False, URL('default', 'support')),
(T('Contributors'), False, URL('default', 'who'))]
#########################################################################
## Changes the menu active item
#########################################################################
def toggle_menuclass(cssclass='pressed',menuid='headermenu'):
def toggle_menuclass(cssclass='pressed', menuid='headermenu'):
"""This function changes the menu class to put pressed appearance"""
positions = dict(
@@ -23,7 +25,6 @@ def toggle_menuclass(cssclass='pressed',menuid='headermenu'):
documentation='-520px -115px'
)
if request.function in positions.keys():
jscript = """
<script>
@@ -42,4 +43,3 @@ def toggle_menuclass(cssclass='pressed',menuid='headermenu'):
return XML(jscript)
else:
return ''
@@ -7,6 +7,7 @@
- [[User Voice http://web2py.uservoice.com/ popup]]
#### Learning and Demos
- [[Intro video http://www.youtube.com/watch?v=BXzqmHx6edY]] and [[code examples https://github.com/mjhea0/web2py]]
- [[Killer Web Development Tutorial http://killer-web-development.com/]]
- [[Admin Demo http://www.web2py.com/demo_admin popup]] (web-based IDE)
- [[Welcome App Demo http://www.web2py.com/welcome]] (scaffolding application)
+6 -2
View File
@@ -61,7 +61,7 @@ input[type=text],input[type=password],select{width:300px; margin-right:5px}
border-top:1px #DEDEDE solid;
}
.header {
// background:<fill here for header image>;
/* background:<fill here for header image>; */
}
@@ -115,6 +115,10 @@ div.flash {
z-index:2000;
}
div.flash #closeflash{color:inherit; float:right; margin-left:15px;}
.ie-lte7 div.flash #closeflash
{color:expression(this.parentNode.currentStyle['color']);float:none;position:absolute;right:4px;}
div.flash:hover { opacity:0.25; }
div.error_wrapper {display:block}
@@ -182,7 +186,7 @@ div.error {
* will look better with the declarations below
* if needed to remove base.css consider keeping these following lines in some css file.
*/
// .web2py_table {border:1px solid #ccc}
/* .web2py_table {border:1px solid #ccc} */
.web2py_paginator {}
.web2py_grid {width:100%}
.web2py_grid table {width:100%}
+2 -2
View File
@@ -1,2 +1,2 @@
/*! jQuery v@1.8.0 jquery.com | jquery.org/license */
(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bX(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bV.length;while(e--){b=bV[e]+c;if(b in a)return b}return d}function bY(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function bZ(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bY(c)&&(e[f]=p._data(c,"olddisplay",cb(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b$(a,b,c){var d=bO.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function b_(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bU[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bU[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bU[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bU[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bU[e]+"Width"))||0));return f}function ca(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bP.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+b_(a,b,c||(f?"border":"content"),e)+"px"}function cb(a){if(bR[a])return bR[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bR[a]=c,c}function ch(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||cd.test(a)?d(a,e):ch(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ch(a+"["+e+"]",b[e],c,d);else d(a,b)}function cy(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cz(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cu;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cz(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cz(a,c,d,e,"*",g)),h}function cA(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((fLine truncated
/*! jQuery v1.8.3 jquery.com | jquery.org/license */
(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r<i;r++)v.event.add(t,n,u[n][r])}o.data&&(o.data=v.extend({},o.data))}function Ot(e,t){var n;if(t.nodeType!==1)return;t.clearAttributes&&t.clearAttributes(),t.mergeAttributes&&t.mergeAttributes(e),n=t.nodeName.toLowerCase(),n==="object"?(t.parentNode&&(t.outerHTML=e.outerHTML),v.support.html5Clone&&e.innerHTML&&!v.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):n==="input"&&Et.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):n==="option"?t.selected=e.defaultSelected:n==="input"||n==="textarea"?t.defaultValue=e.defaultValue:n==="script"&&t.text!==e.text&&(t.text=e.text),t.removeAttribute(v.expando)}function Mt(e){return typeof e.getElementsByTagName!="undefined"?e.getElementsByTagName("*"):typeof e.querySelectorAll!="undefined"?e.querySelectorAll("*"):[]}function _t(e){Et.test(e.type)&&(e.defaultChecked=e.checked)}function Qt(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Jt.length;while(i--){t=Jt[i]+n;if(t in e)return t}return r}function Gt(e,t){return e=t||e,v.css(e,"display")==="none"||!v.contains(e.ownerDocument,e)}function Yt(e,t){var n,r,i=[],s=0,o=e.length;for(;s<o;s++){n=e[s];if(!n.style)continue;i[s]=v._data(n,"olddisplay"),t?(!i[s]&&n.style.display==="none"&&(n.style.display=""),n.style.display===""&&Gt(n)&&(i[s]=v._data(n,"olddisplay",nn(n.nodeName)))):(r=Dt(n,"display"),!i[s]&&r!=="none"&&v._data(n,"olddisplay",r))}for(s=0;s<o;s++){n=e[s];if(!n.style)continue;if(!t||n.style.display==="none"||n.style.display==="")n.style.display=t?i[s]||"":"none"}return e}function Zt(e,t,n){var r=Rt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function en(e,t,n,r){var i=n===(r?"border":"content")?4:t==="width"?1:0,s=0;for(;i<4;i+=2)n==="margin"&&(s+=v.css(e,n+$t[i],!0)),r?(n==="content"&&(s-=parseFloat(Dt(e,"padding"+$t[i]))||0),n!=="margin"&&(s-=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0)):(s+=parseFloat(Dt(e,"padding"+$t[i]))||0,n!=="padding"&&(s+=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0));return s}function tn(e,t,n){var r=t==="width"?e.offsetWidth:e.offsetHeight,i=!0,s=v.support.boxSizing&&v.css(e,"boxSizing")==="border-box";if(r<=0||r==null){r=Dt(e,t);if(r<0||r==null)r=e.style[t];if(Ut.test(r))return r;i=s&&(v.support.boxSizingReliable||r===e.style[t]),r=parseFloat(r)||0}return r+en(e,t,n||(s?"border":"content"),i)+"px"}function nn(e){if(Wt[e])return Wt[e];var t=v("<"+e+">").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write("<!doctype html><html><body>"),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u<a;u++)r=o[u],s=/^\+/.test(r),s&&(r=r.substr(1)||"*"),i=e[r]=e[r]||[],i[s?"unshift":"push"](n)}}function kn(e,n,r,i,s,o){s=s||n.dataTypes[0],o=o||{},o[s]=!0;var u,a=e[s],f=0,l=a?a.length:0,c=e===Sn;for(;f<l&&(c||!u);f++)u=a[f](n,r,i),typeof u=="string"&&(!c||o[u]?u=t:(n.dataTypes.unshift(u),u=kn(e,n,r,i,u,o)));return(c||!u)&&!o["*"]&&(u=kn(e,n,r,i,"*",o)),u}function Ln(e,n){var r,i,s=v.ajaxSettings.flatOptions||{};for(r in n)n[r]Line truncated
@@ -1,4 +1,4 @@
/* Modernizr 2.0.6 (Custom Build) | MIT & BSD
* Build: http://www.modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-iepp-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
* Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-flexboxlegacy-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
*/
;window.Modernizr=function(a,b,c){function H(){e.input=function(a){for(var b=0,c=a.length;b<c;b++)t[a[b]]=a[b]in l;return t}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)l.setAttribute("type",f=a[d]),e=l.type!=="text",e&&(l.value=m,l.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&l.style.WebkitAppearance!==c?(g.appendChild(l),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(l,null).WebkitAppearance!=="textfield"&&l.offsetHeight!==0,g.removeChild(l)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=l.checkValidity&&l.checkValidity()===!1:/^color$/.test(f)?(g.appendChild(l),g.offsetWidth,e=l.value!=m,g.removeChild(l)):e=l.value!=m)),s[a[d]]=!!e;return s}("search tel url email datetime date month week time datetime-local number range color".split(" "))}function F(a,b){var c=a.charAt(0).toUpperCase()+a.substr(1),d=(a+" "+p.join(c+" ")+c).split(" ");return E(d,b)}function E(a,b){for(var d in a)if(k[a[d]]!==c)return b=="pfx"?a[d]:!0;return!1}function D(a,b){return!!~(""+a).indexOf(b)}function C(a,b){return typeof a===b}function B(a,b){return A(o.join(a+";")+(b||""))}function A(a){k.cssText=a}var d="2.0.6",e={},f=!0,g=b.documentElement,h=b.head||b.getElementsByTagName("head")[0],i="modernizr",j=b.createElement(i),k=j.style,l=b.createElement("input"),m=":)",n=Object.prototype.toString,o=" -webkit- -moz- -o- -ms- -khtml- ".split(" "),p="Webkit Moz O ms Khtml".split(" "),q={svg:"http://www.w3.org/2000/svg"},r={},s={},t={},u=[],v=function(a,c,d,e){var f,h,j,k=b.createElement("div");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:i+(d+1),k.appendChild(j);f=["&shy;","<style>",a,"</style>"].join(""),k.id=i,k.innerHTML+=f,g.appendChild(k),h=c(k,a),k.parentNode.removeChild(k);return!!h},w=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=C(e[d],"function"),C(e[d],c)||(e[d]=c),e.removeAttribute(d))),e=null;return f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),x,y={}.hasOwnProperty,z;!C(y,c)&&!C(y.call,c)?z=function(a,b){return y.call(a,b)}:z=function(a,b){return b in a&&C(a.constructor.prototype[b],c)};var G=function(c,d){var f=c.join(""),g=d.length;v(f,function(c,d){var f=b.styleSheets[b.styleSheets.length-1],h=f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"",i=c.childNodes,j={};while(g--)j[i[g].id]=i[g];e.touch="ontouchstart"in a||j.touch.offsetTop===9,e.csstransforms3d=j.csstransforms3d.offsetLeft===9,e.generatedcontent=j.generatedcontent.offsetHeight>=1,e.fontface=/src/i.test(h)&&h.indexOf(d.split(" ")[0])===0},g,d)}(['@font-face {font-family:"font";src:url("https://")}',["@media (",o.join("touch-enabled),("),i,")","{#touch{top:9px;position:absolute}}"].join(""),["@media (",o.join("transform-3d),("),i,")","{#csstransforms3d{left:9px;position:absolute}}"].join(""),['#generatedcontent:after{content:"',m,'";visibility:hidden}'].join("")],["fontface","touch","csstransforms3d","generatedcontent"]);r.flexbox=function(){function c(a,b,c,d){a.style.cssText=o.join(b+":"+c+";")+(d||"")}function a(a,b,c,d){b+=":",a.style.cssText=(b+o.join(c+";"+b)).slice(0,-b.length)+(d||"")}var d=b.createElement("div"),e=b.createElement("div");a(d,"display","box","width:42px;padding:0;"),c(e,"box-flex","1","width:10px;"),d.appendChild(e),g.appendChild(d);var f=e.offsetWidth===42;d.removeChild(e),g.removeChild(d);return f},r.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},r.canvastext=function(){return!!e.canvas&&!!C(b.createElement("canvas").getContext("2d").fillText,"function")},r.webgl=function(){return!!a.WebGLRenderingContext},r.touch=function(){return e.touch},r.geolocation=function(){return!!navigator.geolocation},r.postmessage=function(){return!!a.postMessage},r.websqldatabase=function(){var b=!!a.openDatabase;return b},r.indexedDB=function(){for(var b=-1,c=p.length;++b<c;)if(a[p[b].toLowerCase()+"IndexedDB"])return!0;return!!a.indexedDB},r.hashchange=function(){return w("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},r.history=function(){return!!a.history&&!!history.pushState},r.draganddrop=function(){return w("dragstart")&&w("drop")},r.websockets=function(){for(var b=-1,c=p.length;++b<c;)if(a[p[b]+"WebSocket"])return!0;return"WebSocket"in a},r.rgba=function(){A("background-color:rgba(150,255,150,.5)");return D(k.backgroundColor,"rgba")},r.hsla=function(){A("background-color:hsla(120,40%,100%,.5)");return D(k.backgroundColor,"rgba")||D(k.backgroundColor,"hsla")},r.multiplebgs=function(){A("background:url(https://),url(https://),red url(https://)");return/(url\s*\(.*?){3}/.test(k.background)},r.backgroundsize=function(){return F("backgroundSize")},r.borderimage=function(){return F("borderImage")},r.borderradiLine truncated
;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)u[c[d]]=c[d]in k;return u.list&&(u.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),u}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)k.setAttribute("type",f=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&k.style.WebkitAppearance!==c?(g.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,g.removeChild(k)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=k.checkValidity&&k.checkValidity()===!1:e=k.value!=l)),t[a[d]]=!!e;return t}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m={}.toString,n=" -webkit- -moz- -o- -ms- ".split(" "),o="Webkit Moz O ms",p=o.split(" "),q=o.toLowerCase().split(" "),r={svg:"http://www.w3.org/2000/svg"},s={},t={},u={},v=[],w=v.slice,x,y=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.flexboxlegacy=function(){return J("boxDirection")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){retuLine truncated
+10 -4
View File
@@ -55,7 +55,7 @@ function web2py_event_handlers() {
jQuery(function() {
var flash = jQuery('.flash');
flash.hide();
if(flash.html()) flash.append('<span style="float:right;">&times;</span>').slideDown();
if(flash.html()) flash.append('<span id="closeflash">&times;</span>').slideDown();
web2py_ajax_init(document);
web2py_event_handlers();
});
@@ -102,15 +102,20 @@ function web2py_ajax_page(method, action, data, target) {
web2py_ajax_init('#'+target);
if(command)
eval(decodeURIComponent(command));
if(flash)
jQuery('.flash').html(decodeURIComponent(flash)).slideDown();
if(flash) {
jQuery('.flash')
.html(decodeURIComponent(flash))
.append('<span id="closeflash">&times;</span>')
.slideDown();
}
}
});
}
function web2py_component(action, target, timeout, times){
jQuery(function(){
var element = jQuery("#" + target).get(0);
var jelement = jQuery("#" + target);
var element = jelement.get(0);
var statement = "jQuery('#" + target + "').get(0).reload();";
element.reload = function (){
// Continue if times is Infinity or
@@ -119,6 +124,7 @@ function web2py_component(action, target, timeout, times){
web2py_ajax_page('get', action, null, target);} }; // reload
// Method to check timing limit
element.reload_check = function (){
if (jelement.hasClass('w2p_component_stop')) {return false;}
if (this.reload_counter == Infinity){return true;}
else {
if (!isNaN(this.reload_counter)){
@@ -29,6 +29,7 @@
</li><li>Alvaro Justen (dynamical translations)
</li><li>Anders Roos (file locking)
</li><li>Andrew Willimott (documentation, TeraData support)
</li><li>Andriy Kornatskyy (benchmarks and profiling)
</li><li>Angelo Compagnucci (mobile devices)
</li><li>Anthony Bastardi (book, poweredby site, multiple contributions)
</li><li>Arun K. Rajeevan (plugin_wiki)
@@ -0,0 +1,9 @@
{{extend 'layout.html'}}
<h2>form.vars</h2>
<pre>{{=vars}}</pre>
<h2>form</h2>
{{=form}}
+1 -15
View File
@@ -1,15 +1 @@
{{
###
# response._vars contains the dictionary returned by thecontroller action
###
try:
from gluon.serializers import xml
response.write(xml(response._vars), escape=False)
response.headers['Content-Type'] = 'text/xml'
except (TypeError, ValueError):
raise HTTP(405, 'XML serialization error')
except ImportError:
raise HTTP(405, 'XML not available')
except:
raise HTTP(405, 'XML error')
}}
{{from gluon.serializers import xml}}{{=XML(xml(response._vars,quote=False))}}
@@ -0,0 +1,3 @@
{{extend 'layout.html'}}
{{=toolbar}}
+1
View File
@@ -0,0 +1 @@
+62 -45
View File
@@ -23,7 +23,7 @@ remote_addr = request.env.remote_addr
try:
hosts = (http_host, socket.gethostname(),
socket.gethostbyname(http_host),
'::1','127.0.0.1','::ffff:127.0.0.1')
'::1', '127.0.0.1', '::ffff:127.0.0.1')
except:
hosts = (http_host, )
@@ -32,10 +32,10 @@ if request.env.http_x_forwarded_for or request.is_https:
elif (remote_addr not in hosts) and (remote_addr != "127.0.0.1"):
raise HTTP(200, T('appadmin is disabled because insecure channel'))
if (request.application=='admin' and not session.authorized) or \
(request.application!='admin' and not gluon.fileutils.check_credentials(request)):
if (request.application == 'admin' and not session.authorized) or \
(request.application != 'admin' and not gluon.fileutils.check_credentials(request)):
redirect(URL('admin', 'default', 'index',
vars=dict(send=URL(args=request.args,vars=request.vars))))
vars=dict(send=URL(args=request.args, vars=request.vars))))
ignore_rw = True
response.view = 'appadmin.html'
@@ -95,24 +95,23 @@ def get_query(request):
return None
def query_by_table_type(tablename,db,request=request):
keyed = hasattr(db[tablename],'_primarykey')
def query_by_table_type(tablename, db, request=request):
keyed = hasattr(db[tablename], '_primarykey')
if keyed:
firstkey = db[tablename][db[tablename]._primarykey[0]]
cond = '>0'
if firstkey.type in ['string', 'text']:
cond = '!=""'
qry = '%s.%s.%s%s' % (request.args[0], request.args[1], firstkey.name, cond)
qry = '%s.%s.%s%s' % (
request.args[0], request.args[1], firstkey.name, cond)
else:
qry = '%s.%s.id>0' % tuple(request.args[:2])
return qry
# ##########################################################
# ## list all databases and tables
# ###########################################################
def index():
return dict(databases=databases)
@@ -127,7 +126,7 @@ def insert():
form = SQLFORM(db[table], ignore_rw=ignore_rw)
if form.accepts(request.vars, session):
response.flash = T('new record inserted')
return dict(form=form,table=db[table])
return dict(form=form, table=db[table])
# ##########################################################
@@ -138,7 +137,8 @@ def insert():
def download():
import os
db = get_database(request)
return response.download(request,db)
return response.download(request, db)
def csv():
import gluon.contenttype
@@ -150,18 +150,19 @@ def csv():
return None
response.headers['Content-disposition'] = 'attachment; filename=%s_%s.csv'\
% tuple(request.vars.query.split('.')[:2])
return str(db(query,ignore_common_filters=True).select())
return str(db(query, ignore_common_filters=True).select())
def import_csv(table, file):
table.import_from_csv_file(file)
def select():
import re
db = get_database(request)
dbname = request.args[0]
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>\d+)')
if len(request.args)>1 and hasattr(db[request.args[1]],'_primarykey'):
if len(request.args) > 1 and hasattr(db[request.args[1]], '_primarykey'):
regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>.+)')
if request.vars.query:
match = regex.match(request.vars.query)
@@ -192,21 +193,23 @@ def select():
session.last_query = request.vars.query
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
_name='query', _value=request.vars.query or '',
requires=IS_NOT_EMPTY(error_message=T("Cannot be empty")))), TR(T('Update:'),
requires=IS_NOT_EMPTY(
error_message=T("Cannot be empty")))), TR(T('Update:'),
INPUT(_name='update_check', _type='checkbox',
value=False), INPUT(_style='width:400px',
_name='update_fields', _value=request.vars.update_fields
or '')), TR(T('Delete:'), INPUT(_name='delete_check',
_class='delete', _type='checkbox', value=False), ''),
TR('', '', INPUT(_type='submit', _value=T('submit')))),
_action=URL(r=request,args=request.args))
_action=URL(r=request, args=request.args))
tb = None
if form.accepts(request.vars, formname=None):
regex = re.compile(request.args[0] + '\.(?P<table>\w+)\..+')
match = regex.match(form.vars.query.strip())
if match:
table = match.group('table')
try:
tb = None
nrows = db(query).count()
if form.vars.update_check and form.vars.update_fields:
db(query).update(**eval_in_global_env('dict(%s)'
@@ -217,21 +220,23 @@ def select():
response.flash = T('%s %%{row} deleted', nrows)
nrows = db(query).count()
if orderby:
rows = db(query,ignore_common_filters=True).select(limitby=(start, stop), orderby=eval_in_global_env(orderby))
rows = db(query, ignore_common_filters=True).select(limitby=(
start, stop), orderby=eval_in_global_env(orderby))
else:
rows = db(query,ignore_common_filters=True).select(limitby=(start, stop))
rows = db(query, ignore_common_filters=True).select(
limitby=(start, stop))
except Exception, e:
import traceback
tb = traceback.format_exc()
(rows, nrows) = ([], 0)
response.flash = DIV(T('Invalid Query'),PRE(str(e)))
response.flash = DIV(T('Invalid Query'), PRE(str(e)))
# begin handle upload csv
csv_table = table or request.vars.table
if csv_table:
formcsv = FORM(str(T('or import from csv file'))+" ",
INPUT(_type='file',_name='csvfile'),
INPUT(_type='hidden',_value=csv_table,_name='table'),
INPUT(_type='submit',_value=T('import')))
formcsv = FORM(str(T('or import from csv file')) + " ",
INPUT(_type='file', _name='csvfile'),
INPUT(_type='hidden', _value=csv_table, _name='table'),
INPUT(_type='submit', _value=T('import')))
else:
formcsv = None
if formcsv and formcsv.process().accepted:
@@ -240,7 +245,7 @@ def select():
request.vars.csvfile.file)
response.flash = T('data uploaded')
except Exception, e:
response.flash = DIV(T('unable to parse csv file'),PRE(str(e)))
response.flash = DIV(T('unable to parse csv file'), PRE(str(e)))
# end handle upload csv
return dict(
@@ -251,8 +256,8 @@ def select():
nrows=nrows,
rows=rows,
query=request.vars.query,
formcsv = formcsv,
tb = tb,
formcsv=formcsv,
tb=tb,
)
@@ -263,14 +268,16 @@ def select():
def update():
(db, table) = get_table(request)
keyed = hasattr(db[table],'_primarykey')
keyed = hasattr(db[table], '_primarykey')
record = None
if keyed:
key = [f for f in request.vars if f in db[table]._primarykey]
if key:
record = db(db[table][key[0]] == request.vars[key[0]], ignore_common_filters=True).select().first()
record = db(db[table][key[0]] == request.vars[key[
0]], ignore_common_filters=True).select().first()
else:
record = db(db[table].id == request.args(2),ignore_common_filters=True).select().first()
record = db(db[table].id == request.args(
2), ignore_common_filters=True).select().first()
if not record:
qry = query_by_table_type(table, db)
@@ -280,9 +287,10 @@ def update():
if keyed:
for k in db[table]._primarykey:
db[table][k].writable=False
db[table][k].writable = False
form = SQLFORM(db[table], record, deletable=True, delete_label=T('Check to delete'),
form = SQLFORM(
db[table], record, deletable=True, delete_label=T('Check to delete'),
ignore_rw=ignore_rw and not keyed,
linkto=URL('select',
args=request.args[:1]), upload=URL(r=request,
@@ -293,7 +301,7 @@ def update():
qry = query_by_table_type(table, db)
redirect(URL('select', args=request.args[:1],
vars=dict(query=qry)))
return dict(form=form,table=db[table])
return dict(form=form, table=db[table])
# ##########################################################
@@ -304,11 +312,15 @@ def update():
def state():
return dict()
def ccache():
form = FORM(
P(TAG.BUTTON(T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")),
P(TAG.BUTTON(T("Clear RAM"), _type="submit", _name="ram", _value="ram")),
P(TAG.BUTTON(T("Clear DISK"), _type="submit", _name="disk", _value="disk")),
P(TAG.BUTTON(
T("Clear CACHE?"), _type="submit", _name="yes", _value="yes")),
P(TAG.BUTTON(
T("Clear RAM"), _type="submit", _name="ram", _value="ram")),
P(TAG.BUTTON(
T("Clear DISK"), _type="submit", _name="disk", _value="disk")),
)
if form.accepts(request.vars, session):
@@ -332,11 +344,16 @@ def ccache():
redirect(URL(r=request))
try:
from guppy import hpy; hp=hpy()
from guppy import hpy
hp = hpy()
except ImportError:
hp = False
import shelve, os, copy, time, math
import shelve
import os
import copy
import time
import math
from gluon import portalocker
ram = {
@@ -379,11 +396,13 @@ def ccache():
if value[0] < ram['oldest']:
ram['oldest'] = value[0]
ram['keys'].append((key, GetInHMS(time.time() - value[0])))
locker = open(os.path.join(request.folder,
'cache/cache.lock'), 'a')
folder = os.path.join(request.folder,'cache')
if not os.path.exists(folder):
os.mkdir(folder)
locker = open(os.path.join(folder, 'cache.lock'), 'a')
portalocker.lock(locker, portalocker.LOCK_EX)
disk_storage = shelve.open(os.path.join(request.folder, 'cache/cache.shelve'))
disk_storage = shelve.open(
os.path.join(folder, 'cache.shelve'))
try:
for key, value in disk_storage.items():
if isinstance(value, dict):
@@ -414,7 +433,8 @@ def ccache():
total['misses'] = ram['misses'] + disk['misses']
total['keys'] = ram['keys'] + disk['keys']
try:
total['ratio'] = total['hits'] * 100 / (total['hits'] + total['misses'])
total['ratio'] = total['hits'] * 100 / (total['hits'] +
total['misses'])
except (KeyError, ZeroDivisionError):
total['ratio'] = 0
@@ -440,6 +460,3 @@ def ccache():
return dict(form=form, total=total,
ram=ram, disk=disk, object_stats=hp != False)
+3 -1
View File
@@ -9,6 +9,7 @@
## - call exposes all registered services (none by default)
#########################################################################
def index():
"""
example action using the internationalization operator T and flash
@@ -20,6 +21,7 @@ def index():
response.flash = T("Welcome to web2py!")
return dict(message=T('Hello World'))
def user():
"""
exposes:
@@ -42,7 +44,7 @@ def download():
allows downloading of uploaded files
http://..../[app]/default/download/[filename]
"""
return response.download(request,db)
return response.download(request, db)
def call():
+1
View File
@@ -89,6 +89,7 @@
'export as csv file': 'експортувати як файл csv',
'FAQ': 'ЧаПи (FAQ)',
'First name': "Ім'я",
'Forgot username?': "Забули ім'я користувача?",
'Forms and Validators': 'Форми та коректність даних',
'Free Applications': 'Вільні додатки',
'Group %(group_id)s created': 'Групу %(group_id)s створено',
+4 -4
View File
@@ -11,12 +11,12 @@
if not request.env.web2py_runtime_gae:
## if NOT running on Google App Engine use SQLite or other DB
db = DAL('sqlite://storage.sqlite')
db = DAL('sqlite://storage.sqlite',pool_size=1,check_reserved=['all'])
else:
## connect to Google BigTable (optional 'google:datastore://namespace')
db = DAL('google:datastore')
## store sessions and tickets there
session.connect(request, response, db = db)
session.connect(request, response, db=db)
## or store session in Memcache, Redis, etc.
## from gluon.contrib.memdb import MEMDB
## from google.appengine.api.memcache import Client
@@ -47,7 +47,7 @@ crud, service, plugins = Crud(db), Service(), PluginManager()
auth.define_tables(username=False, signature=False)
## configure email
mail=auth.settings.mailer
mail = auth.settings.mailer
mail.settings.server = 'logging' or 'smtp.gmail.com:587'
mail.settings.sender = 'you@gmail.com'
mail.settings.login = 'username:password'
@@ -60,7 +60,7 @@ auth.settings.reset_password_requires_verification = True
## if you need to use OpenID, Facebook, MySpace, Twitter, Linkedin, etc.
## register with janrain.com, write your domain:api_key in private/janrain.key
from gluon.contrib.login_methods.rpx_account import use_janrain
use_janrain(auth,filename='private/janrain.key')
use_janrain(auth, filename='private/janrain.key')
#########################################################################
## Define your tables below (or better in another model file) for example
+99 -61
View File
@@ -5,7 +5,10 @@
## Customize your APP title, subtitle and menus here
#########################################################################
response.title = ' '.join(word.capitalize() for word in request.application.split('_'))
response.logo = A(B('web',SPAN(2),'py'),XML('&trade;&nbsp;'),
_class="brand",_href="http://www.web2py.com/")
response.title = ' '.join(
word.capitalize() for word in request.application.split('_'))
response.subtitle = T('customize me!')
## read more at http://dev.w3.org/html5/markup/meta.name.html
@@ -22,8 +25,10 @@ response.google_analytics_id = None
#########################################################################
response.menu = [
(T('Home'), False, URL('default','index'), [])
]
(T('Home'), False, URL('default', 'index'), [])
]
DEVELOPMENT_MENU = True
#########################################################################
## provide shortcuts for development. remove in production
@@ -34,68 +39,101 @@ def _():
app = request.application
ctr = request.controller
# useful links to internal and external resources
response.menu+=[
(SPAN('web2py',_class='highlighted'),False, 'http://web2py.com', [
(T('My Sites'),False,URL('admin','default','site')),
(T('This App'),False,URL('admin','default','design/%s' % app), [
(T('Controller'),False,
URL('admin','default','edit/%s/controllers/%s.py' % (app,ctr))),
(T('View'),False,
URL('admin','default','edit/%s/views/%s' % (app,response.view))),
(T('Layout'),False,
URL('admin','default','edit/%s/views/layout.html' % app)),
(T('Stylesheet'),False,
URL('admin','default','edit/%s/static/css/web2py.css' % app)),
(T('DB Model'),False,
URL('admin','default','edit/%s/models/db.py' % app)),
(T('Menu Model'),False,
URL('admin','default','edit/%s/models/menu.py' % app)),
(T('Database'),False, URL(app,'appadmin','index')),
(T('Errors'),False, URL('admin','default','errors/' + app)),
(T('About'),False, URL('admin','default','about/' + app)),
response.menu += [
(SPAN('web2py', _class='highlighted'), False, 'http://web2py.com', [
(T('My Sites'), False, URL('admin', 'default', 'site')),
(T('This App'), False, URL('admin', 'default', 'design/%s' % app), [
(T('Controller'), False,
URL(
'admin', 'default', 'edit/%s/controllers/%s.py' % (app, ctr))),
(T('View'), False,
URL(
'admin', 'default', 'edit/%s/views/%s' % (app, response.view))),
(T('Layout'), False,
URL(
'admin', 'default', 'edit/%s/views/layout.html' % app)),
(T('Stylesheet'), False,
URL(
'admin', 'default', 'edit/%s/static/css/web2py.css' % app)),
(T('DB Model'), False,
URL(
'admin', 'default', 'edit/%s/models/db.py' % app)),
(T('Menu Model'), False,
URL(
'admin', 'default', 'edit/%s/models/menu.py' % app)),
(T('Database'), False, URL(app, 'appadmin', 'index')),
(T('Errors'), False, URL(
'admin', 'default', 'errors/' + app)),
(T('About'), False, URL(
'admin', 'default', 'about/' + app)),
]),
('web2py.com',False,'http://www.web2py.com', [
(T('Download'),False,'http://www.web2py.com/examples/default/download'),
(T('Support'),False,'http://www.web2py.com/examples/default/support'),
(T('Demo'),False,'http://web2py.com/demo_admin'),
(T('Quick Examples'),False,'http://web2py.com/examples/default/examples'),
(T('FAQ'),False,'http://web2py.com/AlterEgo'),
(T('Videos'),False,'http://www.web2py.com/examples/default/videos/'),
(T('Free Applications'),False,'http://web2py.com/appliances'),
(T('Plugins'),False,'http://web2py.com/plugins'),
(T('Layouts'),False,'http://web2py.com/layouts'),
(T('Recipes'),False,'http://web2pyslices.com/'),
(T('Semantic'),False,'http://web2py.com/semantic'),
('web2py.com', False, 'http://www.web2py.com', [
(T('Download'), False,
'http://www.web2py.com/examples/default/download'),
(T('Support'), False,
'http://www.web2py.com/examples/default/support'),
(T('Demo'), False, 'http://web2py.com/demo_admin'),
(T('Quick Examples'), False,
'http://web2py.com/examples/default/examples'),
(T('FAQ'), False, 'http://web2py.com/AlterEgo'),
(T('Videos'), False,
'http://www.web2py.com/examples/default/videos/'),
(T('Free Applications'),
False, 'http://web2py.com/appliances'),
(T('Plugins'), False, 'http://web2py.com/plugins'),
(T('Layouts'), False, 'http://web2py.com/layouts'),
(T('Recipes'), False, 'http://web2pyslices.com/'),
(T('Semantic'), False, 'http://web2py.com/semantic'),
]),
(T('Documentation'),False,'http://www.web2py.com/book', [
(T('Preface'),False,'http://www.web2py.com/book/default/chapter/00'),
(T('Introduction'),False,'http://www.web2py.com/book/default/chapter/01'),
(T('Python'),False,'http://www.web2py.com/book/default/chapter/02'),
(T('Overview'),False,'http://www.web2py.com/book/default/chapter/03'),
(T('The Core'),False,'http://www.web2py.com/book/default/chapter/04'),
(T('The Views'),False,'http://www.web2py.com/book/default/chapter/05'),
(T('Database'),False,'http://www.web2py.com/book/default/chapter/06'),
(T('Forms and Validators'),False,'http://www.web2py.com/book/default/chapter/07'),
(T('Email and SMS'),False,'http://www.web2py.com/book/default/chapter/08'),
(T('Access Control'),False,'http://www.web2py.com/book/default/chapter/09'),
(T('Services'),False,'http://www.web2py.com/book/default/chapter/10'),
(T('Ajax Recipes'),False,'http://www.web2py.com/book/default/chapter/11'),
(T('Components and Plugins'),False,'http://www.web2py.com/book/default/chapter/12'),
(T('Deployment Recipes'),False,'http://www.web2py.com/book/default/chapter/13'),
(T('Other Recipes'),False,'http://www.web2py.com/book/default/chapter/14'),
(T('Buy this book'),False,'http://stores.lulu.com/web2py'),
(T('Documentation'), False, 'http://www.web2py.com/book', [
(T('Preface'), False,
'http://www.web2py.com/book/default/chapter/00'),
(T('Introduction'), False,
'http://www.web2py.com/book/default/chapter/01'),
(T('Python'), False,
'http://www.web2py.com/book/default/chapter/02'),
(T('Overview'), False,
'http://www.web2py.com/book/default/chapter/03'),
(T('The Core'), False,
'http://www.web2py.com/book/default/chapter/04'),
(T('The Views'), False,
'http://www.web2py.com/book/default/chapter/05'),
(T('Database'), False,
'http://www.web2py.com/book/default/chapter/06'),
(T('Forms and Validators'), False,
'http://www.web2py.com/book/default/chapter/07'),
(T('Email and SMS'), False,
'http://www.web2py.com/book/default/chapter/08'),
(T('Access Control'), False,
'http://www.web2py.com/book/default/chapter/09'),
(T('Services'), False,
'http://www.web2py.com/book/default/chapter/10'),
(T('Ajax Recipes'), False,
'http://www.web2py.com/book/default/chapter/11'),
(T('Components and Plugins'), False,
'http://www.web2py.com/book/default/chapter/12'),
(T('Deployment Recipes'), False,
'http://www.web2py.com/book/default/chapter/13'),
(T('Other Recipes'), False,
'http://www.web2py.com/book/default/chapter/14'),
(T('Buy this book'), False,
'http://stores.lulu.com/web2py'),
]),
(T('Community'),False, None, [
(T('Groups'),False,'http://www.web2py.com/examples/default/usergroups'),
(T('Twitter'),False,'http://twitter.com/web2py'),
(T('Live Chat'),False,'http://webchat.freenode.net/?channels=web2py'),
(T('Community'), False, None, [
(T('Groups'), False,
'http://www.web2py.com/examples/default/usergroups'),
(T('Twitter'), False, 'http://twitter.com/web2py'),
(T('Live Chat'), False,
'http://webchat.freenode.net/?channels=web2py'),
]),
(T('Plugins'),False,None, [
('plugin_wiki',False,'http://web2py.com/examples/default/download'),
(T('Other Plugins'),False,'http://web2py.com/plugins'),
(T('Layout Plugins'),False,'http://web2py.com/layouts'),
(T('Plugins'), False, None, [
('plugin_wiki', False,
'http://web2py.com/examples/default/download'),
(T('Other Plugins'), False,
'http://web2py.com/plugins'),
(T('Layout Plugins'),
False, 'http://web2py.com/layouts'),
])
]
)]
_()
if DEVELOPMENT_MENU: _()
-1
View File
@@ -37,4 +37,3 @@ routers = {
#NOTE! To change language in your application using these rules add this line
#in one of your models files:
# if request.uri_language: T.force(request.uri_language)
@@ -1,9 +1,9 @@
/*!
* Bootstrap Responsive v2.1.1
* Bootstrap Responsive v2.2.2
*
* Copyright 2012 Twitter, Inc
* Licensed under the Apache License v2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Designed and built with all the love in the world @twitter by @mdo and @fat.
*/.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*maLine truncated
*/@-ms-viewport{width:device-width}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-lefLine truncated
+2 -2
View File
@@ -1,9 +1,9 @@
/*!
* Bootstrap v2.1.1
* Bootstrap v2.2.2
*
* Copyright 2012 Twitter, Inc
* Licensed under the Apache License v2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Designed and built with all the love in the world @twitter by @mdo and @fat.
*/article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluiLine truncated
*/article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%Line truncated
@@ -115,6 +115,10 @@ div.flash {
z-index:2000;
}
div.flash #closeflash{color:inherit; float:right; margin-left:15px;}
.ie-lte7 div.flash #closeflash
{color:expression(this.parentNode.currentStyle['color']);float:none;position:absolute;right:4px;}
div.flash:hover { opacity:0.25; }
div.error_wrapper {display:block}
@@ -67,10 +67,13 @@ div.controls .error{
border:none;
padding:0;
margin:0;
//display:inline; /* uncommenting this, the animation effect is lost */
/*display:inline;*/ /* uncommenting this, the animation effect is lost */
}
div.controls .inline-help{color:#3A87AD;}
div.controls .error_wrapper+.inline-help{margin-left:-99999px;}
div.controls .help-inline{color:#3A87AD;}
div.controls .error_wrapper +.help-inline {margin-left:-99999px;}
div.controls select +.error_wrapper {margin-left:5px;}
.ie-lte7 div.error{color:#fff;}
/* beautify brand */
.navbar-inverse .brand{color:#c6cecc;}
.navbar-inverse .brand b{display:inline-block;margin-top:-1px;}
@@ -175,9 +178,6 @@ background-repeat:repeat;
OTHER RULES
==============================================================*/
.navbar-inner{
position:relative; /*unnecessary ??*/
}
/* Massimo Di Pierro fixed alignment in forms with list:string */
form table tr{margin-bottom:9px;}
td.w2p_fw ul{margin-left:0px;}
@@ -212,7 +212,7 @@ td.w2p_fw ul{margin-left:0px;}
@media only screen and (max-width:979px){
body{padding-top:0px;}
#navbar{bottom:-10px;left:4px;}
#navbar{top:5px;}
div.flash{right:5px;}
.dropdown-menu ul{visibility:visible;}
}
+805
View File
@@ -0,0 +1,805 @@
<!DOCTYPE html>
<html>
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# githubog: http://ogp.me/ns/fb/githubog#">
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>analytics.js/analytics.min.js at master · segmentio/analytics.js · GitHub</title>
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub" />
<link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub" />
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="apple-touch-icon-114.png" />
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="apple-touch-icon-114.png" />
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="apple-touch-icon-144.png" />
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="apple-touch-icon-144.png" />
<meta name="msapplication-TileImage" content="/windows-tile.png">
<meta name="msapplication-TileColor" content="#ffffff">
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<meta content="authenticity_token" name="csrf-param" />
<meta content="yzKORCZKWgf8oUHQLtjsbuHT1vVUytLyi1oNA2xf4LI=" name="csrf-token" />
<link href="https://a248.e.akamai.net/assets.github.com/assets/github-27292274b2b87ffe79d2e380418f608e3bf89253.css" media="screen" rel="stylesheet" type="text/css" />
<link href="https://a248.e.akamai.net/assets.github.com/assets/github2-4591451faf42b997173d752065f048736e6f9872.css" media="screen" rel="stylesheet" type="text/css" />
<script src="https://a248.e.akamai.net/assets.github.com/assets/frameworks-eee761b9d5e06efb064aaaf528c44ef8e1601e71.js" type="text/javascript"></script>
<script src="https://a248.e.akamai.net/assets.github.com/assets/github-1bba5a5e98213164a06b7a54bec8a300b2883987.js" type="text/javascript"></script>
<link rel='permalink' href='/segmentio/analytics.js/blob/85f0eed5a51bc18d0a2e20bcc71b58ec27bec2a6/analytics.min.js'>
<meta property="og:title" content="analytics.js"/>
<meta property="og:type" content="githubog:gitrepository"/>
<meta property="og:url" content="https://github.com/segmentio/analytics.js"/>
<meta property="og:image" content="https://secure.gravatar.com/avatar/420370b79b6adb3a513c24935907539f?s=420&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png"/>
<meta property="og:site_name" content="GitHub"/>
<meta property="og:description" content="analytics.js - The hassle-free way to integrate analytics into any web application."/>
<meta name="description" content="analytics.js - The hassle-free way to integrate analytics into any web application." />
<link href="https://github.com/segmentio/analytics.js/commits/master.atom" rel="alternate" title="Recent Commits to analytics.js:master" type="application/atom+xml" />
</head>
<body class="logged_out page-blob vis-public env-production ">
<div id="wrapper">
<div class="header header-logged-out">
<div class="container clearfix">
<a class="header-logo-wordmark" href="https://github.com/">
<img alt="GitHub" class="github-logo-4x" height="30" src="https://a248.e.akamai.net/assets.github.com/images/modules/header/logov7@4x.png?1340659511" />
<img alt="GitHub" class="github-logo-4x-hover" height="30" src="https://a248.e.akamai.net/assets.github.com/images/modules/header/logov7@4x-hover.png?1340659511" />
</a>
<ul class="top-nav">
<li class="explore"><a href="https://github.com/explore">Explore GitHub</a></li>
<li class="search"><a href="https://github.com/search">Search</a></li>
<li class="features"><a href="https://github.com/features">Features</a></li>
<li class="blog"><a href="https://github.com/blog">Blog</a></li>
</ul>
<div class="header-actions">
<a class="button primary classy" href="https://github.com/signup">Sign up for free</a>
<a class="button classy" href="https://github.com/login?return_to=%2Fsegmentio%2Fanalytics.js%2Fblob%2Fmaster%2Fanalytics.min.js">Sign in</a>
</div>
</div>
</div>
<div class="site hfeed" itemscope itemtype="http://schema.org/WebPage">
<div class="hentry">
<div class="pagehead repohead instapaper_ignore readability-menu">
<div class="container">
<div class="title-actions-bar">
<ul class="pagehead-actions">
<li>
<span class="star-button"><a href="/login?return_to=%2Fsegmentio%2Fanalytics.js" class="minibutton js-toggler-target entice tooltipped leftwards" title="You must be signed in to use this feature" rel="nofollow"><span class="mini-icon mini-icon-star"></span>Star</a><a class="social-count js-social-count" href="/segmentio/analytics.js/stargazers">869</a></span>
</li>
<li>
<a href="/login?return_to=%2Fsegmentio%2Fanalytics.js" class="minibutton js-toggler-target fork-button entice tooltipped leftwards" title="You must be signed in to fork a repository" rel="nofollow"><span class="mini-icon mini-icon-fork"></span>Fork</a><a href="/segmentio/analytics.js/network" class="social-count">52</a>
</li>
</ul>
<h1 itemscope itemtype="http://data-vocabulary.org/Breadcrumb" class="entry-title public">
<span class="repo-label"><span>public</span></span>
<span class="mega-icon mega-icon-public-repo"></span>
<span class="author vcard">
<a href="/segmentio" class="url fn" itemprop="url" rel="author">
<span itemprop="title">segmentio</span>
</a></span> /
<strong><a href="/segmentio/analytics.js" class="js-current-repository">analytics.js</a></strong>
</h1>
</div>
<ul class="tabs">
<li><a href="/segmentio/analytics.js" class="selected" highlight="repo_sourcerepo_downloadsrepo_commitsrepo_tagsrepo_branches">Code</a></li>
<li><a href="/segmentio/analytics.js/network" highlight="repo_network">Network</a></li>
<li><a href="/segmentio/analytics.js/pulls" highlight="repo_pulls">Pull Requests <span class='counter'>5</span></a></li>
<li><a href="/segmentio/analytics.js/issues" highlight="repo_issues">Issues <span class='counter'>7</span></a></li>
<li><a href="/segmentio/analytics.js/wiki" highlight="repo_wiki">Wiki</a></li>
<li><a href="/segmentio/analytics.js/graphs" highlight="repo_graphsrepo_contributors">Graphs</a></li>
</ul>
<div class="tabnav">
<span class="tabnav-right">
<ul class="tabnav-tabs">
<li><a href="/segmentio/analytics.js/tags" class="tabnav-tab" highlight="repo_tags">Tags <span class="counter ">1</span></a></li>
</ul>
</span>
<div class="tabnav-widget scope">
<div class="context-menu-container js-menu-container js-context-menu">
<a href="#"
class="minibutton bigger switcher js-menu-target js-commitish-button btn-branch repo-tree"
data-hotkey="w"
data-ref="master">
<span><em class="mini-icon mini-icon-branch"></em><i>branch:</i> master</span>
</a>
<div class="context-pane commitish-context js-menu-content">
<a href="#" class="close js-menu-close"><span class="mini-icon mini-icon-remove-close"></span></a>
<div class="context-title">Switch branches/tags</div>
<div class="context-body pane-selector commitish-selector js-navigation-container">
<div class="filterbar">
<input type="text" id="context-commitish-filter-field" class="js-navigation-enable js-filterable-field" placeholder="Filter branches/tags">
<ul class="tabs">
<li><a href="#" data-filter="branches" class="selected">Branches</a></li>
<li><a href="#" data-filter="tags">Tags</a></li>
</ul>
</div>
<div class="js-filter-tab js-filter-branches">
<div data-filterable-for="context-commitish-filter-field" data-filterable-type=substring>
<div class="commitish-item branch-commitish selector-item js-navigation-item js-navigation-target ">
<span class="mini-icon mini-icon-confirm"></span>
<h4>
<a href="/segmentio/analytics.js/blob/gh-pages/analytics.min.js" class="js-navigation-open" data-name="gh-pages" rel="nofollow">gh-pages</a>
</h4>
</div>
<div class="commitish-item branch-commitish selector-item js-navigation-item js-navigation-target selected">
<span class="mini-icon mini-icon-confirm"></span>
<h4>
<a href="/segmentio/analytics.js/blob/master/analytics.min.js" class="js-navigation-open" data-name="master" rel="nofollow">master</a>
</h4>
</div>
</div>
<div class="no-results">Nothing to show</div>
</div>
<div class="js-filter-tab js-filter-tags " style="display:none">
<div data-filterable-for="context-commitish-filter-field" data-filterable-type=substring>
<div class="commitish-item tag-commitish selector-item js-navigation-item js-navigation-target ">
<span class="mini-icon mini-icon-confirm"></span>
<h4>
<a href="/segmentio/analytics.js/blob/0.1.0/analytics.min.js" class="js-navigation-open" data-name="0.1.0" rel="nofollow">0.1.0</a>
</h4>
</div>
</div>
<div class="no-results">Nothing to show</div>
</div>
</div>
</div><!-- /.commitish-context-context -->
</div>
</div> <!-- /.scope -->
<ul class="tabnav-tabs">
<li><a href="/segmentio/analytics.js" class="selected tabnav-tab" highlight="repo_source">Files</a></li>
<li><a href="/segmentio/analytics.js/commits/master" class="tabnav-tab" highlight="repo_commits">Commits</a></li>
<li><a href="/segmentio/analytics.js/branches" class="tabnav-tab" highlight="repo_branches" rel="nofollow">Branches <span class="counter ">2</span></a></li>
</ul>
</div>
</div>
</div><!-- /.repohead -->
<div id="js-repo-pjax-container" class="container context-loader-container" data-pjax-container>
<!-- blob contrib key: blob_contributors:v21:603d6b20cf2de0e6f3cc4751aea062cf -->
<!-- blob contrib frag key: views10/v8/blob_contributors:v21:603d6b20cf2de0e6f3cc4751aea062cf -->
<div id="slider">
<div class="frame-meta">
<p title="This is a placeholder element" class="js-history-link-replace hidden"></p>
<div class="breadcrumb">
<span class='bold'><span itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb"><a href="/segmentio/analytics.js" class="js-slide-to" data-direction="back" itemscope="url"><span itemprop="title">analytics.js</span></a></span></span> / <strong class="final-path">analytics.min.js</strong> <span class="js-clippy mini-icon mini-icon-clippy " data-clipboard-text="analytics.min.js" data-copied-hint="copied!" data-copy-hint="copy to clipboard"></span>
</div>
<a href="/segmentio/analytics.js/find/master" class="js-slide-to" data-hotkey="t" style="display:none">Show File Finder</a>
<div class="commit file-history-tease">
<img class="main-avatar" height="24" src="https://secure.gravatar.com/avatar/e7f4e4b1d3b381e70f864bc7f8b4493e?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="24" />
<span class="author"><a href="/ianstormtaylor" rel="author">ianstormtaylor</a></span>
<time class="js-relative-date" datetime="2012-12-13T14:29:56-08:00" title="2012-12-13 14:29:56">December 13, 2012</time>
<div class="commit-title">
<a href="/segmentio/analytics.js/commit/85f0eed5a51bc18d0a2e20bcc71b58ec27bec2a6" class="message">updated build</a>
</div>
<div class="participation">
<p class="quickstat"><a href="#blob_contributors_box" rel="facebox"><strong>4</strong> contributors</a></p>
<a class="avatar tooltipped downwards" title="ianstormtaylor" href="/segmentio/analytics.js/commits/master/analytics.min.js?author=ianstormtaylor"><img height="20" src="https://secure.gravatar.com/avatar/e7f4e4b1d3b381e70f864bc7f8b4493e?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="20" /></a>
<a class="avatar tooltipped downwards" title="calvinfo" href="/segmentio/analytics.js/commits/master/analytics.min.js?author=calvinfo"><img height="20" src="https://secure.gravatar.com/avatar/c9a93b63666485fa1c84cd93f8ed8111?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="20" /></a>
<a class="avatar tooltipped downwards" title="jessbrandi" href="/segmentio/analytics.js/commits/master/analytics.min.js?author=jessbrandi"><img height="20" src="https://secure.gravatar.com/avatar/a99c959b5a3a7e4a522930af73bbfb3e?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="20" /></a>
<a class="avatar tooltipped downwards" title="nscott" href="/segmentio/analytics.js/commits/master/analytics.min.js?author=nscott"><img height="20" src="https://secure.gravatar.com/avatar/c2ad95ff8e3f1c693258b2a9ad0135cb?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="20" /></a>
</div>
<div id="blob_contributors_box" style="display:none">
<h2>Users on GitHub who have contributed to this file</h2>
<ul class="facebox-user-list">
<li>
<img height="24" src="https://secure.gravatar.com/avatar/e7f4e4b1d3b381e70f864bc7f8b4493e?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="24" />
<a href="/ianstormtaylor">ianstormtaylor</a>
</li>
<li>
<img height="24" src="https://secure.gravatar.com/avatar/c9a93b63666485fa1c84cd93f8ed8111?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="24" />
<a href="/calvinfo">calvinfo</a>
</li>
<li>
<img height="24" src="https://secure.gravatar.com/avatar/a99c959b5a3a7e4a522930af73bbfb3e?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="24" />
<a href="/jessbrandi">jessbrandi</a>
</li>
<li>
<img height="24" src="https://secure.gravatar.com/avatar/c2ad95ff8e3f1c693258b2a9ad0135cb?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="24" />
<a href="/nscott">nscott</a>
</li>
</ul>
</div>
</div>
</div><!-- ./.frame-meta -->
<div class="frames">
<div class="frame" data-permalink-url="/segmentio/analytics.js/blob/85f0eed5a51bc18d0a2e20bcc71b58ec27bec2a6/analytics.min.js" data-title="analytics.js/analytics.min.js at master · segmentio/analytics.js · GitHub" data-type="blob">
<div id="files" class="bubble">
<div class="file">
<div class="meta">
<div class="info">
<span class="icon"><b class="mini-icon mini-icon-text-file"></b></span>
<span class="mode" title="File Mode">file</span>
<span>4 lines (4 sloc)</span>
<span>8.997 kb</span>
</div>
<ul class="button-group actions">
<li>
<a class="grouped-button minibutton bigger lighter js-entice" href=""
data-entice="You must be signed in and on a branch to make or propose changes">Edit</a>
</li>
<li><a href="/segmentio/analytics.js/raw/master/analytics.min.js" class="minibutton grouped-button bigger lighter" id="raw-url">Raw</a></li>
<li><a href="/segmentio/analytics.js/blame/master/analytics.min.js" class="minibutton grouped-button bigger lighter">Blame</a></li>
<li><a href="/segmentio/analytics.js/commits/master/analytics.min.js" class="minibutton grouped-button bigger lighter" rel="nofollow">History</a></li>
</ul>
</div>
<div class="data type-javascript">
<table cellpadding="0" cellspacing="0" class="lines">
<tr>
<td>
<pre class="line_numbers"><span id="L1" rel="#L1">1</span>
<span id="L2" rel="#L2">2</span>
<span id="L3" rel="#L3">3</span>
<span id="L4" rel="#L4">4</span>
</pre>
</td>
<td width="100%">
<div class="highlight"><pre><div class='line' id='LC1'><span class="c1">// Analytics.js 0.2.0</span></div><div class='line' id='LC2'><span class="c1">// (c) 2012 Segment.io Inc.</span></div><div class='line' id='LC3'><span class="c1">// Analytics.js may be freely distributed under the MIT license.</span></div><div class='line' id='LC4'><span class="p">(</span><span class="kd">function</span><span class="p">(){</span><span class="kd">var</span> <span class="nx">e</span><span class="o">=</span><span class="k">this</span><span class="p">,</span><span class="nx">t</span><span class="o">=!</span><span class="mi">1</span><span class="p">,</span><span class="nx">n</span><span class="o">=</span><span class="k">new</span> <span class="nb">Date</span><span class="p">,</span><span class="nx">r</span><span class="o">=</span><span class="sr">/.+\@.+\..+/</span><span class="p">,</span><span class="nx">i</span><span class="o">=!</span><span class="mi">1</span><span class="p">,</span><span class="nx">s</span><span class="o">=</span><span class="nb">window</span><span class="p">.</span><span class="nx">onload</span><span class="p">;</span><span class="nb">window</span><span class="p">.</span><span class="nx">onload</span><span class="o">=</span><span class="kd">function</span><span class="p">(){</span><span class="nx">i</span><span class="o">=!</span><span class="mi">0</span><span class="p">,</span><span class="nx">c</span><span class="p">(</span><span class="nx">s</span><span class="p">)</span><span class="o">&amp;&amp;</span><span class="nx">s</span><span class="p">()},</span><span class="nx">e</span><span class="p">.</span><span class="nx">analytics</span><span class="o">||</span><span class="p">(</span><span class="nx">e</span><span class="p">.</span><span class="nx">analytics</span><span class="o">=</span><span class="p">{</span><span class="nx">providers</span><span class="o">:</span><span class="p">[],</span><span class="nx">userId</span><span class="o">:</span><span class="kc">null</span><span class="p">,</span><span class="nx">initialize</span><span class="o">:</span><span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">){</span><span class="k">this</span><span class="p">.</span><span class="nx">providers</span><span class="o">=</span><span class="p">[];</span><span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">n</span> <span class="k">in</span> <span class="nx">e</span><span class="p">){</span><span class="kd">var</span> <span class="nx">r</span><span class="o">=</span><span class="nx">o</span><span class="p">[</span><span class="nx">n</span><span class="p">];</span><span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">r</span><span class="p">)</span><span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="s1">&#39;Could not find a provider named &quot;&#39;</span><span class="o">+</span><span class="nx">n</span><span class="o">+</span><span class="s1">&#39;&quot;&#39;</span><span class="p">);</span><span class="nx">r</span><span class="p">.</span><span class="nx">initialize</span><span class="p">(</span><span class="nx">e</span><span class="p">[</span><span class="nx">n</span><span class="p">]),</span><span class="k">this</span><span class="p">.</span><span class="nx">providers</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">r</span><span class="p">)}</span><span class="nx">t</span><span class="o">=!</span><span class="mi">0</span><span class="p">},</span><span class="nx">identify</span><span class="o">:</span><span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">,</span><span class="nx">n</span><span class="p">){</span><span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">t</span><span class="p">)</span><span class="k">return</span><span class="p">;</span><span class="nx">f</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span><span class="o">&amp;&amp;</span><span class="p">(</span><span class="nx">n</span><span class="o">=</span><span class="nx">e</span><span class="p">,</span><span class="nx">e</span><span class="o">=</span><span class="kc">null</span><span class="p">),</span><span class="nx">e</span><span class="o">!==</span><span class="kc">null</span><span class="o">?</span><span class="k">this</span><span class="p">.</span><span class="nx">userId</span><span class="o">=</span><span class="nx">e</span><span class="o">:</span><span class="nx">e</span><span class="o">=</span><span class="k">this</span><span class="p">.</span><span class="nx">userId</span><span class="p">;</span><span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">r</span><span class="o">=</span><span class="mi">0</span><span class="p">, Line truncated
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<a href="#jump-to-line" rel="facebox" data-hotkey="l" class="js-jump-to-line" style="display:none">Jump to Line</a>
<div id="jump-to-line" style="display:none">
<h2>Jump to Line</h2>
<form accept-charset="UTF-8" class="js-jump-to-line-form">
<input class="textfield js-jump-to-line-field" type="text">
<div class="full-button">
<button type="submit" class="classy">
Go
</button>
</div>
</form>
</div>
</div>
</div>
<div id="js-frame-loading-template" class="frame frame-loading large-loading-area" style="display:none;">
<img class="js-frame-loading-spinner" src="https://a248.e.akamai.net/assets.github.com/images/spinners/octocat-spinner-128.gif?1347543527" height="64" width="64">
</div>
</div>
</div>
<div class="context-overlay"></div>
</div>
<div id="footer-push"></div><!-- hack for sticky footer -->
</div><!-- end of wrapper - hack for sticky footer -->
<!-- footer -->
<div id="footer">
<div class="container clearfix">
<dl class="footer_nav">
<dt>GitHub</dt>
<dd><a href="https://github.com/about">About us</a></dd>
<dd><a href="https://github.com/blog">Blog</a></dd>
<dd><a href="https://github.com/contact">Contact &amp; support</a></dd>
<dd><a href="http://enterprise.github.com/">GitHub Enterprise</a></dd>
<dd><a href="http://status.github.com/">Site status</a></dd>
</dl>
<dl class="footer_nav">
<dt>Applications</dt>
<dd><a href="http://mac.github.com/">GitHub for Mac</a></dd>
<dd><a href="http://windows.github.com/">GitHub for Windows</a></dd>
<dd><a href="http://eclipse.github.com/">GitHub for Eclipse</a></dd>
<dd><a href="http://mobile.github.com/">GitHub mobile apps</a></dd>
</dl>
<dl class="footer_nav">
<dt>Services</dt>
<dd><a href="http://get.gaug.es/">Gauges: Web analytics</a></dd>
<dd><a href="http://speakerdeck.com">Speaker Deck: Presentations</a></dd>
<dd><a href="https://gist.github.com">Gist: Code snippets</a></dd>
<dd><a href="http://jobs.github.com/">Job board</a></dd>
</dl>
<dl class="footer_nav">
<dt>Documentation</dt>
<dd><a href="http://help.github.com/">GitHub Help</a></dd>
<dd><a href="http://developer.github.com/">Developer API</a></dd>
<dd><a href="http://github.github.com/github-flavored-markdown/">GitHub Flavored Markdown</a></dd>
<dd><a href="http://pages.github.com/">GitHub Pages</a></dd>
</dl>
<dl class="footer_nav">
<dt>More</dt>
<dd><a href="http://training.github.com/">Training</a></dd>
<dd><a href="https://github.com/edu">Students &amp; teachers</a></dd>
<dd><a href="http://shop.github.com">The Shop</a></dd>
<dd><a href="/plans">Plans &amp; pricing</a></dd>
<dd><a href="http://octodex.github.com/">The Octodex</a></dd>
</dl>
<hr class="footer-divider">
<p class="right">&copy; 2012 <span title="0.07091s from fe16.rs.github.com">GitHub</span> Inc. All rights reserved.</p>
<a class="left" href="https://github.com/">
<span class="mega-icon mega-icon-invertocat"></span>
</a>
<ul id="legal">
<li><a href="https://github.com/site/terms">Terms of Service</a></li>
<li><a href="https://github.com/site/privacy">Privacy</a></li>
<li><a href="https://github.com/security">Security</a></li>
</ul>
</div><!-- /.container -->
</div><!-- /.#footer -->
<div id="keyboard_shortcuts_pane" class="instapaper_ignore readability-extra" style="display:none">
<h2>Keyboard Shortcuts <small><a href="#" class="js-see-all-keyboard-shortcuts">(see all)</a></small></h2>
<div class="columns threecols">
<div class="column first">
<h3>Site wide shortcuts</h3>
<dl class="keyboard-mappings">
<dt>s</dt>
<dd>Focus command bar</dd>
</dl>
<dl class="keyboard-mappings">
<dt>?</dt>
<dd>Bring up this help dialog</dd>
</dl>
</div><!-- /.column.first -->
<div class="column middle" style='display:none'>
<h3>Commit list</h3>
<dl class="keyboard-mappings">
<dt>j</dt>
<dd>Move selection down</dd>
</dl>
<dl class="keyboard-mappings">
<dt>k</dt>
<dd>Move selection up</dd>
</dl>
<dl class="keyboard-mappings">
<dt>c <em>or</em> o <em>or</em> enter</dt>
<dd>Open commit</dd>
</dl>
<dl class="keyboard-mappings">
<dt>y</dt>
<dd>Expand URL to its canonical form</dd>
</dl>
</div><!-- /.column.first -->
<div class="column last js-hidden-pane" style='display:none'>
<h3>Pull request list</h3>
<dl class="keyboard-mappings">
<dt>j</dt>
<dd>Move selection down</dd>
</dl>
<dl class="keyboard-mappings">
<dt>k</dt>
<dd>Move selection up</dd>
</dl>
<dl class="keyboard-mappings">
<dt>o <em>or</em> enter</dt>
<dd>Open issue</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> enter</dt>
<dd>Submit comment</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> shift p</dt>
<dd>Preview comment</dd>
</dl>
</div><!-- /.columns.last -->
</div><!-- /.columns.equacols -->
<div class="js-hidden-pane" style='display:none'>
<div class="rule"></div>
<h3>Issues</h3>
<div class="columns threecols">
<div class="column first">
<dl class="keyboard-mappings">
<dt>j</dt>
<dd>Move selection down</dd>
</dl>
<dl class="keyboard-mappings">
<dt>k</dt>
<dd>Move selection up</dd>
</dl>
<dl class="keyboard-mappings">
<dt>x</dt>
<dd>Toggle selection</dd>
</dl>
<dl class="keyboard-mappings">
<dt>o <em>or</em> enter</dt>
<dd>Open issue</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> enter</dt>
<dd>Submit comment</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> shift p</dt>
<dd>Preview comment</dd>
</dl>
</div><!-- /.column.first -->
<div class="column last">
<dl class="keyboard-mappings">
<dt>c</dt>
<dd>Create issue</dd>
</dl>
<dl class="keyboard-mappings">
<dt>l</dt>
<dd>Create label</dd>
</dl>
<dl class="keyboard-mappings">
<dt>i</dt>
<dd>Back to inbox</dd>
</dl>
<dl class="keyboard-mappings">
<dt>u</dt>
<dd>Back to issues</dd>
</dl>
<dl class="keyboard-mappings">
<dt>/</dt>
<dd>Focus issues search</dd>
</dl>
</div>
</div>
</div>
<div class="js-hidden-pane" style='display:none'>
<div class="rule"></div>
<h3>Issues Dashboard</h3>
<div class="columns threecols">
<div class="column first">
<dl class="keyboard-mappings">
<dt>j</dt>
<dd>Move selection down</dd>
</dl>
<dl class="keyboard-mappings">
<dt>k</dt>
<dd>Move selection up</dd>
</dl>
<dl class="keyboard-mappings">
<dt>o <em>or</em> enter</dt>
<dd>Open issue</dd>
</dl>
</div><!-- /.column.first -->
</div>
</div>
<div class="js-hidden-pane" style='display:none'>
<div class="rule"></div>
<h3>Network Graph</h3>
<div class="columns equacols">
<div class="column first">
<dl class="keyboard-mappings">
<dt><span class="badmono">←</span> <em>or</em> h</dt>
<dd>Scroll left</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="badmono">→</span> <em>or</em> l</dt>
<dd>Scroll right</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="badmono">↑</span> <em>or</em> k</dt>
<dd>Scroll up</dd>
</dl>
<dl class="keyboard-mappings">
<dt><span class="badmono">↓</span> <em>or</em> j</dt>
<dd>Scroll down</dd>
</dl>
<dl class="keyboard-mappings">
<dt>t</dt>
<dd>Toggle visibility of head labels</dd>
</dl>
</div><!-- /.column.first -->
<div class="column last">
<dl class="keyboard-mappings">
<dt>shift <span class="badmono">←</span> <em>or</em> shift h</dt>
<dd>Scroll all the way left</dd>
</dl>
<dl class="keyboard-mappings">
<dt>shift <span class="badmono">→</span> <em>or</em> shift l</dt>
<dd>Scroll all the way right</dd>
</dl>
<dl class="keyboard-mappings">
<dt>shift <span class="badmono">↑</span> <em>or</em> shift k</dt>
<dd>Scroll all the way up</dd>
</dl>
<dl class="keyboard-mappings">
<dt>shift <span class="badmono">↓</span> <em>or</em> shift j</dt>
<dd>Scroll all the way down</dd>
</dl>
</div><!-- /.column.last -->
</div>
</div>
<div class="js-hidden-pane" >
<div class="rule"></div>
<div class="columns threecols">
<div class="column first js-hidden-pane" >
<h3>Source Code Browsing</h3>
<dl class="keyboard-mappings">
<dt>t</dt>
<dd>Activates the file finder</dd>
</dl>
<dl class="keyboard-mappings">
<dt>l</dt>
<dd>Jump to line</dd>
</dl>
<dl class="keyboard-mappings">
<dt>w</dt>
<dd>Switch branch/tag</dd>
</dl>
<dl class="keyboard-mappings">
<dt>y</dt>
<dd>Expand URL to its canonical form</dd>
</dl>
</div>
</div>
</div>
<div class="js-hidden-pane" style='display:none'>
<div class="rule"></div>
<div class="columns threecols">
<div class="column first">
<h3>Browsing Commits</h3>
<dl class="keyboard-mappings">
<dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> enter</dt>
<dd>Submit comment</dd>
</dl>
<dl class="keyboard-mappings">
<dt>escape</dt>
<dd>Close form</dd>
</dl>
<dl class="keyboard-mappings">
<dt>p</dt>
<dd>Parent commit</dd>
</dl>
<dl class="keyboard-mappings">
<dt>o</dt>
<dd>Other parent commit</dd>
</dl>
</div>
</div>
</div>
<div class="js-hidden-pane" style='display:none'>
<div class="rule"></div>
<h3>Notifications</h3>
<div class="columns threecols">
<div class="column first">
<dl class="keyboard-mappings">
<dt>j</dt>
<dd>Move selection down</dd>
</dl>
<dl class="keyboard-mappings">
<dt>k</dt>
<dd>Move selection up</dd>
</dl>
<dl class="keyboard-mappings">
<dt>o <em>or</em> enter</dt>
<dd>Open notification</dd>
</dl>
</div><!-- /.column.first -->
<div class="column second">
<dl class="keyboard-mappings">
<dt>e <em>or</em> shift i <em>or</em> y</dt>
<dd>Mark as read</dd>
</dl>
<dl class="keyboard-mappings">
<dt>shift m</dt>
<dd>Mute thread</dd>
</dl>
</div><!-- /.column.first -->
</div>
</div>
</div>
<div id="markdown-help" class="instapaper_ignore readability-extra">
<h2>Markdown Cheat Sheet</h2>
<div class="cheatsheet-content">
<div class="mod">
<div class="col">
<h3>Format Text</h3>
<p>Headers</p>
<pre>
# This is an &lt;h1&gt; tag
## This is an &lt;h2&gt; tag
###### This is an &lt;h6&gt; tag</pre>
<p>Text styles</p>
<pre>
*This text will be italic*
_This will also be italic_
**This text will be bold**
__This will also be bold__
*You **can** combine them*
</pre>
</div>
<div class="col">
<h3>Lists</h3>
<p>Unordered</p>
<pre>
* Item 1
* Item 2
* Item 2a
* Item 2b</pre>
<p>Ordered</p>
<pre>
1. Item 1
2. Item 2
3. Item 3
* Item 3a
* Item 3b</pre>
</div>
<div class="col">
<h3>Miscellaneous</h3>
<p>Images</p>
<pre>
![GitHub Logo](/images/logo.png)
Format: ![Alt Text](url)
</pre>
<p>Links</p>
<pre>
http://github.com - automatic!
[GitHub](http://github.com)</pre>
<p>Blockquotes</p>
<pre>
As Kanye West said:
> We're living the future so
> the present is our past.
</pre>
</div>
</div>
<div class="rule"></div>
<h3>Code Examples in Markdown</h3>
<div class="col">
<p>Syntax highlighting with <a href="http://github.github.com/github-flavored-markdown/" title="GitHub Flavored Markdown" target="_blank">GFM</a></p>
<pre>
```javascript
function fancyAlert(arg) {
if(arg) {
$.facebox({div:'#foo'})
}
}
```</pre>
</div>
<div class="col">
<p>Or, indent your code 4 spaces</p>
<pre>
Here is a Python code example
without syntax highlighting:
def foo:
if not bar:
return true</pre>
</div>
<div class="col">
<p>Inline code for comments</p>
<pre>
I think you should use an
`&lt;addr&gt;` element here instead.</pre>
</div>
</div>
</div>
</div>
<div id="ajax-error-message" class="flash flash-error">
<span class="mini-icon mini-icon-exclamation"></span>
Something went wrong with that request. Please try again.
<a href="#" class="mini-icon mini-icon-remove-close ajax-error-dismiss"></a>
</div>
<span id='server_response_time' data-time='0.07212' data-host='fe16'></span>
</body>
</html>
+1 -1
View File
@@ -3,4 +3,4 @@
* Copyright 2012 Twitter, Inc.
* http://www.apache.org/licenses/LICENSE-2.0.txt
*/
!function(e){e(function(){"use strict";e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()},e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e(function(){e("body").on("click.alert.data-api",t,n.prototype.close)})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")},e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e(function(){e("body").on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=n,this.options.slide&&this.slide(this.options.slide),this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},to:function(t){var n=this.$element.find(".item.active"),r=n.parent().children(),i=r.index(n),s=this;if(t>r.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){s.to(t)}):i==t?this.pause().cycle():this.slide(t>i?"next":"prev",e(r[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle()),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f=e.Event("slide",{relatedTarget:i[0]});this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u]();if(i.hasClass("active"))return;if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}},e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e(function(){e("body").on("click.carousel.data-api","[data-slide]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=!i.data("modal")&&e.extend({},i.data(),n.data());i.carousel(s),t.preventDefault()})})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hLine truncated
!function($){"use strict";$(function(){$.support.transition=function(){var transitionEnd=function(){var name,el=document.createElement("bootstrap"),transEndEventNames={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(name in transEndEventNames)if(void 0!==el.style[name])return transEndEventNames[name]}();return transitionEnd&&{end:transitionEnd}}()})}(window.jQuery),!function($){"use strict";var dismiss='[data-dismiss="alert"]',Alert=function(el){$(el).on("click",dismiss,this.close)};Alert.prototype.close=function(e){function removeElement(){$parent.trigger("closed").remove()}var $parent,$this=$(this),selector=$this.attr("data-target");selector||(selector=$this.attr("href"),selector=selector&&selector.replace(/.*(?=#[^\s]*$)/,"")),$parent=$(selector),e&&e.preventDefault(),$parent.length||($parent=$this.hasClass("alert")?$this:$this.parent()),$parent.trigger(e=$.Event("close")),e.isDefaultPrevented()||($parent.removeClass("in"),$.support.transition&&$parent.hasClass("fade")?$parent.on($.support.transition.end,removeElement):removeElement())};var old=$.fn.alert;$.fn.alert=function(option){return this.each(function(){var $this=$(this),data=$this.data("alert");data||$this.data("alert",data=new Alert(this)),"string"==typeof option&&data[option].call($this)})},$.fn.alert.Constructor=Alert,$.fn.alert.noConflict=function(){return $.fn.alert=old,this},$(document).on("click.alert.data-api",dismiss,Alert.prototype.close)}(window.jQuery),!function($){"use strict";var Button=function(element,options){this.$element=$(element),this.options=$.extend({},$.fn.button.defaults,options)};Button.prototype.setState=function(state){var d="disabled",$el=this.$element,data=$el.data(),val=$el.is("input")?"val":"html";state+="Text",data.resetText||$el.data("resetText",$el[val]()),$el[val](data[state]||this.options[state]),setTimeout(function(){"loadingText"==state?$el.addClass(d).attr(d,d):$el.removeClass(d).removeAttr(d)},0)},Button.prototype.toggle=function(){var $parent=this.$element.closest('[data-toggle="buttons-radio"]');$parent&&$parent.find(".active").removeClass("active"),this.$element.toggleClass("active")};var old=$.fn.button;$.fn.button=function(option){return this.each(function(){var $this=$(this),data=$this.data("button"),options="object"==typeof option&&option;data||$this.data("button",data=new Button(this,options)),"toggle"==option?data.toggle():option&&data.setState(option)})},$.fn.button.defaults={loadingText:"loading..."},$.fn.button.Constructor=Button,$.fn.button.noConflict=function(){return $.fn.button=old,this},$(document).on("click.button.data-api","[data-toggle^=button]",function(e){var $btn=$(e.target);$btn.hasClass("btn")||($btn=$btn.closest(".btn")),$btn.button("toggle")})}(window.jQuery),!function($){"use strict";var Carousel=function(element,options){this.$element=$(element),this.options=options,"hover"==this.options.pause&&this.$element.on("mouseenter",$.proxy(this.pause,this)).on("mouseleave",$.proxy(this.cycle,this))};Carousel.prototype={cycle:function(e){return e||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval($.proxy(this.next,this),this.options.interval)),this},to:function(pos){var $active=this.$element.find(".item.active"),children=$active.parent().children(),activePos=children.index($active),that=this;if(!(pos>children.length-1||0>pos))return this.sliding?this.$element.one("slid",function(){that.to(pos)}):activePos==pos?this.pause().cycle():this.slide(pos>activePos?"next":"prev",$(children[pos]))},pause:function(e){return e||(this.paused=!0),this.$element.find(".next, .prev").length&&$.support.transition.end&&(this.$element.trigger($.support.transition.end),this.cycle()),clearInterval(this.interval),this.interval=null,this},next:function(){return this.sliding?void 0:this.slide("next")},prev:function(){return this.sliding?void 0:this.slide("prev")},slide:function(type,next){var e,$active=this.$element.find(".item.active"),$next=next||$active[type](),isCycling=this.interval,direction="next"==type?"left":"right",fallback="next"==type?"first":"last",that=this;if(this.sliding=!0,isCycling&&this.pause(),$next=$next.length?$next:this.$element.find(".item")[fallback](),e=$.Event("slide",{relatedTarget:$next[0]}),!$next.hasClass("active")){if($.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(e),e.isDefaultPrevented())return;$next.addClass(type),$next[0].offsetWidth,$active.addClass(direction),$next.addClass(direction),this.$element.one($.support.transition.end,function(){$next.removeClass([type,direction].join(" ")).addClass("active"),$active.removeClass(["active",direction].join(" ")),that.sliding=!1,setTimeout(function(){that.$element.trigger("slid")},0)})}else{if(this.$element.trigger(e),e.isDefaultPrevented())return;$active.removeClass("active"),$next.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return isCycling&&this.cycle()Line truncated
+2 -2
View File
@@ -1,2 +1,2 @@
/*! jQuery v@1.8.0 jquery.com | jquery.org/license */
(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bX(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bV.length;while(e--){b=bV[e]+c;if(b in a)return b}return d}function bY(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function bZ(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bY(c)&&(e[f]=p._data(c,"olddisplay",cb(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b$(a,b,c){var d=bO.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function b_(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bU[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bU[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bU[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bU[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bU[e]+"Width"))||0));return f}function ca(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bP.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+b_(a,b,c||(f?"border":"content"),e)+"px"}function cb(a){if(bR[a])return bR[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bR[a]=c,c}function ch(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||cd.test(a)?d(a,e):ch(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ch(a+"["+e+"]",b[e],c,d);else d(a,b)}function cy(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cz(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cu;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cz(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cz(a,c,d,e,"*",g)),h}function cA(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((fLine truncated
/*! jQuery v1.8.3 jquery.com | jquery.org/license */
(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r<i;r++)v.event.add(t,n,u[n][r])}o.data&&(o.data=v.extend({},o.data))}function Ot(e,t){var n;if(t.nodeType!==1)return;t.clearAttributes&&t.clearAttributes(),t.mergeAttributes&&t.mergeAttributes(e),n=t.nodeName.toLowerCase(),n==="object"?(t.parentNode&&(t.outerHTML=e.outerHTML),v.support.html5Clone&&e.innerHTML&&!v.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):n==="input"&&Et.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):n==="option"?t.selected=e.defaultSelected:n==="input"||n==="textarea"?t.defaultValue=e.defaultValue:n==="script"&&t.text!==e.text&&(t.text=e.text),t.removeAttribute(v.expando)}function Mt(e){return typeof e.getElementsByTagName!="undefined"?e.getElementsByTagName("*"):typeof e.querySelectorAll!="undefined"?e.querySelectorAll("*"):[]}function _t(e){Et.test(e.type)&&(e.defaultChecked=e.checked)}function Qt(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Jt.length;while(i--){t=Jt[i]+n;if(t in e)return t}return r}function Gt(e,t){return e=t||e,v.css(e,"display")==="none"||!v.contains(e.ownerDocument,e)}function Yt(e,t){var n,r,i=[],s=0,o=e.length;for(;s<o;s++){n=e[s];if(!n.style)continue;i[s]=v._data(n,"olddisplay"),t?(!i[s]&&n.style.display==="none"&&(n.style.display=""),n.style.display===""&&Gt(n)&&(i[s]=v._data(n,"olddisplay",nn(n.nodeName)))):(r=Dt(n,"display"),!i[s]&&r!=="none"&&v._data(n,"olddisplay",r))}for(s=0;s<o;s++){n=e[s];if(!n.style)continue;if(!t||n.style.display==="none"||n.style.display==="")n.style.display=t?i[s]||"":"none"}return e}function Zt(e,t,n){var r=Rt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function en(e,t,n,r){var i=n===(r?"border":"content")?4:t==="width"?1:0,s=0;for(;i<4;i+=2)n==="margin"&&(s+=v.css(e,n+$t[i],!0)),r?(n==="content"&&(s-=parseFloat(Dt(e,"padding"+$t[i]))||0),n!=="margin"&&(s-=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0)):(s+=parseFloat(Dt(e,"padding"+$t[i]))||0,n!=="padding"&&(s+=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0));return s}function tn(e,t,n){var r=t==="width"?e.offsetWidth:e.offsetHeight,i=!0,s=v.support.boxSizing&&v.css(e,"boxSizing")==="border-box";if(r<=0||r==null){r=Dt(e,t);if(r<0||r==null)r=e.style[t];if(Ut.test(r))return r;i=s&&(v.support.boxSizingReliable||r===e.style[t]),r=parseFloat(r)||0}return r+en(e,t,n||(s?"border":"content"),i)+"px"}function nn(e){if(Wt[e])return Wt[e];var t=v("<"+e+">").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write("<!doctype html><html><body>"),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u<a;u++)r=o[u],s=/^\+/.test(r),s&&(r=r.substr(1)||"*"),i=e[r]=e[r]||[],i[s?"unshift":"push"](n)}}function kn(e,n,r,i,s,o){s=s||n.dataTypes[0],o=o||{},o[s]=!0;var u,a=e[s],f=0,l=a?a.length:0,c=e===Sn;for(;f<l&&(c||!u);f++)u=a[f](n,r,i),typeof u=="string"&&(!c||o[u]?u=t:(n.dataTypes.unshift(u),u=kn(e,n,r,i,u,o)));return(c||!u)&&!o["*"]&&(u=kn(e,n,r,i,"*",o)),u}function Ln(e,n){var r,i,s=v.ajaxSettings.flatOptions||{};for(r in n)n[r]Line truncated
@@ -1,4 +1,4 @@
/* Modernizr 2.0.6 (Custom Build) | MIT & BSD
* Build: http://www.modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-iepp-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
* Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-flexboxlegacy-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
*/
;window.Modernizr=function(a,b,c){function H(){e.input=function(a){for(var b=0,c=a.length;b<c;b++)t[a[b]]=a[b]in l;return t}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)l.setAttribute("type",f=a[d]),e=l.type!=="text",e&&(l.value=m,l.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&l.style.WebkitAppearance!==c?(g.appendChild(l),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(l,null).WebkitAppearance!=="textfield"&&l.offsetHeight!==0,g.removeChild(l)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=l.checkValidity&&l.checkValidity()===!1:/^color$/.test(f)?(g.appendChild(l),g.offsetWidth,e=l.value!=m,g.removeChild(l)):e=l.value!=m)),s[a[d]]=!!e;return s}("search tel url email datetime date month week time datetime-local number range color".split(" "))}function F(a,b){var c=a.charAt(0).toUpperCase()+a.substr(1),d=(a+" "+p.join(c+" ")+c).split(" ");return E(d,b)}function E(a,b){for(var d in a)if(k[a[d]]!==c)return b=="pfx"?a[d]:!0;return!1}function D(a,b){return!!~(""+a).indexOf(b)}function C(a,b){return typeof a===b}function B(a,b){return A(o.join(a+";")+(b||""))}function A(a){k.cssText=a}var d="2.0.6",e={},f=!0,g=b.documentElement,h=b.head||b.getElementsByTagName("head")[0],i="modernizr",j=b.createElement(i),k=j.style,l=b.createElement("input"),m=":)",n=Object.prototype.toString,o=" -webkit- -moz- -o- -ms- -khtml- ".split(" "),p="Webkit Moz O ms Khtml".split(" "),q={svg:"http://www.w3.org/2000/svg"},r={},s={},t={},u=[],v=function(a,c,d,e){var f,h,j,k=b.createElement("div");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:i+(d+1),k.appendChild(j);f=["&shy;","<style>",a,"</style>"].join(""),k.id=i,k.innerHTML+=f,g.appendChild(k),h=c(k,a),k.parentNode.removeChild(k);return!!h},w=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=C(e[d],"function"),C(e[d],c)||(e[d]=c),e.removeAttribute(d))),e=null;return f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),x,y={}.hasOwnProperty,z;!C(y,c)&&!C(y.call,c)?z=function(a,b){return y.call(a,b)}:z=function(a,b){return b in a&&C(a.constructor.prototype[b],c)};var G=function(c,d){var f=c.join(""),g=d.length;v(f,function(c,d){var f=b.styleSheets[b.styleSheets.length-1],h=f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"",i=c.childNodes,j={};while(g--)j[i[g].id]=i[g];e.touch="ontouchstart"in a||j.touch.offsetTop===9,e.csstransforms3d=j.csstransforms3d.offsetLeft===9,e.generatedcontent=j.generatedcontent.offsetHeight>=1,e.fontface=/src/i.test(h)&&h.indexOf(d.split(" ")[0])===0},g,d)}(['@font-face {font-family:"font";src:url("https://")}',["@media (",o.join("touch-enabled),("),i,")","{#touch{top:9px;position:absolute}}"].join(""),["@media (",o.join("transform-3d),("),i,")","{#csstransforms3d{left:9px;position:absolute}}"].join(""),['#generatedcontent:after{content:"',m,'";visibility:hidden}'].join("")],["fontface","touch","csstransforms3d","generatedcontent"]);r.flexbox=function(){function c(a,b,c,d){a.style.cssText=o.join(b+":"+c+";")+(d||"")}function a(a,b,c,d){b+=":",a.style.cssText=(b+o.join(c+";"+b)).slice(0,-b.length)+(d||"")}var d=b.createElement("div"),e=b.createElement("div");a(d,"display","box","width:42px;padding:0;"),c(e,"box-flex","1","width:10px;"),d.appendChild(e),g.appendChild(d);var f=e.offsetWidth===42;d.removeChild(e),g.removeChild(d);return f},r.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},r.canvastext=function(){return!!e.canvas&&!!C(b.createElement("canvas").getContext("2d").fillText,"function")},r.webgl=function(){return!!a.WebGLRenderingContext},r.touch=function(){return e.touch},r.geolocation=function(){return!!navigator.geolocation},r.postmessage=function(){return!!a.postMessage},r.websqldatabase=function(){var b=!!a.openDatabase;return b},r.indexedDB=function(){for(var b=-1,c=p.length;++b<c;)if(a[p[b].toLowerCase()+"IndexedDB"])return!0;return!!a.indexedDB},r.hashchange=function(){return w("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},r.history=function(){return!!a.history&&!!history.pushState},r.draganddrop=function(){return w("dragstart")&&w("drop")},r.websockets=function(){for(var b=-1,c=p.length;++b<c;)if(a[p[b]+"WebSocket"])return!0;return"WebSocket"in a},r.rgba=function(){A("background-color:rgba(150,255,150,.5)");return D(k.backgroundColor,"rgba")},r.hsla=function(){A("background-color:hsla(120,40%,100%,.5)");return D(k.backgroundColor,"rgba")||D(k.backgroundColor,"hsla")},r.multiplebgs=function(){A("background:url(https://),url(https://),red url(https://)");return/(url\s*\(.*?){3}/.test(k.background)},r.backgroundsize=function(){return F("backgroundSize")},r.borderimage=function(){return F("borderImage")},r.borderradiLine truncated
;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)u[c[d]]=c[d]in k;return u.list&&(u.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),u}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)k.setAttribute("type",f=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&k.style.WebkitAppearance!==c?(g.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,g.removeChild(k)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=k.checkValidity&&k.checkValidity()===!1:e=k.value!=l)),t[a[d]]=!!e;return t}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m={}.toString,n=" -webkit- -moz- -o- -ms- ".split(" "),o="Webkit Moz O ms",p=o.split(" "),q=o.toLowerCase().split(" "),r={svg:"http://www.w3.org/2000/svg"},s={},t={},u={},v=[],w=v.slice,x,y=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.flexboxlegacy=function(){return J("boxDirection")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){retuLine truncated
+2 -2
View File
@@ -16,7 +16,7 @@ jQuery(function(){
return match && decodeURIComponent(match[1].replace(/\+/g, ' '))||default_value;
}
var path = params('static','social');
var url = window.location.href;
var url = encodeURIComponent(window.location.href);
var host = window.location.hostname;
var title = escape(jQuery('title').text());
var twit = 'http://twitter.com/home?status='+title+'%20'+url;
@@ -27,7 +27,7 @@ jQuery(function(){
jQuery('body').append(tbar);
var st = jQuery('#socialdrawer');
st.css({'opacity':'.7','z-index':'3000','background':'#FFF','border':'solid 1px #666','border-width':' 1px 0 0 1px','height':'20px','width':'40px','position':'fixed','bottom':'0','right':'0','padding':'2px 5px','overflow':'hidden','-webkit-border-top-left-radius':' 12px','-moz-border-radius-topleft':' 12px','border-top-left-radius':' 12px','-moz-box-shadow':' -3px -3px 3px rgba(0,0,0,0.5)','-webkit-box-shadow':' -3px -3px 3px rgba(0,0,0,0.5)','box-shadow':' -3px -3px 3px rgba(0,0,0,0.5)'});
jQuery('#socialdrawer a').css({'float':'left','width':'32px','margin':'3px 2px 2px 2px','padding':'0'});
jQuery('#socialdrawer a').css({'float':'left','width':'32px','margin':'3px 2px 2px 2px','padding':'0','cursor':'pointer'});
jQuery('#socialdrawer span').css({'float':'left','margin':'2px 3px','text-shadow':' 1px 1px 1px #FFF','color':'#444','font-size':'12px','line-height':'1em'});
jQuery('#socialdrawer img').hide();
// hover
+10 -4
View File
@@ -55,7 +55,7 @@ function web2py_event_handlers() {
jQuery(function() {
var flash = jQuery('.flash');
flash.hide();
if(flash.html()) flash.append('<span style="float:right;">&times;</span>').slideDown();
if(flash.html()) flash.append('<span id="closeflash">&times;</span>').slideDown();
web2py_ajax_init(document);
web2py_event_handlers();
});
@@ -102,15 +102,20 @@ function web2py_ajax_page(method, action, data, target) {
web2py_ajax_init('#'+target);
if(command)
eval(decodeURIComponent(command));
if(flash)
jQuery('.flash').html(decodeURIComponent(flash)).slideDown();
if(flash) {
jQuery('.flash')
.html(decodeURIComponent(flash))
.append('<span id="closeflash">&times;</span>')
.slideDown();
}
}
});
}
function web2py_component(action, target, timeout, times){
jQuery(function(){
var element = jQuery("#" + target).get(0);
var jelement = jQuery("#" + target);
var element = jelement.get(0);
var statement = "jQuery('#" + target + "').get(0).reload();";
element.reload = function (){
// Continue if times is Infinity or
@@ -119,6 +124,7 @@ function web2py_component(action, target, timeout, times){
web2py_ajax_page('get', action, null, target);} }; // reload
// Method to check timing limit
element.reload_check = function (){
if (jelement.hasClass('w2p_component_stop')) {return false;}
if (this.reload_counter == Infinity){return true;}
else {
if (!isNaN(this.reload_counter)){
+1 -1
View File
@@ -1 +1 @@
<?xml version="1.0" encoding="ISO-8859-1"?>{{from gluon.serializers import xml}}{{=XML(xml(response._vars,quote=False))}}
{{from gluon.serializers import xml}}{{=XML(xml(response._vars,quote=False))}}
+10 -3
View File
@@ -29,7 +29,7 @@
device-width: Occupy full width of the screen in its current orientation
initial-scale = 1.0 retains dimensions instead of zooming out if page height > device height
user-scalable = yes allows the user to zoom in -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="shortcut icon" href="{{=URL('static','images/favicon.ico')}}" type="image/x-icon">
<link rel="apple-touch-icon" href="{{=URL('static','images/favicon.png')}}">
@@ -76,7 +76,7 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="brand" href="http://www.web2py.com/"><b>web<span>2</span>py</b>&trade;&nbsp;</a>
{{=response.logo or ''}}
<ul id="navbar" class="nav pull-right">{{='auth' in globals() and auth.navbar(mode="dropdown") or ''}}</ul>
<div class="nav-collapse">
{{is_mobile=request.user_agent().is_mobile}}
@@ -152,7 +152,14 @@
<script src="{{=URL('static','js/dd_belatedpng.js')}}"></script>
<script> DD_belatedPNG.fix('img, .png_bg'); //fix any <img> or .png_bg background-images </script>
<![endif]-->
{{if response.google_analytics_id:}}<script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', '{{=response.google_analytics_id}}']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script> {{pass}}
{{if response.google_analytics_id:}}
<script src="{{=URL('static','js/analytics.js')}}"></script>
<script type="text/javascript">
analytics.initialize({
'Google Analytics':{trackingId:'{{=response.google_analytics_id}}'}
});</script>
{{pass}}
<script src="{{=URL('static','js/share.js',vars=dict(static=URL('static','images')))}}"></script>
</body>
</html>
+1 -6
View File
@@ -56,13 +56,8 @@ import wsgiref.handlers
path = os.path.dirname(os.path.abspath(__file__))
os.chdir(path)
sys.path = [path]+[p for p in sys.path if not p==path]
sys.path = [path] + [p for p in sys.path if not p == path]
import gluon.main
wsgiref.handlers.CGIHandler().run(gluon.main.wsgibase)
+1 -6
View File
@@ -34,7 +34,7 @@ import os
path = os.path.dirname(os.path.abspath(__file__))
os.chdir(path)
sys.path = [path]+[p for p in sys.path if not p==path]
sys.path = [path] + [p for p in sys.path if not p == path]
import gluon.main
import gluon.contrib.gateways.fcgi as fcgi
@@ -51,8 +51,3 @@ if SOFTCRON:
global_settings.web2py_crontype = 'soft'
fcgi.WSGIServer(application, bindAddress='/tmp/fcgi.sock').run()
+8 -6
View File
@@ -33,7 +33,7 @@ import wsgiref.handlers
import datetime
path = os.path.dirname(os.path.abspath(__file__))
sys.path = [path]+[p for p in sys.path if not p==path]
sys.path = [path] + [p for p in sys.path if not p == path]
sys.modules['cPickle'] = sys.modules['pickle']
@@ -78,6 +78,12 @@ def wsgiapp(env, res):
"""Return the wsgiapp"""
env['PATH_INFO'] = env['PATH_INFO'].decode('latin1').encode('utf8')
#when using the blobstore image uploader GAE dev SDK passes these as unicode
# they should be regular strings as they are parts of URLs
env['wsgi.url_scheme'] = str(env['wsgi.url_scheme'])
env['QUERY_STRING'] = str(env['QUERY_STRING'])
env['SERVER_NAME'] = str(env['SERVER_NAME'])
#this deals with a problem where GAE development server seems to forget
# the path between requests
if global_settings.web2py_runtime == 'gae:development':
@@ -91,14 +97,10 @@ def wsgiapp(env, res):
if LOG_STATS or DEBUG:
wsgiapp = log_stats(wsgiapp)
def main():
"""Run the wsgi app"""
run_wsgi_app(wsgiapp)
if __name__ == '__main__':
main()
+1 -12
View File
@@ -10,7 +10,7 @@ Web2Py framework modules
========================
"""
__all__ = ['A', 'B', 'BEAUTIFY', 'BODY', 'BR', 'CAT', 'CENTER', 'CLEANUP', 'CODE', 'CRYPT', 'DAL', 'DIV', 'EM', 'EMBED', 'FIELDSET', 'FORM', 'Field', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'HEAD', 'HR', 'HTML', 'HTTP', 'I', 'IFRAME', 'IMG', 'INPUT', 'IS_ALPHANUMERIC', 'IS_DATE', 'IS_DATETIME', 'IS_DATETIME_IN_RANGE', 'IS_DATE_IN_RANGE', 'IS_DECIMAL_IN_RANGE', 'IS_EMAIL', 'IS_EMPTY_OR', 'IS_EQUAL_TO', 'IS_EXPR', 'IS_FLOAT_IN_RANGE', 'IS_IMAGE', 'IS_INT_IN_RANGE', 'IS_IN_DB', 'IS_IN_SET', 'IS_IPV4', 'IS_LENGTH', 'IS_LIST_OF', 'IS_LOWER', 'IS_MATCH', 'IS_NOT_EMPTY', 'IS_NOT_IN_DB', 'IS_NULL_OR', 'IS_SLUG', 'IS_STRONG', 'IS_TIME', 'IS_UPLOAD_FILENAME', 'IS_UPPER', 'IS_URL', 'LABEL', 'LEGEND', 'LI', 'LINK', 'LOAD', 'MARKMIN', 'MENU', 'META', 'OBJECT', 'OL', 'ON', 'OPTGROUP', 'OPTION', 'P', 'PRE', 'SCRIPT', 'SELECT', 'SPAN', 'SQLFORM', 'SQLTABLE', 'STRONG', 'STYLE', 'TABLE', 'TAG', 'TBODY', 'TD', 'TEXTAREA', 'TFOOT', 'TH', 'THEAD', 'TITLE', 'TR', 'TT', 'UL', 'URL', 'XHTML', 'XML','redirect','current','embed64']
__all__ = ['A', 'B', 'BEAUTIFY', 'BODY', 'BR', 'CAT', 'CENTER', 'CLEANUP', 'CODE', 'CRYPT', 'DAL', 'DIV', 'EM', 'EMBED', 'FIELDSET', 'FORM', 'Field', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'HEAD', 'HR', 'HTML', 'HTTP', 'I', 'IFRAME', 'IMG', 'INPUT', 'IS_ALPHANUMERIC', 'IS_DATE', 'IS_DATETIME', 'IS_DATETIME_IN_RANGE', 'IS_DATE_IN_RANGE', 'IS_DECIMAL_IN_RANGE', 'IS_EMAIL', 'IS_EMPTY_OR', 'IS_EQUAL_TO', 'IS_EXPR', 'IS_FLOAT_IN_RANGE', 'IS_IMAGE', 'IS_INT_IN_RANGE', 'IS_IN_DB', 'IS_IN_SET', 'IS_IPV4', 'IS_LENGTH', 'IS_LIST_OF', 'IS_LOWER', 'IS_MATCH', 'IS_NOT_EMPTY', 'IS_NOT_IN_DB', 'IS_NULL_OR', 'IS_SLUG', 'IS_STRONG', 'IS_TIME', 'IS_UPLOAD_FILENAME', 'IS_UPPER', 'IS_URL', 'LABEL', 'LEGEND', 'LI', 'LINK', 'LOAD', 'MARKMIN', 'MENU', 'META', 'OBJECT', 'OL', 'ON', 'OPTGROUP', 'OPTION', 'P', 'PRE', 'SCRIPT', 'SELECT', 'SPAN', 'SQLFORM', 'SQLTABLE', 'STRONG', 'STYLE', 'TABLE', 'TAG', 'TBODY', 'TD', 'TEXTAREA', 'TFOOT', 'TH', 'THEAD', 'TITLE', 'TR', 'TT', 'UL', 'URL', 'XHTML', 'XML', 'redirect', 'current', 'embed64']
from globals import current
from html import *
@@ -42,14 +42,3 @@ if 0:
mail = Mail()
service = Service()
plugins = PluginManager()
+31 -24
View File
@@ -23,6 +23,7 @@ from http import HTTP
if not global_settings.web2py_runtime_gae:
import site
def apath(path='', r=None):
"""
Builds a path inside an application folder
@@ -95,6 +96,7 @@ def app_pack_compiled(app, request, raise_ex=False):
raise
return None
def app_cleanup(app, request):
"""
Removes session, cache and error files
@@ -113,7 +115,7 @@ def app_cleanup(app, request):
if os.path.exists(path):
for f in os.listdir(path):
try:
if f[:1]!='.': os.unlink(os.path.join(path,f))
if f[:1] != '.': os.unlink(os.path.join(path, f))
except IOError:
r = False
@@ -122,7 +124,7 @@ def app_cleanup(app, request):
if os.path.exists(path):
for f in os.listdir(path):
try:
if f[:1]!='.': recursive_unlink(os.path.join(path,f))
if f[:1] != '.': recursive_unlink(os.path.join(path, f))
except IOError:
r = False
@@ -131,7 +133,7 @@ def app_cleanup(app, request):
if os.path.exists(path):
for f in os.listdir(path):
try:
if f[:1]!='.': os.unlink(os.path.join(path,f))
if f[:1] != '.': os.unlink(os.path.join(path, f))
except IOError:
r = False
return r
@@ -158,7 +160,8 @@ def app_compile(app, request):
remove_compiled_application(folder)
return tb
def app_create(app, request,force=False,key=None,info=False):
def app_create(app, request, force=False, key=None, info=False):
"""
Create a copy of welcome.w2p (scaffolding) app
@@ -186,17 +189,18 @@ def app_create(app, request,force=False,key=None,info=False):
return False
try:
w2p_unpack('welcome.w2p', path)
for subfolder in ['models','views','controllers', 'databases',
'modules','cron','errors','sessions',
'languages','static','private','uploads']:
subpath = os.path.join(path,subfolder)
for subfolder in [
'models', 'views', 'controllers', 'databases',
'modules', 'cron', 'errors', 'sessions', 'cache',
'languages', 'static', 'private', 'uploads']:
subpath = os.path.join(path, subfolder)
if not os.path.exists(subpath):
os.mkdir(subpath)
db = os.path.join(path, 'models', 'db.py')
if os.path.exists(db):
data = read_file(db)
data = data.replace('<your secret key>',
'sha512:'+(key or web2py_uuid()))
'sha512:' + (key or web2py_uuid()))
write_file(db, data)
if info:
return True, None
@@ -283,6 +287,7 @@ def app_uninstall(app, request):
except Exception:
return False
def plugin_pack(app, plugin_name, request):
"""
Builds a w2p package for the application
@@ -302,12 +307,14 @@ def plugin_pack(app, plugin_name, request):
filename of the w2p file or None on error
"""
try:
filename = apath('../deposit/web2py.plugin.%s.w2p' % plugin_name, request)
filename = apath(
'../deposit/web2py.plugin.%s.w2p' % plugin_name, request)
w2p_pack_plugin(filename, apath(app, request), plugin_name)
return filename
except Exception:
return False
def plugin_install(app, fobj, request, filename):
"""
Installs an application:
@@ -345,6 +352,7 @@ def plugin_install(app, fobj, request, filename):
os.unlink(upname)
return False
def check_new_version(myversion, version_URL):
"""
Compares current web2py's version with the latest stable web2py version.
@@ -375,6 +383,7 @@ def check_new_version(myversion, version_URL):
else:
return False, version
def unzip(filename, dir, subfolder=''):
"""
Unzips filename into dir (.zip only, no .gz etc)
@@ -382,7 +391,7 @@ def unzip(filename, dir, subfolder=''):
"""
filename = abspath(filename)
if not zipfile.is_zipfile(filename):
raise RuntimeError, 'Not a valid zipfile'
raise RuntimeError('Not a valid zipfile')
zf = zipfile.ZipFile(filename)
if not subfolder.endswith('/'):
subfolder = subfolder + '/'
@@ -392,7 +401,7 @@ def unzip(filename, dir, subfolder=''):
continue
#print name[n:]
if name.endswith('/'):
folder = os.path.join(dir,name[n:])
folder = os.path.join(dir, name[n:])
if not os.path.exists(folder):
os.mkdir(folder)
else:
@@ -421,7 +430,7 @@ def upgrade(request, url='http://web2py.com'):
if not gluon_parent.endswith('/'):
gluon_parent = gluon_parent + '/'
(check, version) = check_new_version(web2py_version,
url+'/examples/default/version')
url + '/examples/default/version')
if not check:
return (False, 'Already latest version')
if os.path.exists(os.path.join(gluon_parent, 'web2py.exe')):
@@ -442,28 +451,33 @@ def upgrade(request, url='http://web2py.com'):
file = None
try:
write_file(filename, urllib.urlopen(full_url).read(), 'wb')
except Exception,e:
except Exception, e:
return False, e
try:
unzip(filename, destination, subfolder)
return True, None
except Exception,e:
except Exception, e:
return False, e
def add_path_first(path):
sys.path = [path]+[p for p in sys.path if (not p==path and not p==(path+'/'))]
sys.path = [path] + [p for p in sys.path if (
not p == path and not p == (path + '/'))]
if not global_settings.web2py_runtime_gae:
site.addsitedir(path)
def create_missing_folders():
if not global_settings.web2py_runtime_gae:
for path in ('applications', 'deposit', 'site-packages', 'logs'):
path = abspath(path, gluon=True)
if not os.path.exists(path):
os.mkdir(path)
paths = (global_settings.gluon_parent, abspath('site-packages', gluon=True), abspath('gluon', gluon=True), '')
paths = (global_settings.gluon_parent, abspath(
'site-packages', gluon=True), abspath('gluon', gluon=True), '')
[add_path_first(path) for path in paths]
def create_missing_app_folders(request):
if not global_settings.web2py_runtime_gae:
if request.folder not in global_settings.app_folders:
@@ -474,10 +488,3 @@ def create_missing_app_folders(request):
if not os.path.exists(path):
os.mkdir(path)
global_settings.app_folders.add(request.folder)
+46 -35
View File
@@ -40,6 +40,7 @@ __all__ = ['Cache', 'lazy_cache']
DEFAULT_TIME_EXPIRE = 300
class CacheAbstract(object):
"""
Abstract class for cache implementations.
@@ -73,7 +74,7 @@ class CacheAbstract(object):
raise NotImplementedError
def __call__(self, key, f,
time_expire = DEFAULT_TIME_EXPIRE):
time_expire=DEFAULT_TIME_EXPIRE):
"""
Tries retrieve the value corresponding to `key` from the cache of the
object exists and if it did not expire, else it called the function `f`
@@ -130,6 +131,7 @@ class CacheAbstract(object):
if r.match(str(key)):
del storage[key]
class CacheInRam(CacheAbstract):
"""
Ram based caching
@@ -145,10 +147,13 @@ class CacheInRam(CacheAbstract):
def __init__(self, request=None):
self.initialized = False
self.request = request
self.storage = {}
def initialize(self):
if self.initialized: return
else: self.initialized = True
if self.initialized:
return
else:
self.initialized = True
self.locker.acquire()
request = self.request
if request:
@@ -172,13 +177,14 @@ class CacheInRam(CacheAbstract):
self._clear(storage, regex)
if not CacheAbstract.cache_stats_name in storage.keys():
storage[CacheAbstract.cache_stats_name] = {'hit_total': 0,'misses': 0}
storage[CacheAbstract.cache_stats_name] = {
'hit_total': 0, 'misses': 0}
self.locker.release()
def __call__(self, key, f,
time_expire = DEFAULT_TIME_EXPIRE,
destroyer = None):
time_expire=DEFAULT_TIME_EXPIRE,
destroyer=None):
"""
Attention! cache.ram does not copy the cached object. It just stores a reference to it.
Turns out the deepcopying the object has some problems:
@@ -269,14 +275,15 @@ class CacheOnDisk(CacheAbstract):
try:
storage = shelve.open(self.shelve_name)
except:
logger.error('corrupted cache file %s, will try rebuild it' \
logger.error('corrupted cache file %s, will try rebuild it'
% (self.shelve_name))
storage = None
if not storage and os.path.exists(self.shelve_name):
os.unlink(self.shelve_name)
storage = shelve.open(self.shelve_name)
if not CacheAbstract.cache_stats_name in storage.keys():
storage[CacheAbstract.cache_stats_name] = {'hit_total':0, 'misses': 0}
storage[CacheAbstract.cache_stats_name] = {
'hit_total': 0, 'misses': 0}
storage.sync()
except Exception, e:
if storage:
@@ -286,7 +293,8 @@ class CacheOnDisk(CacheAbstract):
portalocker.unlock(locker)
locker.close()
locked = False
raise RuntimeError, 'unable to create/re-create cache file %s' % self.shelve_name
raise RuntimeError(
'unable to create/re-create cache file %s' % self.shelve_name)
self.locker = locker
self.locked = locked
self.storage = storage
@@ -296,10 +304,13 @@ class CacheOnDisk(CacheAbstract):
self.initialized = False
self.request = request
self.folder = folder
self.storage = {}
def initialize(self):
if self.initialized: return
else: self.initialized = True
if self.initialized:
return
else:
self.initialized = True
folder = self.folder
request = self.request
@@ -312,8 +323,8 @@ class CacheOnDisk(CacheAbstract):
### we need this because of a possible bug in shelve that may
### or may not lock
self.locker_name = os.path.join(folder,'cache.lock')
self.shelve_name = os.path.join(folder,'cache.shelve')
self.locker_name = os.path.join(folder, 'cache.lock')
self.shelve_name = os.path.join(folder, 'cache.shelve')
def clear(self, regex=None):
self.initialize()
@@ -328,7 +339,7 @@ class CacheOnDisk(CacheAbstract):
self._close_shelve_and_unlock()
def __call__(self, key, f,
time_expire = DEFAULT_TIME_EXPIRE):
time_expire=DEFAULT_TIME_EXPIRE):
self.initialize()
dt = time_expire
storage = self._open_shelve_and_lock()
@@ -346,7 +357,7 @@ class CacheOnDisk(CacheAbstract):
else:
value = f()
storage[key] = (now, value)
storage[CacheAbstract.cache_stats_name]['misses']+=1
storage[CacheAbstract.cache_stats_name]['misses'] += 1
storage.sync()
finally:
self._close_shelve_and_unlock()
@@ -365,8 +376,9 @@ class CacheOnDisk(CacheAbstract):
self._close_shelve_and_unlock()
return value
class CacheAction(object):
def __init__(self,func,key,time_expire,cache,cache_model):
def __init__(self, func, key, time_expire, cache, cache_model):
self.__name__ = func.__name__
self.__doc__ = func.__doc__
self.func = func
@@ -374,17 +386,18 @@ class CacheAction(object):
self.time_expire = time_expire
self.cache = cache
self.cache_model = cache_model
def __call__(self,*a,**b):
def __call__(self, *a, **b):
if not self.key:
key2 = self.__name__+':'+repr(a)+':'+repr(b)
key2 = self.__name__ + ':' + repr(a) + ':' + repr(b)
else:
key2 = self.key.replace('%(name)s',self.__name__)\
.replace('%(args)s',str(a)).replace('%(vars)s',str(b))
key2 = self.key.replace('%(name)s', self.__name__)\
.replace('%(args)s', str(a)).replace('%(vars)s', str(b))
cache_model = self.cache_model
if not cache_model or isinstance(cache_model,str):
cache_model = getattr(self.cache,cache_model or 'ram')
if not cache_model or isinstance(cache_model, str):
cache_model = getattr(self.cache, cache_model or 'ram')
return cache_model(key2,
lambda a=a,b=b:self.func(*a,**b),
lambda a=a, b=b: self.func(*a, **b),
self.time_expire)
@@ -424,9 +437,9 @@ class Cache(object):
logger.warning('no cache.disk (AttributeError)')
def __call__(self,
key = None,
time_expire = DEFAULT_TIME_EXPIRE,
cache_model = None):
key=None,
time_expire=DEFAULT_TIME_EXPIRE,
cache_model=None):
"""
Decorator function that can be used to cache any function/method.
@@ -459,8 +472,8 @@ class Cache(object):
`request.env.path_info` as key.
"""
def tmp(func,cache=self,cache_model=cache_model):
return CacheAction(func,key,time_expire,self,cache_model)
def tmp(func, cache=self, cache_model=cache_model):
return CacheAction(func, key, time_expire, self, cache_model)
return tmp
@staticmethod
@@ -473,7 +486,7 @@ class Cache(object):
cache_model(prefix + key, f, time_expire)
def lazy_cache(key=None,time_expire=None,cache_model='ram'):
def lazy_cache(key=None, time_expire=None, cache_model='ram'):
"""
can be used to cache any function including in modules,
as long as the cached function is only called within a web2py request
@@ -481,14 +494,12 @@ def lazy_cache(key=None,time_expire=None,cache_model='ram'):
the time_expire defaults to None (no cache expiration)
if cache_model is "ram" then the model is current.cache.ram, etc.
"""
def decorator(f,key=key,time_expire=time_expire,cache_model=cache_model):
def decorator(f, key=key, time_expire=time_expire, cache_model=cache_model):
key = key or repr(f)
def g(*c,**d):
def g(*c, **d):
from gluon import current
return current.cache(key,time_expire,cache_model)(f)(*c,**d)
return current.cache(key, time_expire, cache_model)(f)(*c, **d)
g.__name__ = f.__name__
return g
return decorator
-7
View File
@@ -51,10 +51,3 @@ def getcfs(key, filename, filter=None):
cfs[key] = (t, data)
cfs_lock.release()
return data
+72 -61
View File
@@ -95,6 +95,7 @@ _TEST()
CACHED_REGEXES = {}
CACHED_REGEXES_MAX_SIZE = 1000
def re_compile(regex):
try:
return CACHED_REGEXES[regex]
@@ -104,6 +105,7 @@ def re_compile(regex):
compiled_regex = CACHED_REGEXES[regex] = re.compile(regex)
return compiled_regex
class mybuiltin(object):
"""
NOTE could simple use a dict and populate it,
@@ -114,14 +116,16 @@ class mybuiltin(object):
try:
return getattr(__builtin__, key)
except AttributeError:
raise KeyError, key
raise KeyError(key)
def __setitem__(self, key, value):
setattr(self, key, value)
def LOAD(c=None, f='index', args=None, vars=None,
extension=None, target=None,ajax=False,ajax_trap=False,
url=None,user_signature=False, timeout=None, times=1,
content='loading...',**attr):
extension=None, target=None, ajax=False, ajax_trap=False,
url=None, user_signature=False, timeout=None, times=1,
content='loading...', **attr):
""" LOAD a component into the action's document
Timing options:
@@ -134,13 +138,14 @@ def LOAD(c=None, f='index', args=None, vars=None,
is added on page loading without delay.
"""
from html import TAG, DIV, URL, SCRIPT, XML
if args is None: args = []
if args is None:
args = []
vars = Storage(vars or {})
target = target or 'c'+str(random.random())[2:]
attr['_id']=target
target = target or 'c' + str(random.random())[2:]
attr['_id'] = target
request = current.request
if '.' in f:
f, extension = f.rsplit('.',1)
f, extension = f.rsplit('.', 1)
if url or ajax:
url = url or URL(request.application, c, f, r=request,
args=args, vars=vars, extension=extension,
@@ -160,19 +165,20 @@ def LOAD(c=None, f='index', args=None, vars=None,
if not isinstance(timeout, (int, long)):
raise ValueError("Timeout argument must be an integer or None")
elif timeout <= 0:
raise ValueError("Timeout argument must be greater than zero or None")
raise ValueError(
"Timeout argument must be greater than zero or None")
statement = "web2py_component('%s','%s', %s, %s);" \
% (url, target, timeout, times)
else:
statement = "web2py_component('%s','%s');" % (url, target)
script = SCRIPT(statement, _type="text/javascript")
if not content is None:
return TAG[''](script, DIV(content,**attr))
return TAG[''](script, DIV(content, **attr))
else:
return TAG[''](script)
else:
if not isinstance(args,(list,tuple)):
if not isinstance(args, (list, tuple)):
args = [args]
c = c or request.controller
other_request = Storage(request)
@@ -186,7 +192,7 @@ def LOAD(c=None, f='index', args=None, vars=None,
other_request.post_vars = Storage()
other_response = Response()
other_request.env.path_info = '/' + \
'/'.join([request.application,c,f] + \
'/'.join([request.application, c, f] +
map(str, other_request.args))
other_request.env.query_string = \
vars and URL(vars=vars).split('?')[1] or ''
@@ -194,9 +200,9 @@ def LOAD(c=None, f='index', args=None, vars=None,
request.env.path_info
other_request.cid = target
other_request.env.http_web2py_component_element = target
other_response.view = '%s/%s.%s' % (c,f, other_request.extension)
other_response.view = '%s/%s.%s' % (c, f, other_request.extension)
other_environment = copy.copy(current.globalenv) ### NASTY
other_environment = copy.copy(current.globalenv) # NASTY
other_response._view_environment = other_environment
other_response.generic_patterns = \
@@ -221,37 +227,38 @@ def LOAD(c=None, f='index', args=None, vars=None,
args=args, vars=vars, extension=extension,
user_signature=user_signature)
js = "web2py_trap_form('%s','%s');" % (link, target)
script = js and SCRIPT(js,_type="text/javascript") or ''
return TAG[''](DIV(XML(page),**attr),script)
script = js and SCRIPT(js, _type="text/javascript") or ''
return TAG[''](DIV(XML(page), **attr), script)
class LoadFactory(object):
"""
Attention: this helper is new and experimental
"""
def __init__(self,environment):
def __init__(self, environment):
self.environment = environment
def __call__(self, c=None, f='index', args=None, vars=None,
extension=None, target=None,ajax=False,ajax_trap=False,
url=None,user_signature=False, content='loading...',**attr):
if args is None: args = []
extension=None, target=None, ajax=False, ajax_trap=False,
url=None, user_signature=False, content='loading...', **attr):
if args is None:
args = []
vars = Storage(vars or {})
import globals
target = target or 'c'+str(random.random())[2:]
attr['_id']=target
target = target or 'c' + str(random.random())[2:]
attr['_id'] = target
request = self.environment['request']
if '.' in f:
f, extension = f.rsplit('.',1)
f, extension = f.rsplit('.', 1)
if url or ajax:
url = url or html.URL(request.application, c, f, r=request,
args=args, vars=vars, extension=extension,
user_signature=user_signature)
script = html.SCRIPT('web2py_component("%s","%s")' % (url, target),
_type="text/javascript")
return html.TAG[''](script, html.DIV(content,**attr))
return html.TAG[''](script, html.DIV(content, **attr))
else:
if not isinstance(args,(list,tuple)):
if not isinstance(args, (list, tuple)):
args = [args]
c = c or request.controller
@@ -266,7 +273,7 @@ class LoadFactory(object):
other_request.post_vars = Storage()
other_response = globals.Response()
other_request.env.path_info = '/' + \
'/'.join([request.application,c,f] + \
'/'.join([request.application, c, f] +
map(str, other_request.args))
other_request.env.query_string = \
vars and html.URL(vars=vars).split('?')[1] or ''
@@ -274,7 +281,7 @@ class LoadFactory(object):
request.env.path_info
other_request.cid = target
other_request.env.http_web2py_component_element = target
other_response.view = '%s/%s.%s' % (c,f, other_request.extension)
other_response.view = '%s/%s.%s' % (c, f, other_request.extension)
other_environment = copy.copy(self.environment)
other_response._view_environment = other_environment
other_response.generic_patterns = \
@@ -299,8 +306,8 @@ class LoadFactory(object):
args=args, vars=vars, extension=extension,
user_signature=user_signature)
js = "web2py_trap_form('%s','%s');" % (link, target)
script = js and html.SCRIPT(js,_type="text/javascript") or ''
return html.TAG[''](html.DIV(html.XML(page),**attr),script)
script = js and html.SCRIPT(js, _type="text/javascript") or ''
return html.TAG[''](html.DIV(html.XML(page), **attr), script)
def local_import_aux(name, reload_force=False, app='welcome'):
@@ -321,7 +328,7 @@ def local_import_aux(name, reload_force=False, app='welcome'):
This prevents conflict between applications and un-necessary execs.
It can be used to import any module, including regular Python modules.
"""
items = name.replace('/','.')
items = name.replace('/', '.')
name = "applications.%s.modules.%s" % (app, items)
module = __import__(name)
for item in name.split(".")[1:]:
@@ -355,12 +362,14 @@ OLD IMPLEMENTATION:
file.close()
imp.release_lock()
if not module:
raise ImportError, "cannot find module %s in %s" % (filename, modulepath)
raise ImportError, "cannot find module %s in %s" % (
filename, modulepath)
return module
"""
_base_environment_ = dict((k,getattr(html,k)) for k in html.__all__)
_base_environment_.update((k,getattr(validators,k)) for k in validators.__all__)
_base_environment_ = dict((k, getattr(html, k)) for k in html.__all__)
_base_environment_.update(
(k, getattr(validators, k)) for k in validators.__all__)
_base_environment_['__builtins__'] = __builtins__
_base_environment_['HTTP'] = HTTP
_base_environment_['redirect'] = redirect
@@ -372,6 +381,7 @@ _base_environment_['SQLFORM'] = SQLFORM
_base_environment_['SQLTABLE'] = SQLTABLE
_base_environment_['LOAD'] = LOAD
def build_environment(request, response, session, store_current=True):
"""
Build the environment dictionary into which web2py files are executed.
@@ -386,7 +396,8 @@ def build_environment(request, response, session, store_current=True):
response.models_to_run = [r'^\w+\.py$', r'^%s/\w+\.py$' % request.controller,
r'^%s/%s/\w+\.py$' % (request.controller, request.function)]
t = environment['T'] = translator(request)
t = environment['T'] = translator(os.path.join(request.folder,'languages'),
request.env.http_accept_language)
c = environment['cache'] = Cache(request)
if store_current:
@@ -403,18 +414,19 @@ def build_environment(request, response, session, store_current=True):
elif is_pypy: # apply the same hack to pypy too
__builtins__ = mybuiltin()
else:
__builtins__['__import__'] = __builtin__.__import__ ### WHY?
__builtins__['__import__'] = __builtin__.__import__ # WHY?
environment['request'] = request
environment['response'] = response
environment['session'] = session
environment['local_import'] = \
lambda name, reload=False, app=request.application:\
local_import_aux(name,reload,app)
local_import_aux(name, reload, app)
BaseAdapter.set_folder(pjoin(request.folder, 'databases'))
response._view_environment = copy.copy(environment)
custom_import_install()
return environment
def save_pyc(filename):
"""
Bytecode compiles the file `filename`
@@ -431,7 +443,7 @@ def read_pyc(filename):
"""
data = read_file(filename, 'rb')
if not is_gae and data[:4] != imp.get_magic():
raise SystemError, 'compiled code is incompatible'
raise SystemError('compiled code is incompatible')
return marshal.loads(data[8:])
@@ -441,8 +453,11 @@ def compile_views(folder):
"""
path = pjoin(folder, 'views')
for file in listdir(path, '^[\w/\-]+(\.\w+)+$'):
for file in listdir(path, '^[\w/\-]+(\.\w+)*$'):
try:
data = parse_template(file, path)
except Exception, e:
raise Exception("%s in %s" % (e, file))
filename = ('views/%s.py' % file).replace('/', '_').replace('\\', '_')
filename = pjoin(folder, 'compiled', filename)
write_file(filename, data)
@@ -458,7 +473,7 @@ def compile_models(folder):
path = pjoin(folder, 'models')
for file in listdir(path, '.+\.py$'):
data = read_file(pjoin(path, file))
filename = pjoin(folder, 'compiled','models',file)
filename = pjoin(folder, 'compiled', 'models', file)
mktree(filename)
write_file(filename, data)
save_pyc(filename)
@@ -473,7 +488,7 @@ def compile_controllers(folder):
path = pjoin(folder, 'controllers')
for file in listdir(path, '.+\.py$'):
### why is this here? save_pyc(pjoin(path, file))
data = read_file(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" % \
@@ -500,19 +515,19 @@ def run_models_in(environment):
for model in listdir(cpath, '^models_\w+\.pyc$', 0):
restricted(read_pyc(model), environment, layer=model)
path = pjoin(cpath, 'models')
models = listdir(path, '^\w+\.pyc$',0,sort=False)
compiled=True
models = listdir(path, '^\w+\.pyc$', 0)
compiled = True
else:
path = pjoin(folder, 'models')
models = listdir(path, '^\w+\.py$',0,sort=False)
compiled=False
models = listdir(path, '^\w+\.py$', 0)
compiled = False
n = len(path) + 1
for model in models:
regex = environment['response'].models_to_run
if isinstance(regex, list):
regex = re_compile('|'.join(regex))
file = model[n:].replace(os.path.sep, '/').replace('.pyc', '.py')
if not regex.search(file) and c!= 'appadmin':
if not regex.search(file) and c != 'appadmin':
continue
elif compiled:
code = read_pyc(model)
@@ -548,7 +563,8 @@ def run_controller_in(controller, function, environment):
# TESTING: adjust the path to include site packages
from settings import global_settings
from admin import abspath, add_path_first
paths = (global_settings.gluon_parent, abspath('site-packages', gluon=True), abspath('gluon', gluon=True), '')
paths = (global_settings.gluon_parent, abspath(
'site-packages', gluon=True), abspath('gluon', gluon=True), '')
[add_path_first(path) for path in paths]
# TESTING END
@@ -578,18 +594,19 @@ def run_controller_in(controller, function, environment):
code = "%s\nresponse._vars=response._caller(%s)\n" % (code, function)
if is_gae:
layer = filename + ':' + function
code = getcfs(layer, filename, lambda: compile2(code,layer))
code = getcfs(layer, filename, lambda: compile2(code, layer))
restricted(code, environment, filename)
response = environment['response']
vars=response._vars
vars = response._vars
if response.postprocessing:
vars = reduce(lambda vars, p: p(vars), response.postprocessing, vars)
if isinstance(vars,unicode):
if isinstance(vars, unicode):
vars = vars.encode('utf8')
elif hasattr(vars,'xml') and callable(vars.xml):
elif hasattr(vars, 'xml') and callable(vars.xml):
vars = vars.xml()
return vars
def run_view_in(environment):
"""
Executes the view for the requested action.
@@ -626,7 +643,7 @@ def run_view_in(environment):
files.append('views_generic.pyc')
# end backward compatibility code
for f in files:
filename = pjoin(path,f)
filename = pjoin(path, f)
if os.path.exists(filename):
code = read_pyc(filename)
restricted(code, environment, layer=filename)
@@ -648,13 +665,14 @@ def run_view_in(environment):
ccode = getcfs(layer, filename,
lambda: compile2(parse_template(view,
pjoin(folder, 'views'),
context=environment),layer))
context=environment), layer))
else:
ccode = parse_template(view,
pjoin(folder, 'views'),
context=environment)
restricted(ccode, environment, layer)
def remove_compiled_application(folder):
"""
Deletes the folder `compiled` containing the compiled application.
@@ -662,7 +680,7 @@ def remove_compiled_application(folder):
try:
shutil.rmtree(pjoin(folder, 'compiled'))
path = pjoin(folder, 'controllers')
for file in listdir(path,'.*\.pyc$',drop=False):
for file in listdir(path, '.*\.pyc$', drop=False):
os.unlink(file)
except OSError:
pass
@@ -700,10 +718,3 @@ def test():
if __name__ == '__main__':
import doctest
doctest.testmod()
+6 -12
View File
@@ -644,6 +644,7 @@ CONTENT_TYPE = {
'.wmls': 'text/vnd.wap.wmlscript',
'.wmv': 'video/x-ms-wmv',
'.wmx': 'audio/x-ms-asx',
'.woff': 'application/font-woff',
'.wp': 'application/vnd.wordperfect',
'.wp4': 'application/vnd.wordperfect',
'.wp5': 'application/vnd.wordperfect',
@@ -700,7 +701,7 @@ CONTENT_TYPE = {
'.zabw': 'application/x-abiword',
'.zip': 'application/zip',
'.zoo': 'application/x-zoo',
}
}
def contenttype(filename, default='text/plain'):
@@ -709,18 +710,11 @@ def contenttype(filename, default='text/plain'):
"""
i = filename.rfind('.')
if i>=0:
default = CONTENT_TYPE.get(filename[i:].lower(),default)
if i >= 0:
default = CONTENT_TYPE.get(filename[i:].lower(), default)
j = filename.rfind('.', 0, i)
if j>=0:
default = CONTENT_TYPE.get(filename[j:].lower(),default)
if j >= 0:
default = CONTENT_TYPE.get(filename[j:].lower(), default)
if default.startswith('text/'):
default += '; charset=utf-8'
return default
+37 -33
View File
@@ -21,6 +21,7 @@ import urllib
_known_tuple_types = {}
class NamedTupleBase(tuple):
"""Base class for named tuples with the __new__ operator set, named tuples
yielded by the namedtuple() function will subclass this and add
@@ -29,7 +30,7 @@ class NamedTupleBase(tuple):
"""Create a new instance of this fielded tuple"""
# May need to unpack named field values here
if kws:
values = list(args) + [None]*(len(cls._fields) - len(args))
values = list(args) + [None] * (len(cls._fields) - len(args))
fields = dict((val, idx) for idx, val in enumerate(cls._fields))
for kw, val in kws.iteritems():
assert kw in kws, "%r not in field list" % kw
@@ -37,6 +38,7 @@ class NamedTupleBase(tuple):
args = tuple(values)
return tuple.__new__(cls, args)
def namedtuple(typename, fieldnames):
"""
>>> import namedtuples
@@ -75,24 +77,26 @@ def namedtuple(typename, fieldnames):
# Done
return new_tuple_type
class AIM:
class AIMError(Exception):
def __init__(self, value):
self.parameter = value
def __str__(self):
return str(self.parameter)
def __init__(self, login, transkey, testmode=False):
if str(login).strip() == '' or login == None:
if str(login).strip() == '' or login is None:
raise AIM.AIMError('No login name provided')
if str(transkey).strip() == '' or transkey == None:
if str(transkey).strip() == '' or transkey is None:
raise AIM.AIMError('No transaction key provided')
if testmode != True and testmode != False:
raise AIM.AIMError('Invalid value for testmode. Must be True or False. "{0}" given.'.format(testmode))
self.testmode = testmode
self.proxy = None;
self.proxy = None
self.delimiter = '|'
self.results = []
self.error = True
@@ -117,8 +121,9 @@ class AIM:
else:
url = 'https://secure.authorize.net/gateway/transact.dll'
if self.proxy == None:
self.results += str(urllib.urlopen(url, encoded_args).read()).split(self.delimiter)
if self.proxy is None:
self.results += str(urllib.urlopen(
url, encoded_args).read()).split(self.delimiter)
else:
opener = urllib.FancyURLopener(self.proxy)
opened = opener.open(url, encoded_args)
@@ -147,36 +152,37 @@ class AIM:
raise AIM.AIMError(self.response.ResponseText)
def setTransaction(self, creditcard, expiration, total, cvv=None, tax=None, invoice=None):
if str(creditcard).strip() == '' or creditcard == None:
if str(creditcard).strip() == '' or creditcard is None:
raise AIM.AIMError('No credit card number passed to setTransaction(): {0}'.format(creditcard))
if str(expiration).strip() == '' or expiration == None:
if str(expiration).strip() == '' or expiration is None:
raise AIM.AIMError('No expiration number to setTransaction(): {0}'.format(expiration))
if str(total).strip() == '' or total == None:
if str(total).strip() == '' or total is None:
raise AIM.AIMError('No total amount passed to setTransaction(): {0}'.format(total))
self.setParameter('x_card_num', creditcard)
self.setParameter('x_exp_date', expiration)
self.setParameter('x_amount', total)
if cvv != None:
if cvv is not None:
self.setParameter('x_card_code', cvv)
if tax != None:
if tax is not None:
self.setParameter('x_tax', tax)
if invoice != None:
if invoice is not None:
self.setParameter('x_invoice_num', invoice)
def setTransactionType(self, transtype=None):
types = ['AUTH_CAPTURE', 'AUTH_ONLY', 'PRIOR_AUTH_CAPTURE', 'CREDIT', 'CAPTURE_ONLY', 'VOID']
types = ['AUTH_CAPTURE', 'AUTH_ONLY', 'PRIOR_AUTH_CAPTURE',
'CREDIT', 'CAPTURE_ONLY', 'VOID']
if transtype.upper() not in types:
raise AIM.AIMError('Incorrect Transaction Type passed to setTransactionType(): {0}'.format(transtype))
self.setParameter('x_type', transtype.upper())
def setProxy(self, proxy=None):
if str(proxy).strip() == '' or proxy == None:
if str(proxy).strip() == '' or proxy is None:
raise AIM.AIMError('No proxy passed to setProxy()')
self.proxy = {'http': str(proxy).strip()}
def setParameter(self, key=None, value=None):
if key != None and value != None and str(key).strip() != '' and str(value).strip() != '':
if key is not None and value is not None and str(key).strip() != '' and str(value).strip() != '':
self.parameters[key] = str(value).strip()
else:
raise AIM.AIMError('Incorrect parameters passed to setParameter(): {0}:{1}'.format(key, value))
@@ -194,10 +200,11 @@ class AIM:
responses = ['', 'Approved', 'Declined', 'Error']
return responses[int(self.results[0])]
def process(creditcard,expiration,total,cvv=None,tax=None,invoice=None,
login='cnpdev4289', transkey='SR2P8g4jdEn7vFLQ',testmode=True):
payment = AIM(login,transkey,testmode)
expiration = expiration.replace('/','')
def process(creditcard, expiration, total, cvv=None, tax=None, invoice=None,
login='cnpdev4289', transkey='SR2P8g4jdEn7vFLQ', testmode=True):
payment = AIM(login, transkey, testmode)
expiration = expiration.replace('/', '')
payment.setTransaction(creditcard, expiration, total, cvv, tax, invoice)
try:
payment.process()
@@ -205,6 +212,7 @@ def process(creditcard,expiration,total,cvv=None,tax=None,invoice=None,
except AIM.AIMError:
return False
def test():
import socket
import sys
@@ -219,8 +227,10 @@ def test():
try:
payment = AIM('cnpdev4289', 'SR2P8g4jdEn7vFLQ', True)
payment.setTransaction(creditcard, expiration, total, cvv, tax, invoice)
payment.setParameter('x_duplicate_window', 180) # three minutes duplicate windows
payment.setTransaction(
creditcard, expiration, total, cvv, tax, invoice)
payment.setParameter(
'x_duplicate_window', 180) # three minutes duplicate windows
payment.setParameter('x_cust_id', '1324') # customer ID
payment.setParameter('x_first_name', 'John')
payment.setParameter('x_last_name', 'Conde')
@@ -232,7 +242,8 @@ def test():
payment.setParameter('x_country', 'US')
payment.setParameter('x_phone', '800-555-1234')
payment.setParameter('x_description', 'Test Transaction')
payment.setParameter('x_customer_ip', socket.gethostbyname(socket.gethostname()))
payment.setParameter(
'x_customer_ip', socket.gethostbyname(socket.gethostname()))
payment.setParameter('x_email', 'john@example.com')
payment.setParameter('x_email_customer', False)
payment.process()
@@ -251,16 +262,9 @@ def test():
except AIM.AIMError, e:
print "Exception thrown:", e
print 'An error occured'
print 'approved',payment.isApproved()
print 'declined',payment.isDeclined()
print 'error',payment.isError()
print 'approved', payment.isApproved()
print 'declined', payment.isDeclined()
print 'error', payment.isError()
if __name__=='__main__':
if __name__ == '__main__':
test()
+24 -26
View File
@@ -15,25 +15,27 @@ __all__ = ['DowCommerce']
from operator import itemgetter
import urllib
class DowCommerce:
class DowCommerceError(Exception):
def __init__(self, value):
self.parameter = value
def __str__(self):
return str(self.parameter)
def __init__(self, username=None, password=None, demomode=False):
if not demomode:
if str(username).strip() == '' or username == None:
if str(username).strip() == '' or username is None:
raise DowCommerce.DowCommerceError('No username provided')
if str(password).strip() == '' or password == None:
if str(password).strip() == '' or password is None:
raise DowCommerce.DowCommerceError('No password provided')
else:
username = 'demo'
password = 'password'
self.proxy = None;
self.proxy = None
self.delimiter = '&'
self.results = {}
self.error = True
@@ -45,11 +47,11 @@ class DowCommerce:
self.setParameter('username', username)
self.setParameter('password', password)
def process(self):
encoded_args = urllib.urlencode(self.parameters)
if self.proxy == None:
results = str(urllib.urlopen(self.url, encoded_args).read()).split(self.delimiter)
if self.proxy is None:
results = str(urllib.urlopen(
self.url, encoded_args).read()).split(self.delimiter)
else:
opener = urllib.FancyURLopener(self.proxy)
opened = opener.open(self.url, encoded_args)
@@ -59,7 +61,7 @@ class DowCommerce:
opened.close()
for result in results:
(key,val) = result.split('=')
(key, val) = result.split('=')
self.results[key] = val
if self.results['response'] == '1':
@@ -80,17 +82,18 @@ class DowCommerce:
self.declined = False
raise DowCommerce.DowCommerceError(self.results)
def setTransaction(self, creditcard, expiration, total, cvv=None, orderid=None, orderdescription=None,
def setTransaction(
self, creditcard, expiration, total, cvv=None, orderid=None, orderdescription=None,
ipaddress=None, tax=None, shipping=None,
firstname=None, lastname=None, company=None, address1=None, address2=None, city=None, state=None, zipcode=None,
country=None, phone=None, fax=None, emailaddress=None, website=None,
shipping_firstname=None, shipping_lastname=None, shipping_company=None, shipping_address1=None, shipping_address2=None,
shipping_city=None, shipping_state=None, shipping_zipcode = None, shipping_country=None, shipping_emailaddress=None):
if str(creditcard).strip() == '' or creditcard == None:
shipping_city=None, shipping_state=None, shipping_zipcode=None, shipping_country=None, shipping_emailaddress=None):
if str(creditcard).strip() == '' or creditcard is None:
raise DowCommerce.DowCommerceError('No credit card number passed to setTransaction(): {0}'.format(creditcard))
if str(expiration).strip() == '' or expiration == None:
if str(expiration).strip() == '' or expiration is None:
raise DowCommerce.DowCommerceError('No expiration number passed to setTransaction(): {0}'.format(expiration))
if str(total).strip() == '' or total == None:
if str(total).strip() == '' or total is None:
raise DowCommerce.DowCommerceError('No total amount passed to setTransaction(): {0}'.format(total))
self.setParameter('ccnumber', creditcard)
@@ -165,12 +168,12 @@ class DowCommerce:
self.setParameter('type', transtype.lower())
def setProxy(self, proxy=None):
if str(proxy).strip() == '' or proxy == None:
if str(proxy).strip() == '' or proxy is None:
raise DowCommerce.DowCommerceError('No proxy passed to setProxy()')
self.proxy = {'http': str(proxy).strip()}
def setParameter(self, key=None, value=None):
if key != None and value != None and str(key).strip() != '' and str(value).strip() != '':
if key is not None and value is not None and str(key).strip() != '' and str(value).strip() != '':
self.parameters[key] = str(value).strip()
else:
raise DowCommerce.DowCommerceError('Incorrect parameters passed to setParameter(): {0}:{1}'.format(key, value))
@@ -194,6 +197,7 @@ class DowCommerce:
def getResponseText(self):
return self.results['responsetext']
def test():
import socket
import sys
@@ -216,7 +220,8 @@ def test():
try:
payment = DowCommerce(demomode=True)
payment.setTransaction(creditcard, expiration, total, cvv=cvv, tax=tax, orderid=orderid, orderdescription='Test Transaction',
payment.setTransaction(
creditcard, expiration, total, cvv=cvv, tax=tax, orderid=orderid, orderdescription='Test Transaction',
firstname='John', lastname='Doe', company='Acme', address1='123 Min Street', city='Hometown', state='VA',
zipcode='12345', country='US', phone='888-555-1212', emailaddress='john@noemail.local', ipaddress='192.168.1.1')
@@ -231,16 +236,9 @@ def test():
except DowCommerce.DowCommerceError, e:
print "Exception thrown:", e
print 'An error occured'
print 'approved',payment.isApproved()
print 'declined',payment.isDeclined()
print 'error',payment.isError()
print 'approved', payment.isApproved()
print 'declined', payment.isDeclined()
print 'error', payment.isError()
if __name__=='__main__':
if __name__ == '__main__':
test()
-8
View File
@@ -1,8 +0,0 @@
+5 -7
View File
@@ -64,7 +64,7 @@ def new(key, mode=MODE_CBC, IV=None):
return ECBMode(AES(key))
elif mode == MODE_CBC:
if IV is None:
raise ValueError, "CBC mode needs an IV value!"
raise ValueError("CBC mode needs an IV value!")
return CBCMode(AES(key), IV)
else:
@@ -91,7 +91,7 @@ class AES(object):
elif self.key_size == 32:
self.rounds = 14
else:
raise ValueError, "Key length must be 16, 24 or 32 bytes"
raise ValueError("Key length must be 16, 24 or 32 bytes")
self.expand_key()
@@ -313,7 +313,7 @@ class ECBMode(object):
"""Perform ECB mode with the given function"""
if len(data) % self.block_size != 0:
raise ValueError, "Plaintext length must be multiple of 16"
raise ValueError("Plaintext length must be multiple of 16")
block_size = self.block_size
data = array('B', data)
@@ -357,7 +357,7 @@ class CBCMode(object):
block_size = self.block_size
if len(data) % block_size != 0:
raise ValueError, "Plaintext length must be multiple of 16"
raise ValueError("Plaintext length must be multiple of 16")
data = array('B', data)
IV = self.IV
@@ -381,7 +381,7 @@ class CBCMode(object):
block_size = self.block_size
if len(data) % block_size != 0:
raise ValueError, "Ciphertext length must be multiple of 16"
raise ValueError("Ciphertext length must be multiple of 16")
data = array('B', data)
IV = self.IV
@@ -500,5 +500,3 @@ aes_Rcon = array('B',
'c697356ad4b37dfaefc5913972e4d3bd'
'61c29f254a943366cc831d3a74e8cb'.decode('hex')
)
+28 -18
View File
@@ -42,7 +42,9 @@ revision3.com
viddler.com
"""
import re, cgi, sys
import re
import cgi
import sys
from simplejson import loads
import urllib
import uuid
@@ -75,23 +77,28 @@ EMBED_MAPS = [
'http://revision3.com/api/oembed/'),
(re.compile('http://\S+.viddler.com/\S+'),
'http://lab.viddler.com/services/oembed/'),
]
]
def image(url):
return '<img src="%s" style="max-width:100%%"/>' % url
def audio(url):
return '<audio controls="controls" style="max-width:100%%"><source src="%s" /></audio>' % url
def video(url):
return '<video controls="controls" style="max-width:100%%"><source src="%s" /></video>' % url
def googledoc_viewer(url):
return '<iframe src="http://docs.google.com/viewer?url=%s&embedded=true" style="max-width:100%%"></iframe>' % urllib.quote(url)
def web2py_component(url):
code = str(uuid.uuid4())
return '<div id="%s"></div><script>\nweb2py_component("%s","%s");\n</script>' % (code,url,code)
return '<div id="%s"></div><script>\nweb2py_component("%s","%s");\n</script>' % (code, url, code)
EXTENSION_MAPS = {
'png': image,
@@ -126,33 +133,36 @@ EXTENSION_MAPS = {
'xps': googledoc_viewer,
}
class VimeoURLOpener(urllib.FancyURLopener):
"Vimeo blocks the urllib user agent for some reason"
version = "Mozilla/4.0"
urllib._urlopener = VimeoURLOpener()
def oembed(url):
for k,v in EMBED_MAPS:
for k, v in EMBED_MAPS:
if k.match(url):
oembed = v+'?format=json&url='+cgi.escape(url)
oembed = v + '?format=json&url=' + cgi.escape(url)
try:
data = urllib.urlopen(oembed).read()
print data
return loads(data) # json!
except:
pass
return {}
def extension(url):
return url.split('?')[0].split('.')[-1].lower()
def expand_one(url,cdict):
def expand_one(url, cdict):
# try ombed but first check in cache
if cdict and url in cdict:
r = cdict[url]
else:
r = oembed(url)
if isinstance(cdict,dict):
if isinstance(cdict, dict):
cdict[url] = r
# if oembed service
if 'html' in r:
@@ -170,21 +180,23 @@ def expand_one(url,cdict):
# else regular link
return '<a href="%(u)s">%(u)s</a>' % dict(u=url)
def expand_html(html,cdict=None):
def expand_html(html, cdict=None):
if not have_soup:
raise RuntimeError, "Missing BeautifulSoup"
raise RuntimeError("Missing BeautifulSoup")
soup = BeautifulSoup(html)
comments = soup.findAll(text=lambda text:isinstance(text, Comment))
comments = soup.findAll(text=lambda text: isinstance(text, Comment))
[comment.extract() for comment in comments]
for txt in soup.findAll(text=True):
if not txt.parent.name in ('a','script','pre','code','embed','object','audio','video'):
if not txt.parent.name in ('a', 'script', 'pre', 'code', 'embed', 'object', 'audio', 'video'):
ntxt = regex_link.sub(
lambda match: expand_one(match.group(0),cdict), txt)
lambda match: expand_one(match.group(0), cdict), txt)
txt.replaceWith(BeautifulSoup(ntxt))
return str(soup)
def test():
example="""
example = """
<h3>Fringilla nisi parturient nullam</h3>
<p>http://www.youtube.com/watch?v=IWBFiI5RrA0</p>
<p>http://www.web2py.com/examples/static/images/logo_bw.png</p>
@@ -198,10 +210,8 @@ laoreet tortor.</p>
"""
return expand_html(example)
if __name__=="__main__":
if len(sys.argv)>1:
if __name__ == "__main__":
if len(sys.argv) > 1:
print expand_html(open(sys.argv[1]).read())
else:
print test()
File diff suppressed because it is too large. Load diff
+6 -4
View File
@@ -26,8 +26,9 @@ def hex2dec(color = "#000000"):
class HTML2FPDF(HTMLParser):
"Render basic HTML to FPDF"
def __init__(self, pdf):
def __init__(self, pdf, image_map = None):
HTMLParser.__init__(self)
self.image_map = image_map or (lambda src: src)
self.style = {}
self.pre = False
self.href = ''
@@ -265,7 +266,8 @@ class HTML2FPDF(HTMLParser):
h = px2mm(attrs.get('height',0))
if self.align and self.align[0].upper() == 'C':
x = (self.pdf.w-x)/2.0 - w/2.0
self.pdf.image(attrs['src'], x, y, w, h, link=self.href)
self.pdf.image(self.image_map(attrs['src']),
x, y, w, h, link=self.href)
self.pdf.set_x(x+w)
self.pdf.set_y(y+h)
if tag=='b' or tag=='i' or tag=='u':
@@ -389,9 +391,9 @@ class HTML2FPDF(HTMLParser):
self.pdf.ln(3)
class HTMLMixin(object):
def write_html(self, text):
def write_html(self, text, image_map=None):
"Parse HTML and convert it to PDF"
h2p = HTML2FPDF(self)
h2p = HTML2FPDF(self, image_map)
h2p.feed(text)
+11 -10
View File
@@ -12,6 +12,7 @@ cache.ram=cache.disk=MemcacheClient(request)
import time
from google.appengine.api.memcache import Client
class MemcacheClient(object):
client = Client()
@@ -29,7 +30,7 @@ class MemcacheClient(object):
dt = time_expire
value = None
obj = self.client.get(key)
if obj and (dt == None or obj[0] > time.time() - dt):
if obj and (dt is None or obj[0] > time.time() - dt):
value = obj[1]
elif f is None:
if obj:
@@ -47,21 +48,21 @@ class MemcacheClient(object):
self.client.set(key, (time.time(), value))
return value
def clear(self, key = None):
def clear(self, key=None):
if key:
key = '%s/%s' % (self.request.application, key)
self.client.delete(key)
else:
self.client.flush_all()
def delete(self,*a,**b):
return self.client.delete(*a,**b)
def delete(self, *a, **b):
return self.client.delete(*a, **b)
def get(self,*a,**b):
return self.client.delete(*a,**b)
def get(self, *a, **b):
return self.client.delete(*a, **b)
def set(self,*a,**b):
return self.client.delete(*a,**b)
def set(self, *a, **b):
return self.client.delete(*a, **b)
def flush_all(self,*a,**b):
return self.client.delete(*a,**b)
def flush_all(self, *a, **b):
return self.client.delete(*a, **b)
+8 -12
View File
@@ -51,7 +51,8 @@ def autoretry_datastore_timeouts(attempts=5.0, interval=0.1, exponent=2.0):
:param exponent: rate of exponential back-off.
"""
import time, logging
import time
import logging
from google.appengine.api import apiproxy_stub_map
from google.appengine.runtime import apiproxy_errors
from google.appengine.datastore import datastore_pb
@@ -60,8 +61,8 @@ def autoretry_datastore_timeouts(attempts=5.0, interval=0.1, exponent=2.0):
interval = float(interval)
exponent = float(exponent)
wrapped = apiproxy_stub_map.MakeSyncCall
errors = {datastore_pb.Error.TIMEOUT:'Timeout',
datastore_pb.Error.CONCURRENT_TRANSACTION:'TransactionFailedError'}
errors = {datastore_pb.Error.TIMEOUT: 'Timeout',
datastore_pb.Error.CONCURRENT_TRANSACTION: 'TransactionFailedError'}
def wrapper(*args, **kwargs):
count = 0.0
@@ -70,10 +71,12 @@ def autoretry_datastore_timeouts(attempts=5.0, interval=0.1, exponent=2.0):
return wrapped(*args, **kwargs)
except apiproxy_errors.ApplicationError, err:
errno = err.application_error
if errno not in errors: raise
if errno not in errors:
raise
sleep = (exponent ** count) * interval
count += 1.0
if count > attempts: raise
if count > attempts:
raise
msg = "Datastore %s: retry #%d in %s seconds.\n%s"
vals = ''
if count == 1.0:
@@ -84,10 +87,3 @@ def autoretry_datastore_timeouts(attempts=5.0, interval=0.1, exponent=2.0):
setattr(wrapper, '_autoretry_datastore_timeouts', False)
if getattr(wrapped, '_autoretry_datastore_timeouts', True):
apiproxy_stub_map.MakeSyncCall = wrapper
+22 -20
View File
@@ -12,6 +12,7 @@ from gluon.sanitizer import sanitize
from gluon.contrib.markmin.markmin2latex import markmin2latex
from gluon.contrib.markmin.markmin2pdf import markmin2pdf
def wrapper(f):
def g(data):
try:
@@ -25,46 +26,47 @@ def wrapper(f):
raise HTTP(405, '%s error' % e)
return g
def latex_from_html(html):
markmin=TAG(html).element('body').flatten(markmin_serializer)
markmin = TAG(html).element('body').flatten(markmin_serializer)
return XML(markmin2latex(markmin))
def pdflatex_from_html(html):
if os.system('which pdflatex > /dev/null')==0:
markmin=TAG(html).element('body').flatten(markmin_serializer)
out,warnings,errors=markmin2pdf(markmin)
if os.system('which pdflatex > /dev/null') == 0:
markmin = TAG(html).element('body').flatten(markmin_serializer)
out, warnings, errors = markmin2pdf(markmin)
if errors:
current.response.headers['Content-Type']='text/html'
raise HTTP(405,HTML(BODY(H1('errors'),
current.response.headers['Content-Type'] = 'text/html'
raise HTTP(405, HTML(BODY(H1('errors'),
UL(*errors),
H1('warnings'),
UL(*warnings))).xml())
else:
return XML(out)
def pyfpdf_from_html(html):
request = current.request
def image_map(path):
if path.startswith('/%s/static/' % request.application):
return os.path.join(request.folder,path.split('/',2)[2])
return 'http%s://%s%s' % (request.is_https and 's' or '',request.env.http_host, path)
class MyFPDF(FPDF, HTMLMixin): pass
pdf=MyFPDF()
return os.path.join(request.folder, path.split('/', 2)[2])
return 'http%s://%s%s' % (request.is_https and 's' or '', request.env.http_host, path)
class MyFPDF(FPDF, HTMLMixin):
pass
pdf = MyFPDF()
pdf.add_page()
html = sanitize(html, escape=False) #### should have better list of allowed tags
pdf.write_html(html,image_map=image_map)
html = sanitize(
html, escape=False) # should have better list of allowed tags
pdf.write_html(html, image_map=image_map)
return XML(pdf.output(dest='S'))
def pdf_from_html(html):
# try use latex and pdflatex
if os.system('which pdflatex > /dev/null')==0:
if os.system('which pdflatex > /dev/null') == 0:
return pdflatex_from_html(html)
else:
return pyfpdf_from_html(html)
Loaded 100 of 236 files, more files were not shown because too many files have changed in this diff. Show more