Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial commit

  • Loading branch information...
commit d421c1321beb4f6d508368af7cbd298b2bbcce5e 0 parents
mdipierro mdipierro authored
Showing with 30,353 additions and 0 deletions.
  1. +6 −0 ABOUT
  2. 0  Introduction
  3. +137 −0 LICENSE
  4. +1 −0  MANIFEST.in
  5. +123 −0 Makefile
  6. +1 −0  NEWINSTALL
  7. +1,178 −0 README
  8. +3 −0  TODO
  9. +1 −0  VERSION
  10. +3 −0  __init__.py
  11. +300 −0 anyserver.py
  12. +86 −0 app.example.yaml
  13. +5 −0 appengine_config.py
  14. +6 −0 applications/admin/ABOUT
  15. +137 −0 applications/admin/LICENSE
  16. 0  applications/admin/__init__.py
  17. +430 −0 applications/admin/controllers/appadmin.py
  18. +33 −0 applications/admin/controllers/debug.py
  19. +1,329 −0 applications/admin/controllers/default.py
  20. +87 −0 applications/admin/controllers/gae.py
  21. +82 −0 applications/admin/controllers/mercurial.py
  22. +45 −0 applications/admin/controllers/shell.py
  23. +29 −0 applications/admin/controllers/toolbar.py
  24. +551 −0 applications/admin/controllers/wizard.py
  25. +1 −0  applications/admin/cron/crontab
  26. +21 −0 applications/admin/cron/expire_sessions.py
  27. +87 −0 applications/admin/languages/af.py
  28. +277 −0 applications/admin/languages/bg-bg.py
  29. +341 −0 applications/admin/languages/de-de.py
  30. +282 −0 applications/admin/languages/es-es.py
  31. +279 −0 applications/admin/languages/fr-fr.py
  32. +270 −0 applications/admin/languages/he.py
  33. +264 −0 applications/admin/languages/it-it.py
  34. +266 −0 applications/admin/languages/it.py
  35. +262 −0 applications/admin/languages/pl-pl.py
  36. +277 −0 applications/admin/languages/pl.py
  37. +320 −0 applications/admin/languages/pt-br.py
  38. +290 −0 applications/admin/languages/zh-cn.py
  39. +302 −0 applications/admin/languages/zh-tw.py
  40. +65 −0 applications/admin/models/0.py
  41. +26 −0 applications/admin/models/0_imports.py
  42. +146 −0 applications/admin/models/access.py
  43. +23 −0 applications/admin/models/buttons.py
  44. +40 −0 applications/admin/models/db.py
  45. +33 −0 applications/admin/models/menu.py
  46. +4 −0 applications/admin/models/plugin_multiselect.py
  47. 0  applications/admin/modules/__init__.py
  48. +56 −0 applications/admin/static/css/anytime.css
  49. +47 −0 applications/admin/static/css/jqueryMultiSelect.css
  50. +1,065 −0 applications/admin/static/css/styles.css
  51. +389 −0 applications/admin/static/eamy/bundle_markup.js
  52. +296 −0 applications/admin/static/eamy/bundle_python.js
  53. BIN  applications/admin/static/eamy/chap-bg-sidebar.gif
  54. BIN  applications/admin/static/eamy/chap-bookmark-default.gif
  55. BIN  applications/admin/static/eamy/chap-folding-expand-inner.gif
  56. BIN  applications/admin/static/eamy/chap-folding-expand.gif
  57. BIN  applications/admin/static/eamy/chap-folding-start.gif
  58. BIN  applications/admin/static/eamy/chap-folding-stop.gif
  59. BIN  applications/admin/static/eamy/chap-wrapped-row.gif
  60. +8,143 −0 applications/admin/static/eamy/eamy.js
  61. +56 −0 applications/admin/static/eamy/style.css
  62. BIN  applications/admin/static/eamy/void.gif
  63. +491 −0 applications/admin/static/edit_area/autocompletion.js
  64. +530 −0 applications/admin/static/edit_area/edit_area.css
  65. +527 −0 applications/admin/static/edit_area/edit_area.js
  66. +428 −0 applications/admin/static/edit_area/edit_area_compressor.php
  67. BIN  applications/admin/static/edit_area/edit_area_full.gz
  68. +38 −0 applications/admin/static/edit_area/edit_area_full.js
  69. +39 −0 applications/admin/static/edit_area/edit_area_full_with_plugins.js
  70. +1,202 −0 applications/admin/static/edit_area/edit_area_functions.js
  71. +1,081 −0 applications/admin/static/edit_area/edit_area_loader.js
  72. +336 −0 applications/admin/static/edit_area/elements_functions.js
  73. +407 −0 applications/admin/static/edit_area/highlight.js
  74. BIN  applications/admin/static/edit_area/images/autocompletion.gif
  75. BIN  applications/admin/static/edit_area/images/close.gif
  76. BIN  applications/admin/static/edit_area/images/fullscreen.gif
  77. BIN  applications/admin/static/edit_area/images/go_to_line.gif
  78. BIN  applications/admin/static/edit_area/images/help.gif
  79. BIN  applications/admin/static/edit_area/images/highlight.gif
  80. BIN  applications/admin/static/edit_area/images/load.gif
  81. BIN  applications/admin/static/edit_area/images/move.gif
  82. BIN  applications/admin/static/edit_area/images/newdocument.gif
  83. BIN  applications/admin/static/edit_area/images/opacity.png
  84. BIN  applications/admin/static/edit_area/images/processing.gif
  85. BIN  applications/admin/static/edit_area/images/redo.gif
  86. BIN  applications/admin/static/edit_area/images/reset_highlight.gif
  87. BIN  applications/admin/static/edit_area/images/save.gif
  88. BIN  applications/admin/static/edit_area/images/search.gif
  89. BIN  applications/admin/static/edit_area/images/smooth_selection.gif
  90. BIN  applications/admin/static/edit_area/images/spacer.gif
  91. BIN  applications/admin/static/edit_area/images/statusbar_resize.gif
  92. BIN  applications/admin/static/edit_area/images/undo.gif
  93. BIN  applications/admin/static/edit_area/images/word_wrap.gif
  94. +145 −0 applications/admin/static/edit_area/keyboard.js
  95. +54 −0 applications/admin/static/edit_area/langs/bg.js
  96. +48 −0 applications/admin/static/edit_area/langs/cs.js
  97. +48 −0 applications/admin/static/edit_area/langs/de.js
  98. +48 −0 applications/admin/static/edit_area/langs/dk.js
  99. +48 −0 applications/admin/static/edit_area/langs/en.js
  100. +48 −0 applications/admin/static/edit_area/langs/eo.js
  101. +48 −0 applications/admin/static/edit_area/langs/es.js
  102. +48 −0 applications/admin/static/edit_area/langs/fi.js
  103. +48 −0 applications/admin/static/edit_area/langs/fr.js
  104. +48 −0 applications/admin/static/edit_area/langs/hr.js
  105. +48 −0 applications/admin/static/edit_area/langs/it.js
  106. +48 −0 applications/admin/static/edit_area/langs/ja.js
  107. +48 −0 applications/admin/static/edit_area/langs/mk.js
  108. +48 −0 applications/admin/static/edit_area/langs/nl.js
  109. +48 −0 applications/admin/static/edit_area/langs/pl.js
  110. +48 −0 applications/admin/static/edit_area/langs/pt.js
  111. +48 −0 applications/admin/static/edit_area/langs/ru.js
  112. +48 −0 applications/admin/static/edit_area/langs/sk.js
  113. +48 −0 applications/admin/static/edit_area/langs/zh.js
  114. 0  applications/admin/static/edit_area/license.txt
  115. +7 −0 applications/admin/static/edit_area/license_apache.txt
  116. +10 −0 applications/admin/static/edit_area/license_bsd.txt
  117. +458 −0 applications/admin/static/edit_area/license_lgpl.txt
  118. +623 −0 applications/admin/static/edit_area/manage_area.js
  119. +90 −0 applications/admin/static/edit_area/plugins/charmap/charmap.js
  120. +64 −0 applications/admin/static/edit_area/plugins/charmap/css/charmap.css
  121. BIN  applications/admin/static/edit_area/plugins/charmap/images/charmap.gif
  122. +373 −0 applications/admin/static/edit_area/plugins/charmap/jscripts/map.js
  123. +12 −0 applications/admin/static/edit_area/plugins/charmap/langs/bg.js
  124. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/cs.js
  125. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/de.js
  126. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/dk.js
  127. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/en.js
  128. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/eo.js
  129. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/es.js
  130. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/fr.js
  131. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/hr.js
  132. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/it.js
  133. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/ja.js
  134. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/mk.js
  135. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/nl.js
  136. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/pl.js
  137. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/pt.js
  138. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/ru.js
  139. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/sk.js
  140. +6 −0 applications/admin/static/edit_area/plugins/charmap/langs/zh.js
  141. +24 −0 applications/admin/static/edit_area/plugins/charmap/popup.html
  142. +3 −0  applications/admin/static/edit_area/plugins/test/css/test.css
  143. BIN  applications/admin/static/edit_area/plugins/test/images/test.gif
  144. +10 −0 applications/admin/static/edit_area/plugins/test/langs/bg.js
  145. +4 −0 applications/admin/static/edit_area/plugins/test/langs/cs.js
  146. +4 −0 applications/admin/static/edit_area/plugins/test/langs/de.js
  147. +4 −0 applications/admin/static/edit_area/plugins/test/langs/dk.js
  148. +4 −0 applications/admin/static/edit_area/plugins/test/langs/en.js
  149. +4 −0 applications/admin/static/edit_area/plugins/test/langs/eo.js
  150. +4 −0 applications/admin/static/edit_area/plugins/test/langs/es.js
  151. +4 −0 applications/admin/static/edit_area/plugins/test/langs/fr.js
  152. +4 −0 applications/admin/static/edit_area/plugins/test/langs/hr.js
  153. +4 −0 applications/admin/static/edit_area/plugins/test/langs/it.js
  154. +4 −0 applications/admin/static/edit_area/plugins/test/langs/ja.js
  155. +4 −0 applications/admin/static/edit_area/plugins/test/langs/mk.js
  156. +4 −0 applications/admin/static/edit_area/plugins/test/langs/nl.js
  157. +4 −0 applications/admin/static/edit_area/plugins/test/langs/pl.js
  158. +4 −0 applications/admin/static/edit_area/plugins/test/langs/pt.js
  159. +4 −0 applications/admin/static/edit_area/plugins/test/langs/ru.js
  160. +4 −0 applications/admin/static/edit_area/plugins/test/langs/sk.js
  161. +4 −0 applications/admin/static/edit_area/plugins/test/langs/zh.js
  162. +110 −0 applications/admin/static/edit_area/plugins/test/test.js
  163. +1 −0  applications/admin/static/edit_area/plugins/test/test2.js
  164. +4 −0 applications/admin/static/edit_area/plugins/zencoding/core.js
  165. +4 −0 applications/admin/static/edit_area/plugins/zencoding/langs/en.js
  166. +420 −0 applications/admin/static/edit_area/plugins/zencoding/zencoding.js
  167. +166 −0 applications/admin/static/edit_area/reg_syntax.js
  168. +70 −0 applications/admin/static/edit_area/reg_syntax/basic.js
  169. +45 −0 applications/admin/static/edit_area/reg_syntax/brainfuck.js
  170. +63 −0 applications/admin/static/edit_area/reg_syntax/c.js
  171. +120 −0 applications/admin/static/edit_area/reg_syntax/coldfusion.js
  172. +66 −0 applications/admin/static/edit_area/reg_syntax/cpp.js
  173. +85 −0 applications/admin/static/edit_area/reg_syntax/css.js
  174. +51 −0 applications/admin/static/edit_area/reg_syntax/html.js
  175. +57 −0 applications/admin/static/edit_area/reg_syntax/java.js
  176. +94 −0 applications/admin/static/edit_area/reg_syntax/js.js
  177. +83 −0 applications/admin/static/edit_area/reg_syntax/pas.js
  178. +88 −0 applications/admin/static/edit_area/reg_syntax/perl.js
  179. +157 −0 applications/admin/static/edit_area/reg_syntax/php.js
  180. +145 −0 applications/admin/static/edit_area/reg_syntax/python.js
  181. +25 −0 applications/admin/static/edit_area/reg_syntax/robotstxt.js
  182. +68 −0 applications/admin/static/edit_area/reg_syntax/ruby.js
  183. +56 −0 applications/admin/static/edit_area/reg_syntax/sql.js
  184. +88 −0 applications/admin/static/edit_area/reg_syntax/tsql.js
  185. +53 −0 applications/admin/static/edit_area/reg_syntax/vb.js
  186. +57 −0 applications/admin/static/edit_area/reg_syntax/xml.js
  187. +139 −0 applications/admin/static/edit_area/regexp.js
  188. +73 −0 applications/admin/static/edit_area/resize_area.js
  189. +174 −0 applications/admin/static/edit_area/search_replace.js
  190. +100 −0 applications/admin/static/edit_area/template.html
  191. BIN  applications/admin/static/images/delete_icon.png
  192. BIN  applications/admin/static/images/dim_bullet.gif
  193. BIN  applications/admin/static/images/embossed.png
  194. BIN  applications/admin/static/images/folder.png
  195. BIN  applications/admin/static/images/folder_locked.png
  196. BIN  applications/admin/static/images/folder_sm.png
  197. BIN  applications/admin/static/images/header_bg.png
  198. BIN  applications/admin/static/images/header_shadow.png
  199. BIN  applications/admin/static/images/help.png
  200. BIN  applications/admin/static/images/menu.png
  201. BIN  applications/admin/static/images/red_bullet.gif
  202. BIN  applications/admin/static/images/save_icon.png
  203. BIN  applications/admin/static/images/search.png
  204. BIN  applications/admin/static/images/section_bullet.png
  205. BIN  applications/admin/static/images/sidebar_background.jpg
  206. BIN  applications/admin/static/images/sidebar_bullet.gif
  207. BIN  applications/admin/static/images/sidebar_bullet.png
  208. BIN  applications/admin/static/images/small_button.png
  209. BIN  applications/admin/static/images/small_special_button.png
  210. BIN  applications/admin/static/images/spinner.gif
  211. BIN  applications/admin/static/images/start.png
  212. BIN  applications/admin/static/images/test_icon.png
  213. BIN  applications/admin/static/images/ticket_section.png
  214. +104 −0 applications/admin/static/js/ajax_editor.js
  215. +790 −0 applications/admin/static/js/anytime.js
  216. +62 −0 applications/admin/static/js/autoscroll.js
  217. +244 −0 applications/admin/static/js/jquery.hotkeys.js
  218. +4 −0 applications/admin/static/js/jquery.js
