Merge branch 'master' of github.com:web2py/web2py
This commit is contained in:
commit
a7dddda495
13 files changed
+179
-85
No files matched your search
@@ -1 +1 @@
|
|||||||
Version 2.00.0 (2012-07-19 16:56:40) dev
|
Version 2.00.0 (2012-07-20 17:37:48) dev
|
||||||
@@ -392,7 +392,7 @@ def peek():
|
|||||||
app = get_app(request.vars.app)
|
app = get_app(request.vars.app)
|
||||||
filename = '/'.join(request.args)
|
filename = '/'.join(request.args)
|
||||||
if request.vars.app:
|
if request.vars.app:
|
||||||
path = abspath(filename, gluon=False)
|
path = abspath(filename)
|
||||||
else:
|
else:
|
||||||
path = apath(filename, r=request)
|
path = apath(filename, r=request)
|
||||||
try:
|
try:
|
||||||
@@ -696,7 +696,7 @@ def edit_language():
|
|||||||
s = strings[key]
|
s = strings[key]
|
||||||
(prefix, sep, key) = key.partition('\x01')
|
(prefix, sep, key) = key.partition('\x01')
|
||||||
if sep:
|
if sep:
|
||||||
prefix = SPAN(prefix+': ', _style='color: blue;')
|
prefix = SPAN(prefix+': ', _class='tm_ftag')
|
||||||
k = key
|
k = key
|
||||||
else:
|
else:
|
||||||
(k, prefix) = (prefix, '')
|
(k, prefix) = (prefix, '')
|
||||||
@@ -1034,7 +1034,7 @@ def create_file():
|
|||||||
anchor='#'+request.vars.id if request.vars.id else ''
|
anchor='#'+request.vars.id if request.vars.id else ''
|
||||||
if request.vars.app:
|
if request.vars.app:
|
||||||
app = get_app(request.vars.app)
|
app = get_app(request.vars.app)
|
||||||
path = abspath(request.vars.location, gluon=False)
|
path = abspath(request.vars.location)
|
||||||
else:
|
else:
|
||||||
app = get_app(name=request.vars.location.split('/')[0])
|
app = get_app(name=request.vars.location.split('/')[0])
|
||||||
path = apath(request.vars.location, r=request)
|
path = apath(request.vars.location, r=request)
|
||||||
|
|||||||
@@ -1248,3 +1248,4 @@ color: #222;
|
|||||||
.error, .error a {color:red}
|
.error, .error a {color:red}
|
||||||
.pluralsform thead td {font-weight:bold; font-size:1.2em; padding-bottom:5px}
|
.pluralsform thead td {font-weight:bold; font-size:1.2em; padding-bottom:5px}
|
||||||
.pluralsform td {padding-left:5px}
|
.pluralsform td {padding-left:5px}
|
||||||
|
.tm_ftag {color:blue}
|
||||||
@@ -13,6 +13,9 @@ def index():
|
|||||||
"""
|
"""
|
||||||
example action using the internationalization operator T and flash
|
example action using the internationalization operator T and flash
|
||||||
rendered by views/default/index.html or views/generic.html
|
rendered by views/default/index.html or views/generic.html
|
||||||
|
|
||||||
|
if you need a simple wiki simple replace the two lines below with:
|
||||||
|
return auth.wiki()
|
||||||
"""
|
"""
|
||||||
response.flash = T("Welcome to web2py!")
|
response.flash = T("Welcome to web2py!")
|
||||||
return dict(message=T('Hello World'))
|
return dict(message=T('Hello World'))
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ response.generic_patterns = ['*'] if request.is_local else []
|
|||||||
#########################################################################
|
#########################################################################
|
||||||
|
|
||||||
from gluon.tools import Auth, Crud, Service, PluginManager, prettydate
|
from gluon.tools import Auth, Crud, Service, PluginManager, prettydate
|
||||||
auth = Auth(db, hmac_key=Auth.get_or_create_key(), salt=True)
|
auth = Auth(db)
|
||||||
crud, service, plugins = Crud(db), Service(), PluginManager()
|
crud, service, plugins = Crud(db), Service(), PluginManager()
|
||||||
|
|
||||||
## create all tables needed by auth if not custom tables
|
## create all tables needed by auth if not custom tables
|
||||||
|
|||||||
@@ -1,17 +1,22 @@
|
|||||||
<html><body>
|
<!doctype html>
|
||||||
<style>
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
blockquote { background-color: lime; }
|
<head>
|
||||||
thead { color: white; background-color: gray; text-align: center; }
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||||
tfoot { color: white; background-color: gray; }
|
<style>
|
||||||
|
blockquote { background-color: lime; }
|
||||||
|
thead { color: white; background-color: gray; text-align: center; }
|
||||||
|
tfoot { color: white; background-color: gray; }
|
||||||
|
.tableclass1 { background-color: yellow; }
|
||||||
|
.tableclass1 thead { color: yellow; background-color: green; }
|
||||||
|
.tableclass1 tfoot { color: yellow; background-color: green; }
|
||||||
|
|
||||||
.tableclass1 { background-color: yellow; }
|
td.num { text-align: right; }
|
||||||
.tableclass1 thead { color: yellow; background-color: green; }
|
pre { background-color: #E0E0E0; }
|
||||||
.tableclass1 tfoot { color: yellow; background-color: green; }
|
</style>
|
||||||
|
<title>Markmin markup language</title>
|
||||||
td.num { text-align: right; }
|
</head>
|
||||||
pre { background-color: #E0E0E0; }
|
<body>
|
||||||
</style>
|
<h1>Markmin markup language</h1><h2>About</h2><p>This is a new markup language that we call markmin designed to produce high quality scientific papers and books and also put them online. We provide serializers for html, latex and pdf. It is implemented in the <code>markmin2html</code> function in the <code>markmin2html.py</code>.</p><p>Example of usage:</p><pre><code>m = "Hello **world** [[link http://web2py.com]]"
|
||||||
<h1>Markmin markup language</h1><h2>About</h2><p>This is a new markup language that we call markmin designed to produce high quality scientific papers and books and also put them online. We provide serializers for html, latex and pdf. It is implemented in the <code>markmin2html</code> function in the <code>markmin2html.py</code>.</p><p>Example of usage:</p><pre><code>m = "Hello **world** [[link http://web2py.com]]"
|
|
||||||
from markmin2html import markmin2html
|
from markmin2html import markmin2html
|
||||||
print markmin2html(m)
|
print markmin2html(m)
|
||||||
from markmin2latex import markmin2latex
|
from markmin2latex import markmin2latex
|
||||||
@@ -24,7 +29,7 @@ line 2
|
|||||||
line 3</code></pre> This item finishes with this paragraph.</li></ol><p>Item in sublevel 3 can be continued with paragraphs.</p><pre><code> this is another
|
line 3</code></pre> This item finishes with this paragraph.</li></ol><p>Item in sublevel 3 can be continued with paragraphs.</p><pre><code> this is another
|
||||||
code block
|
code block
|
||||||
in the
|
in the
|
||||||
sublevel 3 item</code></pre></li></ul><ol><li>The last item in sublevel 3</li></ol><p>This is a continuous paragraph for item 2 in sublevel 2. You can use such structure to create difficult structured documents.</p><li>item 3 in sublevel 2</li></li></li></ol><ul><li>item 1 in sublevel 2 (new unordered list)</li><li>item 2 in sublevel 2</li><li>item 3 in sublevel 2</li></ul><ol><li>item 1 in sublevel 2 (new ordered list)</li><li>item 2 in sublevel 2</li><li>item 3 in sublevle 2</li></ol></li><li>item 2 in level 1</li><li>item 3 in level 1</li></ol><ul><li>new unordered list (item 1 in level 1)</li><li>level 2 in level 1</li><li>level 3 in level 1</li><li>level 4 in level 1</li></ul><h2>This is the last section of the test</h2><p>Single paragraph with '----' in it will be turned into separator:</p><hr /><p>And this is the last paragraph in the test. Be happy!</p><p>====================</p><h2>Why?</h2><p>We wanted a markup language with the following requirements:</p><ul><li>less than 300 lines of functional code</li><li>easy to read</li><li>secure</li><li>support table, ul, ol, code</li><li>support html5 video and audio elements (html serialization only)</li><li>can align images and resize them</li><li>can specify class for tables and code elements</li><li>can add anchors</li><li>does not use _ for markup (since it creates odd behavior)</li><li>automatically links urls</li><li>fast</li><li>easy to extend</li><li>supports latex and pdf including references</li><li>allows to describe the markup in the markup (this document is generated from markmin syntax)</li></ul><p>(results depend on text but in average for text ~100K markmin is 30% faster than markdown, for text ~10K it is 10x faster)</p><p>The <a href="http://www.lulu.com/product/paperback/web2py-%283rd-edition%29/12822827">web2py book</a> published by lulu, for example, was entirely generated with markmin2pdf from the online <a href="http://www.web2py.com/book">web2py wiki</a></p><h2>Download</h2><ul><li><a href="http://web2py.googlecode.com/hg/gluon/contrib/markmin/markmin2html.py">http://web2py.googlecode.com/hg/gluon/contrib/markmin/markmin2html.py</a></li><li><a href="http://web2py.googlecode.com/hg/gluon/contrib/markmin/markmin2latex.py">http://web2py.googlecode.com/hg/gluon/contrib/markmin/markmin2latex.py</a></li><li><a href="http://web2py.googlecode.com/hg/gluon/contrib/markmin/markmin2pdf.py">http://web2py.googlecode.com/hg/gluon/contrib/markmin/markmin2pdf.py</a></li></ul><p>markmin2html.py and markmin2latex.py are single files and have no web2py dependence. Their license is BSD.</p><h2>Examples</h2><h3>Bold, italic, code and links</h3><table><thead><tr><td><strong>SOURCE</strong></td><td><strong>OUTPUT</strong></td></tr></thead><tbody><tr><td><code># title</code></td><td><strong>title</strong></td></tr><tr><td><code>## section</code></td><td><strong>section</strong></td></tr><tr><td><code>### subsection</code></td><td><strong>subsection</strong></td></tr><tr><td><code>**bold**</code></td><td><strong>bold</strong></td></tr><tr><td><code>''italic''</code></td><td><em>italic</em></td></tr><tr><td><code>~~strikeout~~</code></td><td><del>strikeout</del></td></tr><tr><td><code>``verbatim``</code></td><td><code>verbatim</code></td></tr><tr><td><code>``color with **bold**``:red</code></td><td><span style="color: red">color with <strong>bold</strong></span></td></tr><tr><td><code>``many colors``:color[blue:#ffff00]</code></td><td><span style="color: blue;background-color: #ffff00;">many colors</span></td></tr><tr><td><code>http://google.com</code></td><td><a href="http://google.com">http://google.com</a></td></tr><tr><td><code>[[**click** me #myanchor]]</code></td><td><a href="#myanchor"><strong>click</strong> me</a></td></tr><tr><td><code>[[click me [extra info] #myanchor popup]]</code></td><td><a href="#myanchor" title="extra info" target="_blank">click me</a></td></tr></tbody></table><h3>More on links</h3><p>The format is always <code>[[title link]]</code> or <code>[[title [extra] link]]</code>. Notice you can nest bold, italic, strikeout and code inside the link <code>title</code>.</p><h3>Anchors <span id="myanchor"></span></h3><p>You can place an anchor anywhere in the text using the syntax <code>[[name]]</code> where <em>name</em> is the name of the anchor. You can then link the anchor with <a href="#myanchor">link</a>, i.e. <code>[[link #myanchor]]</code> or <a href="#myanchor" title="extra info">link with an extra info</a>, i.e. <code>[[link with an extra info [extra info] #myanchor]]</code>.</p><h3>Images</h3><p><img src="http://www.web2py.com/examples/static/web2py_logo.png" alt="alt-string for the image" title="the image title" style="float:right" width="200px" /> This paragraph has an image aligned to the right with a width of 200px. Its is placed using the code</p><p><code>[[alt-string for the image [the image title] http://www.web2py.com/examples/static/web2py_logo.png right 200px]]</code>.</p><h3>Unordered Lists</h3><pre><code>- Dog
|
sublevel 3 item</code></pre></li></ul><ol><li>The last item in sublevel 3</li></ol><p>This is a continuous paragraph for item 2 in sublevel 2. You can use such structure to create difficult structured documents.</p><li>item 3 in sublevel 2</li></li></li></ol><ul><li>item 1 in sublevel 2 (new unordered list)</li><li>item 2 in sublevel 2</li><li>item 3 in sublevel 2</li></ul><ol><li>item 1 in sublevel 2 (new ordered list)</li><li>item 2 in sublevel 2</li><li>item 3 in sublevle 2</li></ol></li><li>item 2 in level 1</li><li>item 3 in level 1</li></ol><ul><li>new unordered list (item 1 in level 1)</li><li>level 2 in level 1</li><li>level 3 in level 1</li><li>level 4 in level 1</li></ul><h2>This is the last section of the test</h2><p>Single paragraph with '----' in it will be turned into separator:</p><hr /><p>And this is the last paragraph in the test. Be happy!</p><p>====================</p><h2>Why?</h2><p>We wanted a markup language with the following requirements:</p><ul><li>less than 300 lines of functional code</li><li>easy to read</li><li>secure</li><li>support table, ul, ol, code</li><li>support html5 video and audio elements (html serialization only)</li><li>can align images and resize them</li><li>can specify class for tables and code elements</li><li>can add anchors</li><li>does not use _ for markup (since it creates odd behavior)</li><li>automatically links urls</li><li>fast</li><li>easy to extend</li><li>supports latex and pdf including references</li><li>allows to describe the markup in the markup (this document is generated from markmin syntax)</li></ul><p>(results depend on text but in average for text ~100K markmin is 30% faster than markdown, for text ~10K it is 10x faster)</p><p>The <a href="http://www.lulu.com/product/paperback/web2py-%283rd-edition%29/12822827">web2py book</a> published by lulu, for example, was entirely generated with markmin2pdf from the online <a href="http://www.web2py.com/book">web2py wiki</a></p><h2>Download</h2><ul><li><a href="http://web2py.googlecode.com/hg/gluon/contrib/markmin/markmin2html.py">http://web2py.googlecode.com/hg/gluon/contrib/markmin/markmin2html.py</a></li><li><a href="http://web2py.googlecode.com/hg/gluon/contrib/markmin/markmin2latex.py">http://web2py.googlecode.com/hg/gluon/contrib/markmin/markmin2latex.py</a></li><li><a href="http://web2py.googlecode.com/hg/gluon/contrib/markmin/markmin2pdf.py">http://web2py.googlecode.com/hg/gluon/contrib/markmin/markmin2pdf.py</a></li></ul><p>markmin2html.py and markmin2latex.py are single files and have no web2py dependence. Their license is BSD.</p><h2>Examples</h2><h3>Bold, italic, code and links</h3><table><thead><tr><td><strong>SOURCE</strong></td><td><strong>OUTPUT</strong></td></tr></thead><tbody><tr><td><code># title</code></td><td><strong>title</strong></td></tr><tr><td><code>## section</code></td><td><strong>section</strong></td></tr><tr><td><code>### subsection</code></td><td><strong>subsection</strong></td></tr><tr><td><code>**bold**</code></td><td><strong>bold</strong></td></tr><tr><td><code>''italic''</code></td><td><em>italic</em></td></tr><tr><td><code>~~strikeout~~</code></td><td><del>strikeout</del></td></tr><tr><td><code>``verbatim``</code></td><td><code>verbatim</code></td></tr><tr><td><code>``color with **bold**``:red</code></td><td><span style="color: red">color with <strong>bold</strong></span></td></tr><tr><td><code>``many colors``:color[blue:#ffff00]</code></td><td><span style="color: blue;background-color: #ffff00;">many colors</span></td></tr><tr><td><code>http://google.com</code></td><td><a href="http://google.com">http://google.com</a></td></tr><tr><td><code>[[**click** me #myanchor]]</code></td><td><a href="#markmin_myanchor"><strong>click</strong> me</a></td></tr><tr><td><code>[[click me [extra info] #myanchor popup]]</code></td><td><a href="#markmin_myanchor" title="extra info" target="_blank">click me</a></td></tr></tbody></table><h3>More on links</h3><p>The format is always <code>[[title link]]</code> or <code>[[title [extra] link]]</code>. Notice you can nest bold, italic, strikeout and code inside the link <code>title</code>.</p><h3>Anchors <a name="markmin_myanchor"></a></h3><p>You can place an anchor anywhere in the text using the syntax <code>[[name]]</code> where <em>name</em> is the name of the anchor. You can then link the anchor with <a href="#markmin_myanchor">link</a>, i.e. <code>[[link #myanchor]]</code> or <a href="#markmin_myanchor" title="extra info">link with an extra info</a>, i.e. <code>[[link with an extra info [extra info] #myanchor]]</code>.</p><h3>Images</h3><p><img src="http://www.web2py.com/examples/static/web2py_logo.png" alt="alt-string for the image" title="the image title" style="float:right" width="200px" /> This paragraph has an image aligned to the right with a width of 200px. Its is placed using the code</p><p><code>[[alt-string for the image [the image title] http://www.web2py.com/examples/static/web2py_logo.png right 200px]]</code>.</p><h3>UnLine truncated
|
||||||
- Cat
|
- Cat
|
||||||
- Mouse</code></pre><p>is rendered as</p><ul><li>Dog</li><li>Cat</li><li>Mouse</li></ul><p>Two new lines between items break the list in two lists.</p><h3>Ordered Lists</h3><pre><code>+ Dog
|
- Mouse</code></pre><p>is rendered as</p><ul><li>Dog</li><li>Cat</li><li>Mouse</li></ul><p>Two new lines between items break the list in two lists.</p><h3>Ordered Lists</h3><pre><code>+ Dog
|
||||||
+ Cat
|
+ Cat
|
||||||
@@ -79,4 +84,6 @@ markmin2html(text,{'latex':lambda code: LATEX % code.replace('"','\"')})</code><
|
|||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
- [[mdipierro]] web2py Manual, 3rd Edition, lulu.com</code></pre><h3>Caveats</h3><p><code><ul/></code>, <code><ol/></code>, <code><code/></code>, <code><table/></code>, <code><blockquote/></code>, <code><h1/></code>, ..., <code><h6/></code> do not have <code><p>...</p></code> around them.</p></body></html>
|
- [[mdipierro]] web2py Manual, 3rd Edition, lulu.com</code></pre><h3>Caveats</h3><p><code><ul/></code>, <code><ol/></code>, <code><code/></code>, <code><table/></code>, <code><blockquote/></code>, <code><h1/></code>, ..., <code><h6/></code> do not have <code><p>...</p></code> around them.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -667,19 +667,19 @@ def render(text,extra={},allowed={},sep='p',URL=None,environment=None,latex='goo
|
|||||||
'<p>[[probe]]</p>'
|
'<p>[[probe]]</p>'
|
||||||
|
|
||||||
>>> render(r"\\\\[[probe]]")
|
>>> render(r"\\\\[[probe]]")
|
||||||
'<p>\\\\<span id="probe"></span></p>'
|
'<p>\\\\<a name="markmin_probe"></a></p>'
|
||||||
|
|
||||||
>>> render(r"\\\\\\[[probe]]")
|
>>> render(r"\\\\\\[[probe]]")
|
||||||
'<p>\\\\[[probe]]</p>'
|
'<p>\\\\[[probe]]</p>'
|
||||||
|
|
||||||
>>> render(r"\\\\\\\\[[probe]]")
|
>>> render(r"\\\\\\\\[[probe]]")
|
||||||
'<p>\\\\\\\\<span id="probe"></span></p>'
|
'<p>\\\\\\\\<a name="markmin_probe"></a></p>'
|
||||||
|
|
||||||
>>> render(r"\\\\\\\\\[[probe]]")
|
>>> render(r"\\\\\\\\\[[probe]]")
|
||||||
'<p>\\\\\\\\[[probe]]</p>'
|
'<p>\\\\\\\\[[probe]]</p>'
|
||||||
|
|
||||||
>>> render(r"\\\\\\\\\\\[[probe]]")
|
>>> render(r"\\\\\\\\\\\[[probe]]")
|
||||||
'<p>\\\\\\\\\\\\<span id="probe"></span></p>'
|
'<p>\\\\\\\\\\\\<a name="markmin_probe"></a></p>'
|
||||||
|
|
||||||
>>> render("``[[ [\\[[probe\]\\]] URL\\[x\\]]]``:red[dummy_params]")
|
>>> render("``[[ [\\[[probe\]\\]] URL\\[x\\]]]``:red[dummy_params]")
|
||||||
'<span style="color: red"><a href="URL[x]" title="[[probe]]">URL[x]</a></span>'
|
'<span style="color: red"><a href="URL[x]" title="[[probe]]">URL[x]</a></span>'
|
||||||
@@ -725,6 +725,10 @@ def render(text,extra={},allowed={},sep='p',URL=None,environment=None,latex='goo
|
|||||||
|
|
||||||
>>> render("**@{probe}**", environment=dict(probe="this is a test"))
|
>>> render("**@{probe}**", environment=dict(probe="this is a test"))
|
||||||
'<p><strong>this is a test</strong></p>'
|
'<p><strong>this is a test</strong></p>'
|
||||||
|
|
||||||
|
>>> render('[[id1 [span **messag** in ''markmin''] ]] ... [[**link** to id [link\\\'s title] #mark1]]')
|
||||||
|
'<p><a name="markmin_id1">span <strong>messag</strong> in markmin</a> ... <a href="#markmin_mark1" title="link\\\'s title"><strong>link</strong> to id</a></p>'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
text = str(text or '')
|
text = str(text or '')
|
||||||
text = regex_backslash.sub(lambda m: m.group(1).translate(ttab_in), text)
|
text = regex_backslash.sub(lambda m: m.group(1).translate(ttab_in), text)
|
||||||
@@ -855,7 +859,7 @@ def render(text,extra={},allowed={},sep='p',URL=None,environment=None,latex='goo
|
|||||||
""" paragraphs in lists """
|
""" paragraphs in lists """
|
||||||
lent=len(t)
|
lent=len(t)
|
||||||
if lent>lev:
|
if lent>lev:
|
||||||
return parse_list(t, '.', s, 'ul', lev, mtag)
|
return parse_list(t, '.', s, 'ul', lev, mtag, lineno)
|
||||||
elif lent<lev:
|
elif lent<lev:
|
||||||
while ltags[-1]>lent:
|
while ltags[-1]>lent:
|
||||||
ltags.pop()
|
ltags.pop()
|
||||||
@@ -986,7 +990,9 @@ def render(text,extra={},allowed={},sep='p',URL=None,environment=None,latex='goo
|
|||||||
URL,
|
URL,
|
||||||
environment,
|
environment,
|
||||||
latex,
|
latex,
|
||||||
auto)
|
auto,
|
||||||
|
class_prefix,
|
||||||
|
id_prefix)
|
||||||
)
|
)
|
||||||
mtag='q'
|
mtag='q'
|
||||||
else:
|
else:
|
||||||
@@ -1100,7 +1106,8 @@ def render(text,extra={},allowed={},sep='p',URL=None,environment=None,latex='goo
|
|||||||
elif p in ('left','right'):
|
elif p in ('left','right'):
|
||||||
style = ' style="float:%s"' % p
|
style = ' style="float:%s"' % p
|
||||||
if p in ('video','audio'):
|
if p in ('video','audio'):
|
||||||
t = render(t, {}, {}, 'br', URL, environment, latex, auto)
|
t = render(t, {}, {}, 'br', URL, environment, latex,
|
||||||
|
auto, class_prefix, id_prefix)
|
||||||
return '<%(p)s controls="controls"%(title)s%(width)s><source src="%(k)s" />%(t)s</%(p)s>' \
|
return '<%(p)s controls="controls"%(title)s%(width)s><source src="%(k)s" />%(t)s</%(p)s>' \
|
||||||
% dict(p=p, title=title, width=width, k=k, t=t)
|
% dict(p=p, title=title, width=width, k=k, t=t)
|
||||||
alt = ' alt="%s"'%escape(t).replace(META, DISABLED_META) if t else ''
|
alt = ' alt="%s"'%escape(t).replace(META, DISABLED_META) if t else ''
|
||||||
@@ -1115,13 +1122,19 @@ def render(text,extra={},allowed={},sep='p',URL=None,environment=None,latex='goo
|
|||||||
t = t or ''
|
t = t or ''
|
||||||
a = escape(a) if a else ''
|
a = escape(a) if a else ''
|
||||||
if k:
|
if k:
|
||||||
|
if k.startswith('#'):
|
||||||
|
k = '#'+id_prefix+k[1:]
|
||||||
k = escape(k)
|
k = escape(k)
|
||||||
title = ' title="%s"' % a.replace(META, DISABLED_META) if a else ''
|
title = ' title="%s"' % a.replace(META, DISABLED_META) if a else ''
|
||||||
target = ' target="_blank"' if p == 'popup' else ''
|
target = ' target="_blank"' if p == 'popup' else ''
|
||||||
t = render(t, {}, {}, 'br', URL, environment, latex, auto) if t else k
|
t = render(t, {}, {}, 'br', URL, environment, latex, auto,
|
||||||
|
class_prefix, id_prefix) if t else k
|
||||||
return '<a href="%(k)s"%(title)s%(target)s>%(t)s</a>' \
|
return '<a href="%(k)s"%(title)s%(target)s>%(t)s</a>' \
|
||||||
% dict(k=k, title=title, target=target, t=t)
|
% dict(k=k, title=title, target=target, t=t)
|
||||||
return '<span id="%s">%s</span>' % (escape(t),a)
|
return '<a name="%s">%s</a>' % (escape(id_prefix+t),
|
||||||
|
render(a, {},{},'br', URL,
|
||||||
|
environment, latex, auto,
|
||||||
|
class_prefix, id_prefix))
|
||||||
|
|
||||||
parts = text.split(LINK)
|
parts = text.split(LINK)
|
||||||
text = parts[0]
|
text = parts[0]
|
||||||
@@ -1183,21 +1196,36 @@ def markmin2html(text, extra={}, allowed={}, sep='p', auto=True):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
import doctest
|
import doctest
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
|
html=dedent("""
|
||||||
|
<!doctype html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||||
|
%(style)s
|
||||||
|
<title>%(title)s</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
%(body)s
|
||||||
|
</body>
|
||||||
|
</html>""")[1:]
|
||||||
|
|
||||||
if sys.argv[1:2] == ['-h']:
|
if sys.argv[1:2] == ['-h']:
|
||||||
print """<html><body>
|
style=dedent("""
|
||||||
<style>
|
<style>
|
||||||
blockquote { background-color: lime; }
|
blockquote { background-color: lime; }
|
||||||
thead { color: white; background-color: gray; text-align: center; }
|
thead { color: white; background-color: gray; text-align: center; }
|
||||||
tfoot { color: white; background-color: gray; }
|
tfoot { color: white; background-color: gray; }
|
||||||
|
.tableclass1 { background-color: yellow; }
|
||||||
|
.tableclass1 thead { color: yellow; background-color: green; }
|
||||||
|
.tableclass1 tfoot { color: yellow; background-color: green; }
|
||||||
|
|
||||||
.tableclass1 { background-color: yellow; }
|
td.num { text-align: right; }
|
||||||
.tableclass1 thead { color: yellow; background-color: green; }
|
pre { background-color: #E0E0E0; }
|
||||||
.tableclass1 tfoot { color: yellow; background-color: green; }
|
</style>""")[1:]
|
||||||
|
|
||||||
td.num { text-align: right; }
|
print html % dict(title="Markmin markup language", style=style, body=markmin2html(__doc__))
|
||||||
pre { background-color: #E0E0E0; }
|
|
||||||
</style>
|
|
||||||
"""+markmin2html(__doc__)+'</body></html>'
|
|
||||||
elif sys.argv[1:2] == ['-t']:
|
elif sys.argv[1:2] == ['-t']:
|
||||||
from timeit import Timer
|
from timeit import Timer
|
||||||
loops=1000
|
loops=1000
|
||||||
@@ -1208,7 +1236,7 @@ if __name__ == '__main__':
|
|||||||
elif len(sys.argv) > 1:
|
elif len(sys.argv) > 1:
|
||||||
fargv = open(sys.argv[1],'r')
|
fargv = open(sys.argv[1],'r')
|
||||||
try:
|
try:
|
||||||
print '<html><body>'+markmin2html(fargv.read())+'</body></html>'
|
print html % dict(title=sys.argv[1], style='', body=markmin2html(fargv.read()))
|
||||||
finally:
|
finally:
|
||||||
fargv.close()
|
fargv.close()
|
||||||
else:
|
else:
|
||||||
|
|||||||
+5
-1
@@ -1800,6 +1800,7 @@ class BaseAdapter(ConnectionPool):
|
|||||||
query = query & newquery
|
query = query & newquery
|
||||||
return query
|
return query
|
||||||
|
|
||||||
|
|
||||||
###################################################################################
|
###################################################################################
|
||||||
# List of all the available adapters; they all extend BaseAdapter.
|
# List of all the available adapters; they all extend BaseAdapter.
|
||||||
###################################################################################
|
###################################################################################
|
||||||
@@ -8593,7 +8594,10 @@ class Rows(object):
|
|||||||
"""
|
"""
|
||||||
returns a list of sorted elements (not sorted in place)
|
returns a list of sorted elements (not sorted in place)
|
||||||
"""
|
"""
|
||||||
return Rows(self.db,sorted(self,key=f,reverse=reverse),self.colnames)
|
rows = Rows(self.db,[],self.colnames,compact=False)
|
||||||
|
rows.records = sorted(self,key=f,reverse=reverse)
|
||||||
|
return rows
|
||||||
|
|
||||||
|
|
||||||
def group_by_value(self, field):
|
def group_by_value(self, field):
|
||||||
"""
|
"""
|
||||||
|
|||||||
+4
-4
@@ -880,7 +880,7 @@ class Auth(object):
|
|||||||
def here(self):
|
def here(self):
|
||||||
return URL(args=current.request.args,vars=current.request.vars)
|
return URL(args=current.request.args,vars=current.request.vars)
|
||||||
|
|
||||||
def __init__(self, environment=None, db=None, mailer=True, salt = False,
|
def __init__(self, environment=None, db=None, mailer=True,
|
||||||
hmac_key=None, controller='default', function='user', cas_provider=None):
|
hmac_key=None, controller='default', function='user', cas_provider=None):
|
||||||
"""
|
"""
|
||||||
auth=Auth(db)
|
auth=Auth(db)
|
||||||
@@ -922,7 +922,6 @@ class Auth(object):
|
|||||||
|
|
||||||
settings.hideerror = False
|
settings.hideerror = False
|
||||||
settings.password_min_length = 4
|
settings.password_min_length = 4
|
||||||
settings.salt = salt
|
|
||||||
settings.cas_domains = [request.env.http_host]
|
settings.cas_domains = [request.env.http_host]
|
||||||
settings.cas_provider = cas_provider
|
settings.cas_provider = cas_provider
|
||||||
settings.cas_actions = {'login':'login',
|
settings.cas_actions = {'login':'login',
|
||||||
@@ -1198,7 +1197,8 @@ class Auth(object):
|
|||||||
if URL() == action:
|
if URL() == action:
|
||||||
next = ''
|
next = ''
|
||||||
else:
|
else:
|
||||||
next = '?_next=' + urllib.quote(URL(args=request.args, vars=request.get_vars))
|
next = '?_next=' + urllib.quote(URL(args=request.args,
|
||||||
|
vars=request.get_vars))
|
||||||
|
|
||||||
href = lambda function: '%s/%s%s' % (action, function,
|
href = lambda function: '%s/%s%s' % (action, function,
|
||||||
next if referrer_actions is DEFAULT or function in referrer_actions else '')
|
next if referrer_actions is DEFAULT or function in referrer_actions else '')
|
||||||
@@ -1409,7 +1409,7 @@ class Auth(object):
|
|||||||
table.last_name.requires = \
|
table.last_name.requires = \
|
||||||
IS_NOT_EMPTY(error_message=self.messages.is_empty)
|
IS_NOT_EMPTY(error_message=self.messages.is_empty)
|
||||||
table[passfield].requires = [
|
table[passfield].requires = [
|
||||||
CRYPT(key=settings.hmac_key,salt=settings.salt,
|
CRYPT(key=settings.hmac_key,
|
||||||
min_length=settings.password_min_length)]
|
min_length=settings.password_min_length)]
|
||||||
table.email.requires = \
|
table.email.requires = \
|
||||||
[IS_EMAIL(error_message=self.messages.invalid_email),
|
[IS_EMAIL(error_message=self.messages.invalid_email),
|
||||||
|
|||||||
+24
-23
@@ -15,7 +15,7 @@ import __builtin__
|
|||||||
__all__ = ['Utf8']
|
__all__ = ['Utf8']
|
||||||
|
|
||||||
repr_escape_tab={}
|
repr_escape_tab={}
|
||||||
for i in xrange(1,32): repr_escape_tab[i]=ur'\x%02i'%i
|
for i in range(1,32): repr_escape_tab[i]=ur'\x%02x'%i
|
||||||
repr_escape_tab[7]=u'\\a'
|
repr_escape_tab[7]=u'\\a'
|
||||||
repr_escape_tab[8]=u'\\b'
|
repr_escape_tab[8]=u'\\b'
|
||||||
repr_escape_tab[9]=u'\\t'
|
repr_escape_tab[9]=u'\\t'
|
||||||
@@ -71,6 +71,24 @@ def size(string):
|
|||||||
"""
|
"""
|
||||||
return Utf8(string).__size__()
|
return Utf8(string).__size__()
|
||||||
|
|
||||||
|
def truncate(string, length, dots='...'):
|
||||||
|
""" returns string of length < *length* or truncate
|
||||||
|
string with adding *dots* suffix to the string's end
|
||||||
|
|
||||||
|
args:
|
||||||
|
length (int): max length of string
|
||||||
|
dots (str or unicode): string suffix, when string is cutted
|
||||||
|
|
||||||
|
returns:
|
||||||
|
(utf8-str): original or cutted string
|
||||||
|
"""
|
||||||
|
text = unicode(string, 'utf-8')
|
||||||
|
dots = unicode(dots, 'utf-8') if isinstance(dots, str) else dots
|
||||||
|
if len(text) > length:
|
||||||
|
text = text[:length-len(dots)] + dots
|
||||||
|
return str.__new__(Utf8, text.encode('utf-8'))
|
||||||
|
|
||||||
|
|
||||||
class Utf8(str):
|
class Utf8(str):
|
||||||
"""
|
"""
|
||||||
Class for utf8 string storing and manipulations
|
Class for utf8 string storing and manipulations
|
||||||
@@ -131,23 +149,6 @@ class Utf8(str):
|
|||||||
else:
|
else:
|
||||||
return "'"+unicode(self, 'utf-8').translate(repr_escape_tab2).encode('utf-8')+"'"
|
return "'"+unicode(self, 'utf-8').translate(repr_escape_tab2).encode('utf-8')+"'"
|
||||||
|
|
||||||
def truncate(self, length, dots='...'):
|
|
||||||
""" returns string of length < *length* or truncate
|
|
||||||
string with adding *dots* suffix to the string's end
|
|
||||||
|
|
||||||
args:
|
|
||||||
length (int): max length of string
|
|
||||||
dots (str or unicode): string suffix, when string is cutted
|
|
||||||
|
|
||||||
returns:
|
|
||||||
(utf8-str): original or cutted string
|
|
||||||
"""
|
|
||||||
text = unicode(self, 'utf-8')
|
|
||||||
dots = unicode(dots, 'utf-8') if isinstance(dots, str) else dots
|
|
||||||
if len(text) > length:
|
|
||||||
text = text[:length-len(dots)] + dots
|
|
||||||
return str.__new__(Utf8, text.encode('utf-8'))
|
|
||||||
|
|
||||||
def __size__(self):
|
def __size__(self):
|
||||||
""" length of utf-8 string in bytes """
|
""" length of utf-8 string in bytes """
|
||||||
return str.__len__(self)
|
return str.__len__(self)
|
||||||
@@ -419,15 +420,15 @@ if __name__ == '__main__':
|
|||||||
'прОБА є prOBE'
|
'прОБА є prOBE'
|
||||||
>>> type(s.swapcase())
|
>>> type(s.swapcase())
|
||||||
<class '__main__.Utf8'>
|
<class '__main__.Utf8'>
|
||||||
>>> s.truncate(10)
|
>>> truncate(s, 10)
|
||||||
'ПРоба Є...'
|
'ПРоба Є...'
|
||||||
>>> s.truncate(20)
|
>>> truncate(s, 20)
|
||||||
'ПРоба Є PRobe'
|
'ПРоба Є PRobe'
|
||||||
>>> s.truncate(10, '•••') # utf-8 string as *dots*
|
>>> truncate(s, 10, '•••') # utf-8 string as *dots*
|
||||||
'ПРоба Є•••'
|
'ПРоба Є•••'
|
||||||
>>> s.truncate(10, u'®') # you can use unicode string as *dots*
|
>>> truncate(s, 10, u'®') # you can use unicode string as *dots*
|
||||||
'ПРоба Є P®'
|
'ПРоба Є P®'
|
||||||
>>> type(s.truncate(10))
|
>>> type(truncate(s, 10))
|
||||||
<class '__main__.Utf8'>
|
<class '__main__.Utf8'>
|
||||||
>>> Utf8(s.encode('koi8-u'), 'koi8-u')
|
>>> Utf8(s.encode('koi8-u'), 'koi8-u')
|
||||||
'ПРоба Є PRobe'
|
'ПРоба Є PRobe'
|
||||||
|
|||||||
+8
-8
@@ -16,7 +16,7 @@ import random
|
|||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
from gluon.contrib.pbkdf2 import pbkdf2_hex
|
from contrib.pbkdf2 import pbkdf2_hex
|
||||||
|
|
||||||
logger = logging.getLogger("web2py")
|
logger = logging.getLogger("web2py")
|
||||||
|
|
||||||
@@ -69,15 +69,15 @@ def get_digest(value):
|
|||||||
elif value == "sha512":
|
elif value == "sha512":
|
||||||
return hashlib.sha512
|
return hashlib.sha512
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid digest algorithm")
|
raise ValueError("Invalid digest algorithm: %s" % value)
|
||||||
|
|
||||||
DIGEST_ALG_BY_SIZE = {
|
DIGEST_ALG_BY_SIZE = {
|
||||||
128/16: 'md5',
|
128/4: 'md5',
|
||||||
160/16: 'sha1',
|
160/4: 'sha1',
|
||||||
224/16: 'sha224',
|
224/4: 'sha224',
|
||||||
256/16: 'sha256',
|
256/4: 'sha256',
|
||||||
384/16: 'sha384',
|
384/4: 'sha384',
|
||||||
512/16: 'sha512',
|
512/4: 'sha512',
|
||||||
}
|
}
|
||||||
|
|
||||||
def hmac_hash(value, salt, digest_alg='md5'):
|
def hmac_hash(value, salt, digest_alg='md5'):
|
||||||
|
|||||||
+56
-7
@@ -130,7 +130,7 @@ class IS_MATCH(Validator):
|
|||||||
('hello', None)
|
('hello', None)
|
||||||
|
|
||||||
>>> IS_MATCH('hell')('hello')
|
>>> IS_MATCH('hell')('hello')
|
||||||
('hello', 'invalid expression')
|
('hello', None)
|
||||||
|
|
||||||
>>> IS_MATCH('hell.*', strict=False)('hello')
|
>>> IS_MATCH('hell.*', strict=False)('hello')
|
||||||
('hello', None)
|
('hello', None)
|
||||||
@@ -139,10 +139,10 @@ class IS_MATCH(Validator):
|
|||||||
('shello', 'invalid expression')
|
('shello', 'invalid expression')
|
||||||
|
|
||||||
>>> IS_MATCH('hello', search=True)('shello')
|
>>> IS_MATCH('hello', search=True)('shello')
|
||||||
('hello', None)
|
('shello', None)
|
||||||
|
|
||||||
>>> IS_MATCH('hello', search=True, strict=False)('shellox')
|
>>> IS_MATCH('hello', search=True, strict=False)('shellox')
|
||||||
('hello', None)
|
('shellox', None)
|
||||||
|
|
||||||
>>> IS_MATCH('.*hello.*', search=True, strict=False)('shellox')
|
>>> IS_MATCH('.*hello.*', search=True, strict=False)('shellox')
|
||||||
('shellox', None)
|
('shellox', None)
|
||||||
@@ -2579,7 +2579,13 @@ class LazyCrypt(object):
|
|||||||
"""
|
"""
|
||||||
compares the current lazy crypted password with a stored password
|
compares the current lazy crypted password with a stored password
|
||||||
"""
|
"""
|
||||||
key = self.crypt.key.split(':')[1] if ':' in self.crypt.key else ''
|
if self.crypt.key:
|
||||||
|
if ':' in self.crypt.key:
|
||||||
|
key = self.crypt.key.split(':')[1]
|
||||||
|
else:
|
||||||
|
key = self.crypt.key
|
||||||
|
else:
|
||||||
|
key = ''
|
||||||
if stored_password.count('$')==2:
|
if stored_password.count('$')==2:
|
||||||
(digest_alg, salt, hash) = stored_password.split('$')
|
(digest_alg, salt, hash) = stored_password.split('$')
|
||||||
masterkey = key+salt
|
masterkey = key+salt
|
||||||
@@ -2629,13 +2635,55 @@ class CRYPT(object):
|
|||||||
Important: hashed password is returned as a LazyCrypt object and computed only if needed.
|
Important: hashed password is returned as a LazyCrypt object and computed only if needed.
|
||||||
The LasyCrypt object also knows how to compare itself with an existing salted password
|
The LasyCrypt object also knows how to compare itself with an existing salted password
|
||||||
|
|
||||||
|
Supports standard algorithms
|
||||||
|
|
||||||
|
>>> for alg in ('md5','sha1','sha256','sha384','sha512'):
|
||||||
|
... print str(CRYPT(digest_alg=alg,salt=True)('test')[0])
|
||||||
|
md5$...$...
|
||||||
|
sha1$...$...
|
||||||
|
sha256$...$...
|
||||||
|
sha384$...$...
|
||||||
|
sha512$...$...
|
||||||
|
|
||||||
|
The syntax is always alg$salt$hash
|
||||||
|
|
||||||
|
Supports for pbkdf2
|
||||||
|
|
||||||
|
>>> alg = 'pbkdf2(1000,20,sha512)'
|
||||||
|
>>> print str(CRYPT(digest_alg=alg,salt=True)('test')[0])
|
||||||
|
pbkdf2(1000,20,sha512)$...$...
|
||||||
|
|
||||||
|
An optional hmac_key can be specified and it is used as salt prefix
|
||||||
|
|
||||||
|
>>> a = str(CRYPT(digest_alg='md5',key='mykey',salt=True)('test')[0])
|
||||||
|
>>> print a
|
||||||
|
md5$...$...
|
||||||
|
|
||||||
|
Even if the algorithm changes the hash can still be validated
|
||||||
|
|
||||||
|
>>> CRYPT(digest_alg='sha1',key='mykey',salt=True)('test')[0] == a
|
||||||
|
True
|
||||||
|
|
||||||
|
If no salt is specified CRYPT can guess the algorithms from length:
|
||||||
|
|
||||||
|
>>> a = str(CRYPT(digest_alg='sha1',salt=False)('test')[0])
|
||||||
|
>>> a
|
||||||
|
'sha1$$a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'
|
||||||
|
>>> CRYPT(digest_alg='sha1',salt=False)('test')[0] == a
|
||||||
|
True
|
||||||
|
>>> CRYPT(digest_alg='sha1',salt=False)('test')[0] == a[6:]
|
||||||
|
True
|
||||||
|
>>> CRYPT(digest_alg='md5',salt=False)('test')[0] == a
|
||||||
|
True
|
||||||
|
>>> CRYPT(digest_alg='md5',salt=False)('test')[0] == a[6:]
|
||||||
|
True
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
key=None,
|
key=None,
|
||||||
digest_alg='md5',
|
digest_alg='pbkdf2(1000,20,sha512)',
|
||||||
min_length=0,
|
min_length=0,
|
||||||
error_message='too short', salt=None):
|
error_message='too short', salt=True):
|
||||||
"""
|
"""
|
||||||
important, digest_alg='md5' is not the default hashing algorithm for
|
important, digest_alg='md5' is not the default hashing algorithm for
|
||||||
web2py. This is only an example of usage of this function.
|
web2py. This is only an example of usage of this function.
|
||||||
@@ -3093,7 +3141,8 @@ class IS_IPV4(Validator):
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import doctest
|
import doctest
|
||||||
doctest.testmod()
|
doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -9,6 +9,7 @@ License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html)
|
|||||||
The widget is called from web2py.
|
The widget is called from web2py.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import datetime
|
||||||
import sys
|
import sys
|
||||||
import cStringIO
|
import cStringIO
|
||||||
import time
|
import time
|
||||||
@@ -41,7 +42,7 @@ except NameError:
|
|||||||
BaseException = Exception
|
BaseException = Exception
|
||||||
|
|
||||||
ProgramName = 'web2py Web Framework'
|
ProgramName = 'web2py Web Framework'
|
||||||
ProgramAuthor = 'Created by Massimo Di Pierro, Copyright 2007-2011'
|
ProgramAuthor = 'Created by Massimo Di Pierro, Copyright 2007-' + str(datetime.datetime.now().year)
|
||||||
ProgramVersion = read_file('VERSION').strip()
|
ProgramVersion = read_file('VERSION').strip()
|
||||||
|
|
||||||
ProgramInfo = '''%s
|
ProgramInfo = '''%s
|
||||||
|
|||||||
Reference in new issue
Block a user