Sorry, we could not display the entire diff because too many files (579) changed.
6 ABOUT
@@ -0,0 +1,6 @@
+web2py is an open source full-stack framework for agile development
+of secure database-driven web-based applications, written and programmable in
+Python.
+
+Created by Massimo Di Pierro <mdipierro@cs.depaul.edu>
+
0  Introduction
No changes.
137 LICENSE
@@ -0,0 +1,137 @@
+## Web2py License
+
+Web2py is Licensed under the LGPL license version 3
+(http://www.gnu.org/licenses/lgpl.html)
+
+Copyrighted (c) by Massimo Di Pierro (2007-2011)
+
+### On Commercial Redistribution
+
+In accordance with LGPL you may:
+- redistribute web2py with your apps (including official web2py binary versions)
+- release your applications which use official web2py libraries under any license you wish
+But you must:
+- make clear in the documentation that your application uses web2py
+- release any modification of the web2py libraries under the LGPLv3 license
+
+THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT
+HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE,
+BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
+DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
+OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
+PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+(Earlier versions of web2py, 1.0.*-1.90.*, were released under the GPL2 license plus a
+commercial exception which, for practical purposes, was very similar to the current LPGLv3)
+
+### Licenses for third party contributed software
+
+web2py contains third party software under the gluon/contrib/ folder.
+Each file/module in contrib is distributed with web2py under its original license.
+Here we list some of them.
+
+#### gluon.contrib.simplejson LICENSE
+
+Copyright (c) 2006 Bob Ippolito - Permission is hereby granted, free of charge,
+to any person obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+#### gluon.contrib.rss2.py (originally PyRSS2Gen) LICENSE
+
+This is copyright (c) by Dalke Scientific Software, LLC and released under the
+BSD license. See the file LICENSE in the distribution or
+<http://www.opensource.org/licenses/bsd-license.php> for details.
+
+#### gluon.contrib.markdown (markdown2) LICENSE
+
+MIT License from from <http://code.google.com/p/python-markdown2/>
+
+#### gluon.contrib.feedparser LICENSE
+
+Copyright (c) 2002-2005, Mark Pilgrim
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+#### gluon.wsgiserver.py LICENSE (borrowed from cherrypy)
+
+Copyright (c) 2004, CherryPy Team (team@cherrypy.org)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the CherryPy Team nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#### gluon.contrib.pam LICENSE
+
+Copyright (C) 2007-2009 Chris AtLee <chris@atlee.ca> Licensed under the MIT license
+
+#### gluon.contrib.shell LICENSE
+
+Copyright (C) by Google inc. Apache 2.0 Lincense
+
+#### The javascript licenses are in the code itself
+
1  MANIFEST.in
@@ -0,0 +1 @@
+include VERSION LICENSE
123 Makefile
@@ -0,0 +1,123 @@
+clean:
+ rm -f httpserver.log
+ rm -f parameters*.py
+ rm -f -r applications/*/compiled
+ find ./ -name '*~' -exec rm -f {} \;
+ find ./ -name '*.orig' -exec rm -f {} \;
+ find ./ -name '*.rej' -exec rm -f {} \;
+ find ./ -name '#*' -exec rm -f {} \;
+ find ./ -name 'Thumbs.db' -exec rm -f {} \;
+ find ./gluon/ -name '.*' -exec rm -f {} \;
+ find ./gluon/ -name '*class' -exec rm -f {} \;
+ find ./applications/admin/ -name '.*' -exec rm -f {} \;
+ find ./applications/examples/ -name '.*' -exec rm -f {} \;
+ find ./applications/welcome/ -name '.*' -exec rm -f {} \;
+ find ./ -name '*.pyc' -exec rm -f {} \;
+all:
+ echo "The Makefile is used to build the distribution."
+ echo "In order to run web2py you do not need to make anything."
+ echo "just run web2py.py"
+epydoc:
+ ### build epydoc
+ rm -f -r applications/examples/static/epydoc/
+ epydoc --config epydoc.conf
+ cp applications/examples/static/title.png applications/examples/static/epydoc
+tests:
+ cd gluon/tests; ./test.sh 1>tests.log 2>&1
+update:
+ wget -O gluon/contrib/feedparser.py http://feedparser.googlecode.com/svn/trunk/feedparser/feedparser.py
+ wget -O gluon/contrib/simplejsonrpc.py http://rad2py.googlecode.com/hg/ide2py/simplejsonrpc.py
+src:
+ echo 'Version 1.99.3 ('`date +%Y-%m-%d\ %H:%M:%S`') dev' > VERSION
+ ### rm -f all junk files
+ make clean
+ ### clean up baisc apps
+ rm -f routes.py
+ rm -f applications/*/sessions/*
+ rm -f applications/*/errors/* | echo 'too many files'
+ rm -f applications/*/cache/*
+ rm -f applications/admin/databases/*
+ rm -f applications/welcome/databases/*
+ rm -f applications/examples/databases/*
+ rm -f applications/admin/uploads/*
+ rm -f applications/welcome/uploads/*
+ rm -f applications/examples/uploads/*
+ ### make admin layout and appadmin the default
+ cp applications/admin/views/appadmin.html applications/welcome/views
+ cp applications/admin/views/appadmin.html applications/examples/views
+ cp applications/admin/controllers/appadmin.py applications/welcome/controllers
+ cp applications/admin/controllers/appadmin.py applications/examples/controllers
+ ### update the license
+ cp ABOUT applications/admin/
+ cp ABOUT applications/examples/
+ cp LICENSE applications/admin/
+ cp LICENSE applications/examples/
+ ### build web2py_src.zip
+ echo '' > NEWINSTALL
+ mv web2py_src.zip web2py_src_old.zip | echo 'no old'
+ cd ..; zip -r web2py/web2py_src.zip web2py/gluon/*.py web2py/gluon/contrib/* web2py/splashlogo.gif web2py/*.py web2py/ABOUT web2py/LICENSE web2py/README 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
+app:
+ echo 'did you uncomment import_all in gluon/main.py?'
+ python2.5 -c 'import compileall; compileall.compile_dir("gluon/")'
+ #python web2py.py -S welcome -R __exit__.py
+ find gluon -path '*.pyc' -exec cp {} ../web2py_osx/site-packages/{} \;
+ cd ../web2py_osx/site-packages/; zip -r ../site-packages.zip *
+ mv ../web2py_osx/site-packages.zip ../web2py_osx/web2py/web2py.app/Contents/Resources/lib/python2.5
+ cp ABOUT ../web2py_osx/web2py/web2py.app/Contents/Resources
+ cp NEWINSTALL ../web2py_osx/web2py/web2py.app/Contents/Resources
+ cp LICENSE ../web2py_osx/web2py/web2py.app/Contents/Resources
+ cp VERSION ../web2py_osx/web2py/web2py.app/Contents/Resources
+ cp README ../web2py_osx/web2py/web2py.app/Contents/Resources
+ cp splashlogo.gif ../web2py_osx/web2py/web2py.app/Contents/Resources
+ cp options_std.py ../web2py_osx/web2py/web2py.app/Contents/Resources
+ cp routes.example.py ../web2py_osx/web2py/web2py.app/Contents/Resources
+ cp router.example.py ../web2py_osx/web2py/web2py.app/Contents/Resources
+ cp app.example.yaml ../web2py_osx/web2py/web2py.app/Contents/Resources
+ cp queue.example.yaml ../web2py_osx/web2py/web2py.app/Contents/Resources
+ cp -r applications/admin ../web2py_osx/web2py/web2py.app/Contents/Resources/applications
+ cp -r applications/welcome ../web2py_osx/web2py/web2py.app/Contents/Resources/applications
+ cp -r applications/examples ../web2py_osx/web2py/web2py.app/Contents/Resources/applications
+ cp applications/__init__.py ../web2py_osx/web2py/web2py.app/Contents/Resources/applications
+ cd ../web2py_osx; zip -r web2py_osx.zip web2py
+ mv ../web2py_osx/web2py_osx.zip .
+win:
+ echo 'did you uncomment import_all in gluon/main.py?'
+ python2.5 -c 'import compileall; compileall.compile_dir("gluon/")'
+ find gluon -path '*.pyc' -exec cp {} ../web2py_win/library/{} \;
+ cd ../web2py_win/library/; zip -r ../library.zip *
+ mv ../web2py_win/library.zip ../web2py_win/web2py
+ cp ABOUT ../web2py_win/web2py/
+ cp NEWINSTALL ../web2py_win/web2py/
+ cp LICENSE ../web2py_win/web2py/
+ cp VERSION ../web2py_win/web2py/
+ cp README ../web2py_win/web2py/
+ cp splashlogo.gif ../web2py_win/web2py/
+ cp options_std.py ../web2py_win/web2py/
+ cp routes.example.py ../web2py_win/web2py/
+ cp router.example.py ../web2py_win/web2py/
+ cp app.example.yaml ../web2py_win/web2py/
+ cp queue.example.yaml ../web2py_win/web2py/
+ cp -r applications/admin ../web2py_win/web2py/applications
+ cp -r applications/welcome ../web2py_win/web2py/applications
+ cp -r applications/examples ../web2py_win/web2py/applications
+ cp applications/__init__.py ../web2py_win/web2py/applications
+ cd ../web2py_win; zip -r web2py_win.zip web2py
+ mv ../web2py_win/web2py_win.zip .
+pip:
+ # create Web2py distribution for upload to Pypi
+ # after upload clean Web2py sources with rm -R ./dist
+ python setup.py sdist
+run:
+ python2.5 web2py.py -a hello
+push:
+ make src
+ echo '' > NEWINSTALL
+ hg push
+ bzr push bzr+ssh://mdipierro@bazaar.launchpad.net/~mdipierro/web2py/devel --use-existing-dir
+
1  NEWINSTALL
@@ -0,0 +1 @@
+
1,178 README
@@ -0,0 +1,1178 @@
+## INSTALLATION INSTRUCTION - IMPORTANT
+
+To start web2py there is NO NEED to install it. Just unzip and do:
+
+> python web2py.py
+
+Thats is it!!!
+
+## web2py file structure
+
+start web2py with:
+
+ python web2py.py
+
+``
+ \project
+ README
+ LICENSE
+ TODO
+ Makefile ## make all and make app
+ web2py.py ## the startup script (*)
+ parameters.py ## created at startup
+ admin.tar ## the admin app (*)
+ examples.tar ## examples and documentation app (*)
+ welcome.tar ## the welcome app (entry point) (*)
+ \gluon ## the core libraries (*)
+ \deposit ## used for zip and install apps
+ setup_app.py ## used by py2app to make OSX executable
+ setup_exe.py ## used by py2app to make Winows executble
+ wsgihandler.py ## to use Gluon with mod_wsgi
+ \dist ## used by py2app, py2exe
+ \build ## used by py2app, py2exe
+ \tests ## under development stuff
+ \docs ## in progress documentation
+ \applications ## are the apps
+ \welcome ## application welcome, for example
+ \models
+ \views
+ \controllers
+ \sessions
+ \errors
+ \cache
+ \static
+ \uploads
+ \modules
+``
+
+## EWF v1.5 -> v1.6
+- load and save .py in ascii, avoids problem with LF+CR on windows
+- added path.join in compileapp, fixed problem with Windows compileapp
+
+## EWF v1.6 -> v1.7
+- in paths replace '\' with '/' to fix problem with windows paths
+- using limitby in database administration
+- replaced mime/miltupart with multipart/form-data to fix a windows problem
+
+## EWF v1.7 -> Gluon v1.0
+- Name change
+- Improved layout.html
+
+## Gluon v1.0 -> v1.1
+- bug in sqlhtml with JOINS queries
+
+## Gluon v1.1 -> v1.2
+- fixed some typos in examples
+- IS_IN_SET now supports labels
+- cleanup in sql.py does not cleanup, just checks valid field and table names
+
+## Gluon v1.3
+- added IS_IN_DB, IS_NOT_IN_DB and updated examples accordingly
+
+## Gluon v1.4
+- fixed problem with IS_INT_IN_RANGE and IS_FLOAT_IN_RANGE. Now an error in a validator is reported as a ticket. Good validators should not raise Exceptions.
+- IS_IN_DB displays "label (id)"
+- it can upload files without extension
+- migration is now optional (define_table has migrate=False option)
+
+## Gluon v1.5
+- <form> -> <form method="post"> in errors.html
+- replace('//','////') in sub in template.py
+
+## Gluon v1.8
+- no more chdir (thread unsafe)
+- no more sys.stdout (thread unsafe)
+- response.body is StringIO()
+- admin/default/site informs about upgrade
+- response.locker (optional)
+
+## Gluon v1.9
+- allow "count(*)" in select
+- db.execute()
+- fixed problem with continue and return in template
+- removed try: ... except in sql.py
+- fixed '\t'
+
+## Gluon v1.10
+- fixed concurrency problems with SQLDB._instances and SQLDB._folders, now use lock
+- now, by default, edit SQLFORMs retain uploaded files
+
+## Gluon v1.11
+- appadmin allows to keep or delete uploaded files
+
+## Gluon v1.12
+- in sql.py
+- handles NULL values properly
+- unicode support (data always stored in utf-8)
+- 'date' -> datetime.date ,'time' -> datetime.time, 'datetime' -> datetime.datetime, 'boolean' -> True/False
+- most types have default validators
+- SQLField(...,required=True) option.
+- SQLRows has __str__ that serializes in CSV and xml() that serializes in HTML
+- SQLTable has import_from_csv_file(...)
+- gluon.simplejson for AJAX
+- in validators.py
+- IS_IN_DB(db,..) - db can be an SQLSet or an SQLDB
+- better error messages
+- in admin
+- new import/export in csv, update and delete interface.
+- in appadmin
+- edit form allows to keep stored encrypted password
+- in main.py
+- http://host not defaults to http://host/init/default/index
+- New third party modules
+- gluon.simplejson(.dumps, .loads)
+- gluon.pyrtf(.dumps)
+- gluon.rss2(.dumps)
+
+## Gluon v1.13
+- (this is one of the biggest revisions ever)
+- Improved sql.py has support MySQL, cxOracle (experimental), extract, like and better testing
+- SQLDB.tables and SQLTable.fields are now SQLCalableList objects
+- Fixed bug with editing integer fields storing zero
+- Admin interface now says "insert new [tablename]" and display insert, select or update properly in the title.
+- Added a cache mechamism. Works for data, controllers, views and SQLRows.
+- main.py now uses a request.folder absolute path when not os.name in ['nt','posix']. Seems to work on windowsce devices, except no file locking has consequences.
+- Now you can put modules in applications/[anyapp]/modules and import them with
+- import applications.[anyapp].modules.[module] as [module]
+- Fixed problem with init
+- New applications/examples/controller/global.py controller for docs.
+
+## Gluon v1.14
+- Fixed a bug fix in URLs
+
+## Gluon v1.15
+- New try:... except. in gluon/main.py for when sessions cannot be saved
+- Now validator/formatter method allows IS_DATE('%d/%m/%Y')
+
+## web2py v1.16
+- yes we changed the name! Turns out Gluon was trademarked by somebody else.
+- Although we are not infringing the trademark since this is a non-commercial
+- product we could have run into some issues. So we have been professional
+- and changed the name to web2py.
+- Now SQLFORMs and FORM can have a formname and multiple forms are allowed
+- per page.
+- A new examples/default/index page.
+- web2py.py instead of runme.py
+- mysql sets utf8 encoding.
+- input integer field values are automatically converted int().
+
+## web2py v1.17
+- I posted v1.16 too soon. v1.17 was released after 1h to fix some bugs.
+
+## web2py v1.18
+- removed vulnerability in accept_languages and session_id
+- Minor bug fixes. Typos and cleanup cache. Textarea now clears.
+- Support for PyAMF.
+- T returns a class, not a string
+- new template parser (faster?)
+- got rid of sintaxhighlighter in favor of server side CODE
+- fix problem with cacheondisk locking
+- fix 'None' instead of NULL in IS_NOT_IN_DB (I think)
+- gluon.contrib.markdown
+- notnull and unique in SQLField now supported (tested on sqlite mysql and postgresql)
+- Storage now has __getstate__ and __setstate__ needed for pickling.
+- session files are now locked to make it work better with asynchronous requests
+- cxoracle should work, apart for limitby
+- .../examples is now mapped to .../examples/default/index etc.
+- .../init is now mapped to .../welcome if init is not present
+
+## web2py 1.19
+- minor typos
+
+## web2py 1.20
+- new IFRAME, LABEL, FIELDSET validators
+- P(..cr2br=True) option
+- FORM and SQLFORM have hidden=dict(...) option for REST
+- testing framework.
+- improved examples pages
+
+## web2py 1.21
+- replaced paste.httpserver with cherrypy.wsgi server
+- temporary sessions are no longer saved
+- widget has [stop] button and graph
+- logging is done by main by appfactory
+- fixed a bug in sql belongs
+
+## web2py 1.22-1.25
+- fixed minor bugs, added IS_NULL_OR
+
+## web2py 1.26
+- added shell.py (thanks Limodou!)
+- added memcache support
+
+## web2py 1.27
+- IS_NULL_OR now works will all fields
+- admin creates paths to static files
+- wsgiserver options are passed to HttpServer
+- faking limitby for oracle to make appadmin work
+- all objects inherit from object
+- fixed bug in app names with .
+- fixed bug in created RestrictedError object on windows
+- shell is now in gluon and accessible via web2py.py
+
+## web2py 1.28
+- fixed bug with belongs, faster sql.py
+- included jquery.js
+- minor aestetical fixes
+- sortable.js is gone
+
+## web2py 1.29
+- Now selet mutliple works with get, so does is IS_LENGTH
+- Added IS_LIST_OF
+- fixed problem with admin from windows and localhost
+
+## web2py 1.30
+- added flv to contenttype
+- added support for appengine
+
+## web2py 1.31-1.41
+- some bug fixes, mostly better appengine support
+- mssql support
+- firebird support
+- widgets support
+- connection pools
+
+## 1.42
+- fixed security issue by removing slash escape in mysql
+- removed random everywhere
+- use uuid for session and tickets
+- use http_x_forward_for to figure out the client causing a ticket
+- use longtext and longblob for mysql
+- main now really catches all exceptions
+- no more warnings on GAE
+
+## 1.43-1.48
+- html.py rewrite (better support for custom forms) (Bill Ferrett)
+- new stickers in examples (thanks Mateusz)
+- on windows can run in taskbar (Mark Larsen)
+- in admin|edit page link to edit|controller (Nathan Freeze)
+- better error codes and routes_onerror (Timothy Farrell)
+- DAL support for groupy and having
+- DAL support for expressions instead of values
+- DAL has experimental Informix support
+- fixed bug with non-printable chars in DAL
+- 'text' fields limited to 2**16 (to avoid mysql problems)
+- widget has -quiet and -debug (Attila Csipa)
+- web2py_session uses BLOB instead of TEXT
+- improved IS_URL
+- Runs with python 2.6 (Tim)
+- On GAE uses GAE for static files (Robin)
+
+
+## 1.49
+- fixed a bug with taskbar widget, thanks Mark
+- fixed a bug with form.latest
+- made many DIV methods private (_)
+
+
+## 1.50
+- Fixed some bugs introduced in 1.49
+
+## 1.51
+- Fixed more bugs introduced in 1.49 (sql _extra and html select)
+- support for sqlite:memory:
+
+## 1.52
+- Fixed a minor bug with _extra[key] and key not str.
+- check for upgrade via ajax
+
+## 1.53
+- On GAE upload data goes automatically in datastore (blob created automatically)
+- New appadmin runs on GAE (most of it, not all)
+- Martin Hufsky patch allow slicing of fields in DAL expressions
+
+## 1.54
+- fixed minor bugs
+
+## 1.55?
+- rowcount
+- fixed bug when IS_IN_DB involved multiple fields on GAE
+- T.set_current_languages
+- better unittests
+- response.custom_commit and response.custom_rollback
+- you can next cache calls (like cache a controller that caches a select). Thanks Iceberg
+- db(....id==None).select() no longer returns an error but an empty SQLRows on GAE
+- db(...).delete(delete_uploads=True) and SQLFORM.accepts(....delete_uploads=True) will delete all referenced uploaded files
+- DIV.element and DIV.update
+- sqlrows.json()
+- SQLFORM.widgets
+- URL(r=request,args=0)
+- IS_IN_DB(...,multiple=True) for Many2Many (sort of)
+- In URL(...,f) f is url encoded
+- In routes_in=[['a/b/c/','a/b/c/?var=value']]
+- simplejson 2.0.7
+
+
+## 1.56
+- Consider the following table:
+
+- db.define_table('cirlce',
+- db.Field('radius','double'),
+- db.Field('area','double'),
+- db.Field('modified_on','datetime'))
+
+- now you can do:
+
+## add a comment in the forms
+- db.circle.area.comment="(this is a comment)"
+
+## do not show area in create/edit forms
+- db.circle.area.writable=False
+
+- ## do not show now in display forms
+- db.circle.modified_on.readable=False
+
+## automatically timestamp when record cretaed
+- db.circle.modified_on.default=request.now
+
+## automatically timestamp when record is modified
+- db.circle.modified_on.update=request.now
+
+## make the radius appear in bold in display and table
+- db.circle.radius.represent=lambda value: B(value)
+
+## make a form that automatically computes area
+- pi=3.1415
+- form=SQLFOM(db.circle)
+- if form.accepts(request.vars,
+- onvalidation=lambda form: form.vars.area=pi*form.vars.radius**2): ...
+
+## make a create form in two possible ways:
+- form=SQLFORM(db.circle)
+- form=SQLFORM(db.circle,0)
+
+## make an update form in two possible ways:
+- form=SQLFORM(db.circle,record)
+- form=SQLFORM(db.circle,record_id)
+
+## make a display form in two possible ways:
+- form=SQLFORM(db.circle,record,readonly=True)
+- form=SQLFORM(db.circle,record_id,readonly=True)
+
+## so now you can do...
+
+- form=SQLFORM(db.circle,request.args[-1])
+
+- and you get a create form if the URL ends in /0, you get an update
+- form if the URL ends in /[valid_record_id]
+
+## you can also define once for all
+
+- timestamp=SQLTable(None,'timestamp',
+- SQLField('created_on','datetime',
+- writable=False,
+- default=request.now),
+- SQLField('modified_on','datetime',
+- writable=False,
+- default=request.now,update=request.now))
+
+## and use it in all your tables
+
+- db.define_table('mytable',db.Field('somefield'),timestamp)
+
+## ## ##
+
+- One more feature in trunk....
+
+- db.define_table('image',SQLField('file','upload'))
+
+- db.image.file.authorize=lambda row: True or False
+
+- then controller
+- def download(): return response.download(request,db)
+- id' is now a hidden field sqlform
+- gql references converted to long
+- admin login has autofocus
+- new notation proposed by Robin, db.table[id]
+- new UploadWidget shows images
+- new generic.html shows request, response, session
+- new LEGEND helper (thanks Marcus)
+- fixed doctests in sql (thanks Robin)
+- new notation for DB
+
+- record=db.table[id]
+- db.table[id]=dict(...)
+- del db.table[id]
+
+- request.env.web2py_version
+- new class gluon.storage.Settings has lock_keys, lock_values
+- jquery 1.3.1
+- PEP8 compliance
+- new examples application
+- runs on jython (no database drivers yet, thanks Phyo)
+- fixed bugs in tests
+- passes all unittest but test_rewite (not sure it should pass that one)
+
+- Lots of patches from Fran Boone (about tools) and Dougla Soares de Andarde (Python 2.6 compliance, user use of hashlib instead of md5, new markdown2.py)
+
+## 1.56.1-1.56.4
+- fixing lots of small bugs with tool and languages
+- jquery.1.3.2
+
+## 1.57
+- New ajax edit with keepalive (no longer logged out when editing code)
+- Fixed conflict resolution page.
+- Removed /user/bin/python from models/controllers
+
+## 1.58
+- Fixed some CRON bugs
+- Fixed a bug with new ajax edit
+- Experimental DB2 support in DAL
+- Customizable font size in admin edit page
+- New welcome/models/db.py shows how to memcache sessions on GAE with MEMDB
+- More expressive titles in admin
+- DB2 support. Thanks Denes!
+
+## 1.59-1.60
+- fixed lots of small bugs
+- routes_in can filter by http_host
+
+## 1.61
+- fixed some typos
+- auth.add_permissions(0,....) 0 indicates group of current user
+- crud.update has deletable=True or False
+- fixed issue with GAE detection -> gluon.settings.web2py_runtime -> request
+
+## 1.62
+- SQLFORMS and crud now show readble fields
+- Better WingIDE support
+- Languages are automatically translated
+- T.force and lazyT works better, optional T.lazy=False
+- gluon.storage.Messages are now translated without T
+- if routes.py then request.env.web2py_original_uri
+- db.table.field.isattachment = True
+- internationalizaiton of admin by Yair
+- admin.py by Alvaro
+- new MENU helper
+- new w2p file format
+- new welcome app with auth, service and crud turned on
+
+## 1.63-1.63.4
+- no more import gluon.
+- support for generic.xxx
+- simplejson can handle datetime date and time
+
+## 1.63.5
+- You can do jQuery.noConflict() without breaking web2py_ajax
+- Wigets can have attributes (thanks Hans)
+- Lots of internal cleanup and better code reusage (thanks Hans)
+
+## 1.64
+- Models 2-3 times faster (thanks Alexey)
+- Better LDAP support
+- Works with Jython (including sqlite and postgresql with zxJDBC):
+
+- download jython-2.5rc3.jar
+- download qlite-jdbc-3.6.14.2.jar
+- java -jar jython-xxx.jar
+- export CLASSPATH=$CLASSPATH:/Users/mdipierro/jython2.5rc3/sqlite-jdbc-3.6.14.2.jar
+- cd web2py
+- ../jython2.5rc3/jython web2py.py
+
+## 1.64.2
+- New IS_COMPLEX validator, thank Mr. Freeze
+- Experimental Informix support
+- Autologin on registration
+
+## 1.64.3
+- Some bug fixes
+
+## 1.64.4
+- Som bug fixes
+- Informix Support
+- response.render(stream)
+- SQLFORM.factory
+- SQLFORM.widgets.radio and SQLFORM.widgets.checkboxes
+
+## 1.65
+- reST docstrings for Sphinx, thanks Hans
+- gluon/conrtib/login_methods/gae_google_account.py for google CAS login on GAE, thanks Hans
+- fixed problem with Auth and Firebird 'password' issue
+- new auth.settings.create_user_groups
+- tickets stored on datastore on GAE and also logged, thanks Hans
+- imporved IS_LENGTH with max and min, thanks Mateusz
+- improved IS_EMAIL with filters, thanks Mateusz
+- new IS_IMAGE checks for format and size, thanks Mateusz
+- new IS_IPV4, thanks Mateusz
+
+## 1.65.1
+- spreadsheet
+- shell history, thanks sherdim
+- crontab editor, thanks Angelo
+- gluon/contrib/login_methods/cas_auth.py (thanks Hans)
+- DAL(...) instead of SQLDB(...)
+- DAL('gae') instead of GQLDB()
+- Field instead of SQLField
+- (the old syntax still works)
+
+## 1.65.2
+- Fixed some small auth bugs
+- Field.store(...)
+
+## 1.65.3-10
+- Fixed some small bugs and typos in the docstrings
+- Fixed AMF3 support
+
+## 1.65.11
+- Fixed a sqlhtml bug with image upload
+
+## 1.65.12
+- lables in auth auto-translate (thanks Alvaro)
+- better ldap_auth (thanks Fran)
+- auth chacks locally for blocked accounts even for alternate login methods (thanks Fran)
+
+## 1.65.13
+- request.url (thanks Jonathan)
+- restored uploadfield_newfilename
+- new examples layout nad logo (thanks Mateusz)
+
+## 1.66
+- new doctypes
+- form.vars.newfilename
+- new HTML and XHTML helpers
+- better IS_LENGTH
+
+## 1.67.0
+- Python 2.4 support (again)
+- New layout for welcome
+- changed defauld field sizes to 512
+- Field(uploadfolder="...")
+- appadmin works on GAE (again, somehting got broken at some point)
+- new wsgiserver 3.2.0 should fix recurrent broken download problems
+
+## 1.67.1
+- Bux fixed
+
+## 1.67.2
+- Security fix in markdown
+
+## 1.68.1
+- New official markdown with security fix
+- rows.first()
+- rows.last()
+- New cron
+- New hindi and spanish translation
+- cached uploads allow for progress bars (thanks AndCycle)
+- ingres support (thanks Chris)
+- legacy database support for db2, mssql with non-int primary keys (thanks Denes)
+- default setting of content-type (this may cause strange behavior in old apps when downloading images)
+- IS_UPPER and IS_LOWER works with unicode
+- CLENUP not takes regex of allowed/now allowed chartares
+- New rewrite.py allows dynamic routes
+- Better error messages for IS_INT_* and IS_FLOAT_*
+
+## 1.68.2
+- Fixing bug with admin and missing crontab
+- Fixing bug with rewrite.load on GAE (thanks Willian Wang)
+
+## 1.69.1
+- Fixed a bug introduced in 1.68 about inserting unicode in DAL
+- Fixed other small bugs
+- Better support for legacy databases (thank Denes)
+- response.meta replaces response.author, response.keywords, response.description
+- response.files stets dependes in plugins
+- better admin for packing/unpacking plugins
+- reference fiels nor evaluate to DALRef with lazy evaluation (cool, thanks Mr Freeze)
+- can insert a record in place of a reference
+- record[e] instead of record._extra[e] (tentatively!)
+- record.update_record() with no args
+- rows.find() (thanks Mr Freeze)
+- rows.exclude()
+- rows.sort()
+- rows[:]
+
+## 1.70.1
+- Fixed bug with Rows.as_list and DALRef
+- Added Rows.as_dict (thanks Mr Freeze and Thedeus)
+- Added request.wsgi (thanks hcvst) allows running wsgi apps under web2py and applying wegi middleware to regular web2py actions that return strings.
+- Experimental distributed transactions between postgresql, mysql and firebird
+- Finally local_import is here!
+
+## 1.71.1
+- Complete rewrite of Rows
+- renamed DALStorage->Rows, DALRef->Reference
+- Experimental serializarion of Row and Rows (get serialized to dict and list of dict)
+- DAL(...,folder) and template.render(content=, context=) make it more modular
+
+## 1.72.1 - 1.72.3
+- Better support for legacy databases
+
+## 1.73.1
+- Fixed problem with storage and comparison of Row objects
+- Fixed problem with mail on GAE
+- Fixed problem with T in IS_DATE(TIME) error_message and format
+- Rows[i].delete_record()
+- Even better support for legacy databases
+- Experimantal support for non UTF8 encoding in DB
+- Better IPV4 (thanks Thandeus)
+- T.current_languages default to 'en' and new T.set_current_languages(...) (thanks Yarko)
+- INPUT(...,hideerror=False) used to fix rare chechbox widget problem
+- Admin allows change of admin password
+- New gluon/contrib/populate.py
+- Size of input/textarea set by CSS no more by jQuery (thanks Iceberg)
+- Customizable CSV (thanks Thandeus)
+- More bug fixed (thanks Thandeus)
+- Better regex for template fixed Jython problem (thank Jonathan)
+
+## 1.74.1
+- Moved to mercurial
+- Default validators use the new define_table(....,format='...')
+- New get_vars and post_vars compatible in 2.5 and 2.6 (thanks Tim)
+- Major rewrite of gql.py extends DAL syntax on GAE
+- No more *.w2p, welcome.w2p is create automatically, base apps are always upgraded
+- export_to_csv(delimiter = ',', quotechar = '"', quoting = csv.QUOTE_MINIMAL), thanks Thadeus
+
+## 1.74.2-4
+- Fix bugs including including unicode in emails and blobs on GAE
+
+## 1.74.5
+- bug fixes
+- restored python 2.4 support,thanks ont.rif
+- support for native types on Google App Engine
+- cache.ram usage statictics, thanks Thadus
+- no more auth manu in scaffolding
+- no more spash screen with -Q
+- fixed doctest in html.py, thanks Anand Vaidya
+- export_to_csv_file has represent, thanks Thadeus
+
+## 1.74.6
+- bug fixes
+- IS_IN_DB(...,_and=IS_NOT_IN_DB)
+- Smaller populate, thanks Piotr
+- better slicing of fields, thanks Michael Fig
+- Cache stats, thanks Thadeus
+- Better gql.py
+- IS_IN_DB and IS_IN_SET default to zero='', no longer zero=None
+
+## 1.74.7
+- request_password_reset and password reset verification
+- python web2py.py -S app -M -R script.py -A arg1 arg2 arg3
+- T("%(a)s") % dict(a="hello")
+
+## 1.74.8
+- IS_SLUG, thanks Gustavo and Jonathan
+- web2py.py -nogui, thanks Jeff Bauer
+- solved a problem with jython, thanks Tim Farrel
+- login has "remember be option", thanks Piotr Banasziewicz
+- fixed problem with keepvalue in update forms, thanks Miguel Lopez
+
+## 1.74.9
+- IS_IN_SET(((0,'label0'),(1,'label1'))), thanks Falko Krause
+- SQLFORM(...).accpets stores True or False in boolean types no None, thanks Frederik Wagner
+- SQLFORM.factory(...,table_name='no_table'), thanks Thedeus
+- jQuery 1.4.1
+- Fixed major problem with internationalization of multiple languages.
+- Fixed a serius security issue with login
+- Possibly fixed some issues with cron
+
+## 1.75.1
+- better cron
+- better fetch
+- logging of email failures
+- new web2py.fedora.sh
+- new setup-web2py-ubuntu.sh
+- experimental autocomplete
+- menus work on IE6
+
+## 1.75.2
+- fetch supports cache
+- curd.update(....,onaccept=crud.archive) magic
+- new UUID mechnism fixes session conflicts with cloned machine in cloud
+- allow to upload app and overwrite existing old ones, thanks Jonathan
+- print gluon.tools.prettydate(request.now,T), thanks Richard
+
+## 1.75.3
+- added support for PAM authentican for apps and for admin
+- INTRODUCED MAJOR BUG IN BEAUTIFY (upgrade to 1.75.4) IMMEDIATELY
+
+## 1.75.4
+- customizable BEAUTIFY, thanks John
+
+## 1.75.5
+- fixed behaviour with languages.py, thanks Iceberg
+- added chinese (thanks Iceberg) and Hungarian (thanks Gyuris)
+- fixed problem with GAE deleted by id (thanks what_ho)
+- fixed bug in LOAD with custom views, thanks vhang
+- improved IS_IN_SET takes iterator, dict, list and list of tuples, thanks Iceberg
+- Auth(...,controller='default')
+- Fixed major bug in parsing repeated request.vars, thanks Ben
+- IS_DATE and IS_DATETIME can now handle any 0<year
+- allow to disable editarea onload, thanks Alex
+
+## 1.76.1
+- editarea 0.8.2 + zencoding
+- new (better) cron locking meachnism
+- no storing session cookies on session.forget(), thank you Alvaro
+- routes_apps_raw allows disabling of request.args validation, thanks Jonathan and Denes
+- fixed problem with edit_languages ad multiple tabs, thanks Iceberg
+- crud captcha, thanks you Nathan
+- softcron disabled by default in wsgihandler and fcgihandler
+
+## 1.76.2-1.76.3
+- major fix in cron (will I ever get this 100% right?)
+- fix in delete for GAE
+- auth.settings.login_captcha and auth.settings.register_captcha
+- crud.settings.create_captcha and crud.settings.update_captcha
+- automatic update button in admin
+
+## 1.76.4
+- SQLTABLE(db(db.auth_user.id>0).select(),headers='fieldname:capitalize')
+- Oracle limitby improved (thanks Sergey)
+- fixed migrations in Firebird, thanks Jose Jachuf
+- gluon/contrib/login_methods/linkedin_account.py (to be tested)
+
+## 1.76.5
+- Fixed a typo in auth that created some registration problems
+
+## 1.77.1
+- Replaced CherryPy with Rocket web server, thanks Tim
+- CacheOnDisk allows to specify a folder
+- IS_DATE/DATETIME can handle any year since 0
+- SQLTABLE(...,headers='fieldname:capitalize')
+- Field().with_alias, thanks Nathan and Mengu
+- has_membership(group=...,role=...), thank Jonathan
+- db.define_table(username=True), thanks Jonathan
+- gluon.tools.prettydate
+- can specify hostname in routes_out (same syntax as routes in), thanks Martin
+- db.table.bulk_insert([...records...]) now works on GAE, thanks Jon
+- IS_EMAIL validates on 'localhost', thanks Jonathan
+- welcome/views/layout.html uses ez.css, thanks Yarko
+- mail attachments support utf8, thanks szimszon
+- works with PyPy, thanks Joe
+- better Firebird support, thanks Jose
+- better Oracle support, thanks Gabriele
+- cron supports days of week
+- SQLFORM(...,formstyle="table3cols") or "table2cols" or "divs" or "ul"
+- crud.settings.formstyle
+- web2py.py -f folder allows to specify locations of applications, thanks Iceberg
+- better/faster regex in template works in Jython
+- fixed lots of small bugs
+
+## 1.77.2
+- fixed x-index in calendar
+## 1.77.3
+- some cleanup of code in compileapp
+
+## 1.78.1
+- new template system allows {{block name}}{{end}}, thanks Thadeus
+- fixed mime headers in emails, included PGP in emails, thanks Gyuris
+- automatic database retry connect when pooling and lost connections
+- OPTGROUP helper, thanks Iceberg
+- web2py_ajax_trap captures all form submissions, thank you Skiros
+- multicolumn checkwidget and arbitrary chars in multiple is_in_set, thanks hy
+- Québécois for welcome, thanks Chris
+- crud.search(), thanks Mr Freeze
+- DAL(...migrate,fake_migrate), thanks Thadeus
+
+## 1.78.3
+- reverted temporarily to old template system because of backward compatibility issues
+
+## 1.79.1
+- x509 emails, thanks Gyuris
+- attachment and html in Mail on GAE, thanks PanosJee
+- fixed docstring in SQLTABLE, thanks aabelyakov
+- TAG(html) parese html into helpers (experimental, still some problems with unicode, , thanks RobertVa for unicode help)
+- DIV.elements(find=re.compile(....))
+- DIV.flatten()
+- DIV.elements('....') supports jQuery syntax in '....'
+- better it-it.py and it.py, thanks Marcello Della Longa
+- Many Bug fixes:
+- improved support for DAL and joins in postgresql/oracle, thanks Nico de Groot
+- bux fixex in html.py, thanks Ian
+- fixed an issue with registration_key==None, thanks Jay Kelkar
+- fixed bug in gql.py, thanks NoNoNo
+- fixed problem with multiple and checkboxes, thanks MIchael Howden
+- fixed bug in gae, thanks NoNoNo
+- restored 2.4 compatibility, thanks Paolo Gasparello
+- auth.update() when pictures in profile
+- formstyle can be a function, thanks Howden
+- escape in sanitizer, thanks Howes
+- add missing settings, thanks Hamdy
+- find and exclude return empty Rows instead of [], thanks iceberg
+- simplejson 2.1.1 should fix compatibility problems
+- added sms_utils and Authorize.net in contrib
+
+## 1.79.2
+- solved simplejson imcompatibility problem
+
+## 1.80.1
+- MARKMIN helper (no backward compatibility promise yet)
+- self._last_reference, thanks Dave (no backward compatibility promise yet)
+- IS_EQUAL_TO
+- zh-tw and better internationalization page, thanks Daniel Lin and Iceberg
+- better crud.search, thanks MrFreeze
+- Rocket interfaces, thanks Nik Klever
+- db.table.field.uploadseparate=True, thanks Gyuris
+- SCOPE_IDENITY for MSSQL, thanks Jose
+- fixed email attachment issue, thanks Bob_in_Comox
+- fixed problem with groupby and IS_IN_DB
+- other bug fixes
+- new implementation for local_import
+- ajax(..,...,null)
+- fixed Chrome bug in calendar.js, thanks Iceberg
+- experimental scrips/web2py-setup-fedora.sh
+- generic.load, thanks Iceberg
+
+## 1.81.1
+- rpx (janrain) support out of the box, allows login with Facebook, MySpace, etc. Thanks Mr Freeze
+- Increased security (escape single and double quotes, thanks Craig"
+- Fixed a bug with db.table.field.uploadseparate=True and autodelete
+- New welcome app with superfish and jQuery 1.4.2
+- Deleted openwysiwyg from admin
+- In XML and xmlescape quote defaults to True. Both ' and " are escaped. Thanks Craig Younkins
+
+## 1.81.2
+- fixed bug in Auth
+
+## 1.81.3
+- fixed bug in label names in formstyle
+- fixed id names in admin test.html page
+
+## 1.81.4
+- Fixed gluon.tools to work work with load and base.css to nowrap labels
+
+## 1.81.5
+- Fixed a few bugs. The most important bugs we fixed are in memcache (thanks Scott) and in a process starvation issue with Rocket (thanks Mike Ellis and Tim).
+
+## 1.82.1
+- request.ajax to detect if action is called via ajax, tahnks Jonathan and David Mako
+- more captcha options, thanks Vidul
+- openid and oauth2 thanks Michele and Keith
+- better PluginManager and load components
+- new template system, thanks Thadeus
+- new db.table(id,[field=value]) and db.table(query) syntax
+- URL('index') (no more r=request), thanks Thadeus
+- mail.send(message='<html>...</html>', ....)
+- DAL([....]) for load balancing
+- @service.soap(...) with mysimplesoap, thanks Mariano
+- hideerror
+
+## 1.83.1
+- New error reporting mechanism (thanks Mariano)
+- New routing system with app level routing (thanks Jonathan)
+- Integrated GAE appstat and GAE precompilation (thanks Scott)
+- New Field types "list:string", "list:integer", "list:reference"
+- request.cid, request.ajax, A(cid=request.cid), response.js
+
+## 1.83.2
+- mostly cleanup
+
+## 1.84.1-4
+- flash now stays put in the top right corner
+- improved behavior for URL and T objects
+- new app level logging with logging.conf (thanks Jonathan)
+- improved OpenID (thanks Michele)
+- web2py_ajax handles prepend, append, hide (thanks Juris)
+- web2py_ajax also handels pre-validation of decimal fields
+- ru-ru translation (thanks Michele)
+- sk-sk translation (thanks Julius)
+- migrations save .table only if changed and after each ALTER TABLE (no more mysql inconsistencies)
+- fixed bugs in SQLCustomField, Field(default=...), IS_IMAGE, IS_DECIMAL_IN_RANGE and a few more.
+- Better validators (IS_DECIMAL_IN_RANGE, IS_INT_IN_RANGE, etc) thanks Jonatham
+- Polymmodel support on GAE
+- Experimental ListWidget
+- moved DAL and routes to thread.local (thanks Jonathan, again)
+- scripts/extract_mysql_models.py, thanks Falko Krause and Ron McOuat
+- scripts/dbsessions2trash.py, thanks Scott
+
+## 1.85.1-3
+- fixed some bugs
+- added pyfpdf, thank Mariano
+
+## 1.86.1-1.86.3
+- markmin2latex
+- markmin2pdf
+- fixed some bugs
+- Storage getfirst, getlast, getall by Kevin and Nathan
+- db(db.table), db(db.table.id) both suported and equivalent to db(db.table.id>0)
+- postresql ssl support
+- less un-necessary logging and warnings on GAE
+- IS_DECIMAL_IN_RANGE and IS_FLOAT_IN_RANGE support dot="," (dot="." is default)
+- on_failed_authorization can be a function, thanks Niphold
+- gluon/contrib/login_methods/cas_auth.py for integration between CAS and Auth.
+
+## 1.86.3
+- Error reporting on save, thanks Mariano
+recalled
+
+## 1.87.1-2
+- new layout for examples, thanks Bruno and Martin
+- admin allow ``DEMO_MODE=True`` and ``FILTER_APPS=['welcome']``
+- fixed a possible problem with CRON and paths
+
+
+## 1.87.3
+- fixed a major bug introduced in 1.87.1 that prevents appadmin from working for new apps created with 1.87.1-2.
+- upgraded to clockpick 1.28, thanks villas
+
+## 1.88.1-2
+- better list: string support, thanks Bob
+- jquery 1.4.3
+- scripts/autoroutes.py
+- new admin wizard
+- added retrieve_username to navbar (if username)
+- internal rewrite for arbitrary paths (abspath), thanks Jonathan
+- populate support for list: and decimal, thanks Chirstian
+- markmin2latex has extra attribute
+- better mercual admin allows list of files, versions and retrieve
+- new error report system, thanks Thadeus and Selecta
+- SQLFORM.accepts(detect_record_change).record_changed
+- fixed cron for bytecode compiled apps, thanks Álvaro J. Iradier Muro
+- other bugs fixes and pep8 compliant fixes
+
+## 1.89.1-.5
+- new admin layout (thanks Branko Vukelic)
+- new admin search
+- new admin language selector (thanks Yair)
+- new Welcome app (thanks Martin Mulone)
+- better wizard
+- admin support for DEMO_MODE=True
+- admin exposes GAE deployment button (always)
+- MENU support None links (thanks Michael Wolfe)
+- web2py.py -J for running cron (thanks Jonathan Lundell)
+- fixed ~db.table.id on GAE (thanks MicLee)
+- service.jsonrpc supports service.JsonRpcException (thanks Matt)
+- bug fixes
+
+## 1.90.1
+- new DAL (complete rewrite of the web2py DAL is more modular)
+- rewrite has fail safe reload, thanks Jonathan
+- better CAS with v2 support, thanks Olivier ROCH VILATO
+- better markmin2latex
+- session.connect(separate=True) to handle many session files, thanks huaiyu wang
+- changed bahvior of impersonate (more secure, can generate form or used as API)
+- new rocket, thanks Tim
+- new pyfpdf
+- no more old style classes
+- experimental couchdb support in new dal (only insert, select, update by id)
+- mysql support out of the box via pymysql
+- SQLITABLE(...,headers='labels') thanks Bruno
+- optional: digitally signed URLs, thanks Brian Meredyk
+- minor bug fixes
+
+## 1.90.2-4
+- pymysql no longer requires ssl (if not used)
+- fixed bug with virtualfields
+- fixed bug in truncate (new dal)
+- fixed bug in select with alternate primary key (new dal)
+- fixed bug with IS_IN_DB and self refences (also new dal)
+
+## 1.90.5
+- set poll = False in rocket because of poll python thread bug often unfixed, thanks Jonathan
+- fixes issue with crud and reCaptcha
+
+## 1.90.6
+- fix issue with pickling new dal Row and Rows.
+
+## 1.91.1
+- LICENSE CHANGE FROM GPLv2 to LGPLv3
+- URL(...,hash_vars=...) allows to specify which vars need to be signed
+- fixed bug with aliasing in new DAL
+
+## 1.91.2-1.91.5
+- fixed a problem with deplyment on GAE
+- other new dal bug fixes
+
+## 1.91.6
+- web2py comet via gluon/contrib/comet_messaging.py (html5 websockets) experimental
+- fixed problem with services (broken in 1.91.5), thanks Vollrath
+- customizable uploadwidget, thanks Fran
+- fixed problem with mail unicode support, thanks Richard
+- fixed problem with linkto=None and references fields in SQLTABLE, thanks villas
+- no more upgrade button on windows since does not work
+- better remember-me login, thanks Martin Weissenboeck
+- support for recatcha options
+- support for GAE namespaces via DAL('gae://namespace')
+- new rocket (1.2.2), thanks Tim
+- many other bug fixes and improvements (thanks Jonathan)
+
+## 1.92.1
+- much improved routing (thanks Jonathan)
+- Expression.__mod__ (thanks Denes)
+- admin has MULTI_USER_MODE (admin/models/0.py)
+- support for count(distinct=...)
+- has_permissions(...,group_id)
+- IS_MATCH(...,strict=True)
+- URL(...,scheme=,host=,port=), thanks Jonathan
+- admin in Afrikaans, thanks Caleb
+- auth.signature (experimental)
+- many other bug fixes
+
+## 1.93.1-2
+- support for multiple interfaces, thanks Jonathan
+- jquery 1.5.1
+- simplejson 2.1.3
+- customizable simplejson
+- leaner app.yaml
+- css3 buttons in welcome
+- android support (experimental)
+- Field(':hidden'), Field('.readonly'), Field('name=value')
+- combined expressions print db.data.body.len().sum()
+- wizard can download plugins
+- better json serilization (object.custom_json)
+- better xml serialization (object.custom_xml)
+- better formstyle support
+- better comet_messaging.py (needs more testing)
+- many bug fixes
+
+## 1.94.1
+- moderniz 1.17
+- web2py no longer saves session if no change, this makes it up up to 10x faster for simple actions
+- experimental REST API
+- better support for MSSQL NOT NULL
+- small bug fixes
+
+## 1.94.2
+- reverted wrong behavior of auth.requires(condition) in 1.94.1
+
+## 1.94.3
+- fixed major bug in auth redirection
+
+## 1.94.4
+- removed debug print statement that caused problems on GAE and mod_wsgi
+
+## 1.94.5
+- fixed a major bug with session introdued in 1.94.1
+
+## 1.94.6
+- fixed a number of minor bugs including adding some missing files
+- better session handling on session._unlock(..), thanks Jonathan
+- added experimental pip support, thanks Lifeeth
+- added experimental SAP DB support
+
+## 1.95.1
+- Google MySQL support (experimental)
+- pip support, thanks lifeeth
+- better setup_exe.py, thanks meredyk
+- importved pyfpdf
+- domain check in email_auth.py, thanks Gyuris
+- added change_password_onvalidation and change_password_onaccept
+- DAL(...,migrate_enabled=True)
+- login_methods/loginza.py, thanks Vladimir
+- bpython shell support, thanks Arun
+- request.uuid and response.uuid (for a future toolbar)
+- db._timings contains database query timing info
+- efficient db(...).isempty()
+- setup-web2py-nginx-uwsgi-ubuntu.sh
+- Many bug fixes, thanks Jonathan
+
+## 1.96.1
+
+- "from gluon import *" imports in every python module a web2py environment (A, DIV,..SQLFORM, DAL, Field,...) including current.request, current.response, current.session, current.T, current.cache, thanks Jonathan.
+- conditional models in
+ models/<controller>/a.py and models/<controller>/<function>/a.py
+- from mymodule import *, looks for mymodule in applications/thisapp/modules first and then in sys.path. No more need for local_import. Thanks Pierre.
+- usage of generic.* views is - by default - restricted to localhost for security. This can be changed in a granular way with: response.generic_patterns=['*']. This is a slight change of behavior for new app but a major security fix.
+
+- all applications have cas 2.0 provider at http://.../user/cas/login
+- all applications can delegate to login to external provider Auth(...,cas_provider='http://.../other_app/default/user/cas')
+- A(...,callback=URL(...),larget='id') does Ajax
+- URL(...,user_signature=True), LOAD(...,user_signature=True) can sign urls and @auth.requires_signature() will check the signature for any decorated action.
+
+- DAL(...,migrate_enabled=False) to disable all migrations
+- DAL(...,fake_migrate_all=True) to rebuild all corrupted metadata
+- new DAL metadata format (databases/*.table)
+- DAL(...,adapter_arg={}) allows support for alternate drivers
+- DAL now allows circular table defintions
+- DAL(..,auto_import=True) automatically imports tables from metadata without need to db.define_table(...)s.
+- new alterante syntax for inner joins: db(...).select(join=...)
+- experimental cubrid database support
+- DAL 'request_tenant' fields are special, the altomatically filer all records based on their default value.
+- db._common_fields.append(Field('owner')) allows to add fields to ALL tables
+- DAL ignores repeated fields with same names
+
+- web2py_ajax.html is more modular, thanks Anthony
+- request.is_local
+- request.is_http
+- new sessions2trash.py thanks Jim Karsten
+- corrupted cache files are automatically deleted
+- new simpler API gluon.contrib.AuthorizeNet.procss(...)
+- fixed recaptcha (as they released new API)
+- messages in validators have default internationalization
+- No more Auth(globals(),db), just Auth(db). Same for Crud and Service.
+- scripts/access.wsgi allows apache+mod_wsgi to delegate authentication of any URL to any web2py app
+- json now supports T(...)
+- scripts/setup-web2py-nginx-uwsgi-ubuntu.sh
+- web2py HTTP responses now set: "X-Powered-By: web2py", thanks Bruno
+- mostly fixed generic.pdf. You can view any page in PDF if you have pdflatex installed or if your html follows the pyfpdf convention.
+- auth.settings.extra_fields['auth_user'].append(Field('country')) allows to extend auth_* tables without need of definiting a custom auth_* table. Must be placed before auth.define_tables()
+- {{=response.toolbar()}} to help you debug applications
+- web based shell now supports object modifications (but no redefinitions of non-serializable types)
+- jQuery 1.6.1
+- Lots of bug fixes
+
+# 1.96.2-1.96.4
+- bug fixes
+
+# 1.97.1
+- validate_and_update, thanks Bruno
+- fixed problem with new custom import, thanks Mart
+- fixed pyamf 0.6, thanks Alexei and Nickd
+- fixed "+ =" bug in wizard
+- fixed problem with allowed_patterns
+- fixed problems with LOAD and vars and ajax
+- closed lots of google code tickets
+- checkboxes should now work with list:string
+- web2py works on Android, thanks Corne Dickens
+- new cpdb.py, thanks Mart
+- improved translation (frech in particuler), thanks Pierre
+- improved cas_auth.py, thanks Sergio
+- IS_DATE and IS_DATETIME validators now work with native types
+- better description of --shell, thanks Anthony
+- extra SQLTABLE columns, thanks Martin
+- fixed toolbar conflics, thanks Simon
+- GAE password shows with ****
+
+# 1.98.1-1.98.2
+- fixed some problems with LOAD(ajax=False), thanks Anthony
+- jquery 1.6.2
+- gevent.pywsgi adds ssl support, thanks Vasile
+- import/export of blobs are base64 encoded
+- max number of login attemts in admin, thanks Ross
+- fixed joins with alias tables
+- new field.custom_delete attribute
+- removed resctions on large 'text fields, thanks Martin
+- field.represent = lambda value,record: .... (record is optional)
+- FORM.validate() and FORM.process(), thanks Bruno
+- faster visrtualfields, thanks Howsec
+- mail has ssl support separate from tls, thanks Eric
+- TAG objects are now pickable
+- new CAT tag for no tags
+- request.user_agent(), thanks Ross
+- fixed fawps support
+- SQLFORM(...,separator=': ') now customizable
+- many small bug fixes
+
+## 1.99.1
+- gluon/contrib/simplejsonrpc.py
+- gluon/contrib/redis_cache.py
+- support for A(name,callback=url,target='id',delete='tr')
+- support for A(name,component=url,target='id',delete='tr')
+- new pip installer, thanks Chris Steel
+- isapiwsgihandler.py
+- dal expression.coalesce(*options)
+- gluon/contrib/simplejsonrpc.py, thanks Mariano
+- expire_sessions.py respects expiration time, thanks iceberg
+- addressed this issue: http://fuelyourcoding.com/jquery-events-stop-misusing-return-false/
+- x509 support (thanks Michele)
+- form.process() and for.validate()
+- rocket upgrade (1.2.4)
+- jQuery upgrade (1.6.3)
+- new syntax rows[i]('tablename.fieldname')
+- new query syntax field.contains(list,all=True or False)
+- new SQLFORM.grid and SQLFORM.smartgrid (should replace crud.search and crud.select)
+- support for natural language queries (english only) in SQLFORM.grid
+- support for computed columns and additional links in SQLFORM.grid
+- new style virtual fields (experimental): db.table.field=Field.Lazy(...)
+- request.utcnow
+- cleaner/simpler welcome/models/db.py and welcome layout.html
+- response.include_meta() and response.include_files(), thanks Denes
+- dal auto-reconnect on time-out connections
+- COL and COLGROUP helpers
+- addresed OWASP #10, thanks Anthony and Eric
+- auth.settings.login_after_registration=True
+- detection of mobile devices and @mobilize helper (view.mobile.html), thanks Angelo
+- experimental gluon/scheduler.py
+- scripts/make_min_web2py.py
+- crud.search has more options, thanks Denes
+- many bug fixes (thanks Jonathan, Michele, Fran and others)
3  TODO
@@ -0,0 +1,3 @@
+idea for scheduler
+http://panela.blog-city.com/how_to_timeout_in_python_with_multiprocessing.htm
+
1  VERSION
@@ -0,0 +1 @@
+Version 1.99.3 (2011-11-22 08:38:58) dev
3  __init__.py
@@ -0,0 +1,3 @@
+
+
+
300 anyserver.py
@@ -0,0 +1,300 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+This file is part of the web2py Web Framework
+Copyrighted by Massimo Di Pierro <mdipierro@cs.depaul.edu>
+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
+path = os.path.dirname(os.path.abspath(__file__))
+os.chdir(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):
+ from wsgiref.handlers import CGIHandler
+ CGIHandler().run(app) # Just ignore host and port here
+
+ @staticmethod
+ 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
+ from wsgiref.simple_server import make_server, WSGIRequestHandler
+ class QuietHandler(WSGIRequestHandler):
+ def log_request(*args, **kw): pass
+ options['handler_class'] = QuietHandler
+ srv = make_server(address[0],address[1],app,**options)
+ srv.serve_forever()
+
+ @staticmethod
+ def cherrypy(app,address, **options):
+ from cherrypy import wsgiserver
+ server = wsgiserver.CherryPyWSGIServer(address, app)
+ server.start()
+
+ @staticmethod
+ 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):
+ from gluon.rocket import CherryPyWSGIServer
+ from repoze.profile.profiler import AccumulatingProfileMiddleware
+ from gluon.settings import global_settings
+ global_settings.web2py_crontype = 'none'
+ wrapped = AccumulatingProfileMiddleware(
+ app,
+ log_filename='wsgi.prof',
+ discard_first_request=True,
+ flush_at_shutdown=True,
+ path = '/__profile__'
+ )
+ server = CherryPyWSGIServer(address, wrapped)
+ server.start()
+
+ @staticmethod
+ 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):
+ import fapws._evwsgi as evwsgi
+ from fapws import base
+ 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.run()
+
+
+ @staticmethod
+ 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()
+
+ @staticmethod
+ def bjoern(app,address, **options):
+ import bjoern
+ bjoern.run(app, *address)
+
+ @staticmethod
+ def tornado(app,address, **options):
+ import tornado.wsgi
+ import tornado.httpserver
+ import tornado.ioloop
+ container = tornado.wsgi.WSGIContainer(app)
+ server = tornado.httpserver.HTTPServer(container)
+ server.listen(address=address[0], port=address[1])
+ tornado.ioloop.IOLoop.instance().start()
+
+ @staticmethod
+ def twisted(app,address, **options):
+ from twisted.web import server, wsgi
+ from twisted.python.threadpool import ThreadPool
+ from twisted.internet import reactor
+ thread_pool = ThreadPool()
+ thread_pool.start()
+ reactor.addSystemEventTrigger('after', 'shutdown', thread_pool.stop)
+ factory = server.Site(wsgi.WSGIResource(reactor, thread_pool, app))
+ reactor.listenTCP(address[1], factory, interface=address[0])
+ reactor.run()
+
+ @staticmethod
+ def diesel(app,address, **options):
+ from diesel.protocols.wsgi import WSGIApplication
+ app = WSGIApplication(app, port=address[1])
+ app.run()
+
+ @staticmethod
+ def gnuicorn(app,address, **options):
+ import gunicorn.arbiter
+ gunicorn.arbiter.Arbiter(address, 4, app).run()
+
+ @staticmethod
+ def eventlet(app,address, **options):
+ from eventlet import wsgi, listen
+ wsgi.server(listen(address), app)
+
+ @staticmethod
+ 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)
+
+
+def run(servername,ip,port,softcron=True,logging=False,profiler=None):
+ if logging:
+ application = gluon.main.appfactory(wsgiapp=gluon.main.wsgibase,
+ logfilename='httpserver.log',
+ profilerfilename=profiler)
+ else:
+ application = gluon.main.wsgibase
+ if softcron:
+ from gluon.settings import global_settings
+ global_settings.web2py_crontype = 'soft'
+ getattr(Servers,servername)(application,(ip,int(port)))
+
+def mongrel2_handler(application,conn,debug=False):
+ """
+ Based on :
+ https://github.com/berry/Mongrel2-WSGI-Handler/blob/master/wsgi-handler.py
+
+ WSGI handler based on the Python wsgiref SimpleHandler.
+ A WSGI application should return a iterable op StringTypes.
+ Any encoding must be handled by the WSGI application itself.
+ """
+ from wsgiref.handlers import SimpleHandler
+ try:
+ import cStringIO as StringIO
+ except:
+ import StringIO
+
+ # TODO - this wsgi handler executes the application and renders a page
+ # in memory completely before returning it as a response to the client.
+ # Thus, it does not "stream" the result back to the client. It should be
+ # possible though. The SimpleHandler accepts file-like stream objects. So,
+ # it should be just a matter of connecting 0MQ requests/response streams to
+ # the SimpleHandler requests and response streams. However, the Python API
+ # for Mongrel2 doesn't seem to support file-like stream objects for requests
+ # and responses. Unless I have missed something.
+
+ while True:
+ if debug: print "WAITING FOR REQUEST"
+
+ # receive a request
+ req = conn.recv()
+ 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
+
+ # Set a couple of environment attributes a.k.a. header attributes
+ # that are a must according to PEP 333
+ environ = req.headers
+ environ['SERVER_PROTOCOL'] = 'HTTP/1.1' # SimpleHandler expects a server_protocol, lets assume it is HTTP 1.1
+ environ['REQUEST_METHOD'] = environ['METHOD']
+ if ':' in environ['Host']:
+ environ['SERVER_NAME'] = environ['Host'].split(':')[0]
+ environ['SERVER_PORT'] = environ['Host'].split(':')[1]
+ else:
+ environ['SERVER_NAME'] = environ['Host']
+ environ['SERVER_PORT'] = ''
+ environ['SCRIPT_NAME'] = '' # empty for now
+ environ['PATH_INFO'] = urllib.unquote(environ['PATH'])
+ if '?' in environ['URI']:
+ 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
+ environ['wsgi.input'] = req.body
+
+ if debug: print "ENVIRON: %r\n" % environ
+
+ # SimpleHandler needs file-like stream objects for
+ # requests, errors and responses
+ reqIO = StringIO.StringIO(req.body)
+ errIO = StringIO.StringIO()
+ respIO = StringIO.StringIO()
+
+ # execute the application
+ handler = SimpleHandler(reqIO, respIO, errIO, environ, multithread = False, multiprocess = False)
+ handler.run(application)
+
+ # Get the response and filter out the response (=data) itself,
+ # the response headers,
+ # the response status code and the response status description
+ response = respIO.getvalue()
+ response = response.split("\r\n")
+ data = response[-1]
+ headers = dict([r.split(": ") for r in response[1:-2]])
+ code = response[0][9:12]
+ status = response[0][13:]
+
+ # strip BOM's from response data
+ # Especially the WSGI handler from Django seems to generate them (2 actually, huh?)
+ # a BOM isn't really necessary and cause HTML parsing errors in Chrome and Safari
+ # See also: http://www.xs4all.nl/~mechiel/projects/bomstrip/
+ # Although I still find this a ugly hack, it does work.
+ data = data.replace('\xef\xbb\xbf', '')
+
+ # Get the generated errors
+ errors = errIO.getvalue()
+
+ # return the response
+ if debug: print "RESPONSE: %r\n" % response
+ if 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)
+
+def main():
+ usage = "python anyserver.py -s tornado -i 127.0.0.1 -p 8000 -l -P"
+ try:
+ version = read_file('VERSION')
+ except IOError:
+ version = ''
+ parser = optparse.OptionParser(usage, None, optparse.Option, version)
+ parser.add_option('-l',
+ '--logging',
+ action='store_true',
+ default=False,
+ dest='logging',
+ help='log into httpserver.log')
+ parser.add_option('-P',
+ '--profiler',
+ default=False,
+ dest='profiler',
+ help='profiler filename')
+ servers = ', '.join(x for x in dir(Servers) if not x[0]=='_')
+ parser.add_option('-s',
+ '--server',
+ default='rocket',
+ dest='server',
+ help='server name (%s)' % servers)
+ parser.add_option('-i',
+ '--ip',
+ default='127.0.0.1',
+ dest='ip',
+ help='ip address')
+ parser.add_option('-p',
+ '--port',
+ default='8000',
+ dest='port',
+ help='port number')
+ parser.add_option('-w',
+ '--workers',
+ default='',
+ 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)
+
+
+if __name__=='__main__':
+ main()
+
86 app.example.yaml
@@ -0,0 +1,86 @@
+# For Google App Engine deployment, copy this file to app.yaml
+# and edit as required
+# See http://code.google.com/appengine/docs/python/config/appconfig.html
+# and http://web2py.com/book/default/chapter/11?search=app.yaml
+
+application: web2py
+version: 1
+api_version: 1
+
+# use this line for Python 2.5
+#
+runtime: python
+
+# use these lines for Python 2.7
+# upload app with: appcfg.py update web2py (where 'web2py' is web2py's root directory)
+#
+# runtime: python27
+# threadsafe: true # true for WSGI & concurrent requests (Python 2.7 only)
+
+default_expiration: "24h" # for static files
+
+handlers:
+
+- url: /(?P<a>.+?)/static/(?P<b>.+)
+ static_files: applications/\1/static/\2
+ upload: applications/(.+?)/static/(.+)
+ secure: optional
+
+- url: /favicon.ico
+ static_files: applications/welcome/static/favicon.ico
+ upload: applications/welcome/static/favicon.ico
+
+- url: /robots.txt
+ static_files: applications/welcome/static/robots.txt
+ upload: applications/welcome/static/robots.txt
+
+- url: .*
+ script: gaehandler.py # CGI
+# script: gaehandler.wsgiapp # WSGI (Python 2.7 only)
+ secure: optional
+
+admin_console:
+ pages:
+ - name: Appstats
+ url: /_ah/stats
+
+skip_files: |
+ ^(.*/)?(
+ (app\.yaml)|
+ (app\.yml)|
+ (index\.yaml)|
+ (index\.yml)|
+ (#.*#)|
+ (.*~)|
+ (.*\.py[co])|
+ (.*/RCS/.*)|
+ (\..*)|
+ (applications/(admin|examples)/.*)|
+ ((admin|examples|welcome)\.(w2p|tar))|
+ (applications/.*?/(cron|databases|errors|cache|sessions)/.*)|
+ ((logs|scripts)/.*)|
+ (anyserver\.py)|
+ (web2py\.py)|
+ ((cgi|fcgi|modpython|wsgi)handler\.py)|
+ (epydoc\.(conf|css))|
+ (httpserver\.log)|
+ (logging\.example\.conf)|
+ (route[rs]\.example\.py)|
+ (setup_(app|exe)\.py)|
+ (splashlogo\.gif)|
+ (parameters_\d+\.py)|
+ (options_std.py)|
+ (gluon/tests/.*)|
+ (gluon/(rocket|winservice)\.py)|
+ (contrib/(gateways|markdown|memcache|pymysql)/.*)|
+ (contrib/(populate|taskbar_widget)\.py)|
+ (google_appengine/.*)|
+ (.*\.(bak|orig))|
+ )$
+
+builtins:
+- remote_api: on
+- datastore_admin: on
+- appstats: on
+- admin_redirect: on
+- deferred: on
5 appengine_config.py
@@ -0,0 +1,5 @@
+def webapp_add_wsgi_middleware(app):
+ from google.appengine.ext.appstats import recording
+ app = recording.appstats_wsgi_middleware(app)
+ return app
+
6 applications/admin/ABOUT
@@ -0,0 +1,6 @@
+web2py is an open source full-stack framework for agile development
+of secure database-driven web-based applications, written and programmable in
+Python.
+
+Created by Massimo Di Pierro <mdipierro@cs.depaul.edu>
+
137 applications/admin/LICENSE
@@ -0,0 +1,137 @@
+## Web2py License
+
+Web2py is Licensed under the LGPL license version 3
+(http://www.gnu.org/licenses/lgpl.html)
+
+Copyrighted (c) by Massimo Di Pierro (2007-2011)
+
+### On Commercial Redistribution
+
+In accordance with LGPL you may:
+- redistribute web2py with your apps (including official web2py binary versions)
+- release your applications which use official web2py libraries under any license you wish
+But you must:
+- make clear in the documentation that your application uses web2py
+- release any modification of the web2py libraries under the LGPLv3 license
+
+THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT
+HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE,
+BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
+DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
+OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
+PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+(Earlier versions of web2py, 1.0.*-1.90.*, were released under the GPL2 license plus a
+commercial exception which, for practical purposes, was very similar to the current LPGLv3)
+
+### Licenses for third party contributed software
+
+web2py contains third party software under the gluon/contrib/ folder.
+Each file/module in contrib is distributed with web2py under its original license.
+Here we list some of them.
+
+#### gluon.contrib.simplejson LICENSE
+
+Copyright (c) 2006 Bob Ippolito - Permission is hereby granted, free of charge,
+to any person obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish, distribute,
+sublicense, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+#### gluon.contrib.rss2.py (originally PyRSS2Gen) LICENSE
+
+This is copyright (c) by Dalke Scientific Software, LLC and released under the
+BSD license. See the file LICENSE in the distribution or
+<http://www.opensource.org/licenses/bsd-license.php> for details.
+
+#### gluon.contrib.markdown (markdown2) LICENSE
+
+MIT License from from <http://code.google.com/p/python-markdown2/>
+
+#### gluon.contrib.feedparser LICENSE
+
+Copyright (c) 2002-2005, Mark Pilgrim
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+#### gluon.wsgiserver.py LICENSE (borrowed from cherrypy)
+
+Copyright (c) 2004, CherryPy Team (team@cherrypy.org)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the CherryPy Team nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#### gluon.contrib.pam LICENSE
+
+Copyright (C) 2007-2009 Chris AtLee <chris@atlee.ca> Licensed under the MIT license
+
+#### gluon.contrib.shell LICENSE
+
+Copyright (C) by Google inc. Apache 2.0 Lincense
+
+#### The javascript licenses are in the code itself
+
0  applications/admin/__init__.py
No changes.
430 applications/admin/controllers/appadmin.py
@@ -0,0 +1,430 @@
+# -*- coding: utf-8 -*-
+
+# ##########################################################
+# ## make sure administrator is on localhost
+# ###########################################################
+
+import os
+import socket
+import datetime
+import copy
+import gluon.contenttype
+import gluon.fileutils
+
+# ## critical --- make a copy of the environment
+
+global_env = copy.copy(globals())
+global_env['datetime'] = datetime
+
+http_host = request.env.http_host.split(':')[0]
+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')
+except:
+ hosts = (http_host, )
+
+if request.env.http_x_forwarded_for or request.env.wsgi_url_scheme\
+ in ['https', 'HTTPS']:
+ session.secure()
+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)):
+ redirect(URL('admin', 'default', 'index',
+ vars=dict(send=URL(args=request.args,vars=request.vars))))
+
+ignore_rw = True
+response.view = 'appadmin.html'
+response.menu = [[T('design'), False, URL('admin', 'default', 'design',
+ args=[request.application])], [T('db'), False,
+ URL('index')], [T('state'), False,
+ URL('state')], [T('cache'), False,
+ URL('ccache')]]
+
+# ##########################################################
+# ## auxiliary functions
+# ###########################################################
+
+
+def get_databases(request):
+ dbs = {}
+ for (key, value) in global_env.items():
+ cond = False
+ try:
+ cond = isinstance(value, GQLDB)
+ except:
+ cond = isinstance(value, SQLDB)
+ if cond:
+ dbs[key] = value
+ return dbs
+
+
+databases = get_databases(None)
+
+
+def eval_in_global_env(text):
+ exec ('_ret=%s' % text, {}, global_env)
+ return global_env['_ret']
+
+
+def get_database(request):
+ if request.args and request.args[0] in databases:
+ return eval_in_global_env(request.args[0])
+ else:
+ session.flash = T('invalid request')
+ redirect(URL('index'))
+
+
+def get_table(request):
+ db = get_database(request)
+ if len(request.args) > 1 and request.args[1] in db.tables:
+ return (db, request.args[1])
+ else:
+ session.flash = T('invalid request')
+ redirect(URL('index'))
+
+
+def get_query(request):
+ try:
+ return eval_in_global_env(request.vars.query)
+ except Exception:
+ return None
+
+
+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)
+ else:
+ qry = '%s.%s.id>0' % tuple(request.args[:2])
+ return qry
+
+
+
+# ##########################################################
+# ## list all databases and tables
+# ###########################################################
+
+
+def index():
+ return dict(databases=databases)
+
+
+# ##########################################################
+# ## insert a new record
+# ###########################################################
+
+
+def insert():
+ (db, table) = get_table(request)
+ 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])
+
+
+# ##########################################################
+# ## list all records in table and insert new record
+# ###########################################################
+
+
+def download():
+ import os
+ db = get_database(request)
+ return response.download(request,db)
+
+def csv():
+ import gluon.contenttype
+ response.headers['Content-Type'] = \
+ gluon.contenttype.contenttype('.csv')
+ db = get_database(request)
+ query = get_query(request)
+ if not query:
+ return None
+ response.headers['Content-disposition'] = 'attachment; filename=%s_%s.csv'\
+ % tuple(request.vars.query.split('.')[:2])
+ return str(db(query).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'):
+ regex = re.compile('(?P<table>\w+)\.(?P<field>\w+)=(?P<value>.+)')
+ if request.vars.query:
+ match = regex.match(request.vars.query)
+ if match:
+ request.vars.query = '%s.%s.%s==%s' % (request.args[0],
+ match.group('table'), match.group('field'),
+ match.group('value'))
+ else:
+ request.vars.query = session.last_query
+ query = get_query(request)
+ if request.vars.start:
+ start = int(request.vars.start)
+ else:
+ start = 0
+ nrows = 0
+ stop = start + 100
+ table = None
+ rows = []
+ orderby = request.vars.orderby
+ if orderby:
+ orderby = dbname + '.' + orderby
+ if orderby == session.last_orderby:
+ if orderby[0] == '~':
+ orderby = orderby[1:]
+ else:
+ orderby = '~' + orderby
+ session.last_orderby = orderby
+ 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:'),
+ 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='submit'))),
+ _action=URL(r=request,args=request.args))
+ if request.vars.csvfile != None:
+ try:
+ import_csv(db[request.vars.table],
+ request.vars.csvfile.file)
+ response.flash = T('data uploaded')
+ except Exception, e:
+ response.flash = DIV(T('unable to parse csv file'),PRE(str(e)))
+ if form.accepts(request.vars, formname=None):
+# regex = re.compile(request.args[0] + '\.(?P<table>\w+)\.id\>0')
+ regex = re.compile(request.args[0] + '\.(?P<table>\w+)\..+')
+
+ match = regex.match(form.vars.query.strip())
+ if match:
+ table = match.group('table')
+ try:
+ nrows = db(query).count()
+ if form.vars.update_check and form.vars.update_fields:
+ db(query).update(**eval_in_global_env('dict(%s)'
+ % form.vars.update_fields))
+ response.flash = T('%s rows updated', nrows)
+ elif form.vars.delete_check:
+ db(query).delete()
+ response.flash = T('%s rows deleted', nrows)
+ nrows = db(query).count()
+ if orderby:
+ rows = db(query).select(limitby=(start, stop),
+ orderby=eval_in_global_env(orderby))
+ else:
+ rows = db(query).select(limitby=(start, stop))
+ except Exception, e:
+ (rows, nrows) = ([], 0)
+ response.flash = DIV(T('Invalid Query'),PRE(str(e)))
+ return dict(
+ form=form,
+ table=table,
+ start=start,
+ stop=stop,
+ nrows=nrows,
+ rows=rows,
+ query=request.vars.query,
+ )
+
+
+# ##########################################################
+# ## edit delete one record
+# ###########################################################
+
+
+def update():
+ (db, table) = get_table(request)
+ 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]]).select().first()
+ else:
+ record = db(db[table].id == request.args(2)).select().first()
+
+ if not record:
+ qry = query_by_table_type(table, db)
+ session.flash = T('record does not exist')
+ redirect(URL('select', args=request.args[:1],
+ vars=dict(query=qry)))
+
+ if keyed:
+ for k in db[table]._primarykey:
+ db[table][k].writable=False
+
+ 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,
+ f='download', args=request.args[:1]))
+
+ if form.accepts(request.vars, session):
+ session.flash = T('done!')
+ 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])
+
+
+# ##########################################################
+# ## get global variables
+# ###########################################################
+
+
+def state():
+ return dict()
+
+def ccache():
+ form = FORM(
+ P(TAG.BUTTON("Clear CACHE?", _type="submit", _name="yes", _value="yes")),
+ P(TAG.BUTTON("Clear RAM", _type="submit", _name="ram", _value="ram")),
+ P(TAG.BUTTON("Clear DISK", _type="submit", _name="disk", _value="disk")),
+ )
+
+ if form.accepts(request.vars, session):
+ clear_ram = False
+ clear_disk = False
+ session.flash = ""
+ if request.vars.yes:
+ clear_ram = clear_disk = True
+ if request.vars.ram:
+ clear_ram = True
+ if request.vars.disk:
+ clear_disk = True
+
+ if clear_ram:
+ cache.ram.clear()
+ session.flash += "Ram Cleared "
+ if clear_disk:
+ cache.disk.clear()
+ session.flash += "Disk Cleared"
+
+ redirect(URL(r=request))
+
+ try:
+ from guppy import hpy; hp=hpy()
+ except ImportError:
+ hp = False
+
+ import shelve, os, copy, time, math
+ from gluon import portalocker
+
+ ram = {
+ 'entries': 0,
+ 'bytes': 0,
+ 'objects': 0,
+ 'hits': 0,
+ 'misses': 0,
+ 'ratio': 0,
+ 'oldest': time.time(),
+ 'keys': []
+ }
+ disk = copy.copy(ram)
+ total = copy.copy(ram)
+ disk['keys'] = []
+ total['keys'] = []
+
+ def GetInHMS(seconds):
+ hours = math.floor(seconds / 3600)
+ seconds -= hours * 3600
+ minutes = math.floor(seconds / 60)
+ seconds -= minutes * 60
+ seconds = math.floor(seconds)
+
+