OpenSecurity/install/web.py-0.37/build/lib/web/debugerror.py
changeset 3 65432e6c6042
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/OpenSecurity/install/web.py-0.37/build/lib/web/debugerror.py	Mon Dec 02 14:02:05 2013 +0100
     1.3 @@ -0,0 +1,354 @@
     1.4 +"""
     1.5 +pretty debug errors
     1.6 +(part of web.py)
     1.7 +
     1.8 +portions adapted from Django <djangoproject.com> 
     1.9 +Copyright (c) 2005, the Lawrence Journal-World
    1.10 +Used under the modified BSD license:
    1.11 +http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
    1.12 +"""
    1.13 +
    1.14 +__all__ = ["debugerror", "djangoerror", "emailerrors"]
    1.15 +
    1.16 +import sys, urlparse, pprint, traceback
    1.17 +from template import Template
    1.18 +from net import websafe
    1.19 +from utils import sendmail, safestr
    1.20 +import webapi as web
    1.21 +
    1.22 +import os, os.path
    1.23 +whereami = os.path.join(os.getcwd(), __file__)
    1.24 +whereami = os.path.sep.join(whereami.split(os.path.sep)[:-1])
    1.25 +djangoerror_t = """\
    1.26 +$def with (exception_type, exception_value, frames)
    1.27 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    1.28 +<html lang="en">
    1.29 +<head>
    1.30 +  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    1.31 +  <meta name="robots" content="NONE,NOARCHIVE" />
    1.32 +  <title>$exception_type at $ctx.path</title>
    1.33 +  <style type="text/css">
    1.34 +    html * { padding:0; margin:0; }
    1.35 +    body * { padding:10px 20px; }
    1.36 +    body * * { padding:0; }
    1.37 +    body { font:small sans-serif; }
    1.38 +    body>div { border-bottom:1px solid #ddd; }
    1.39 +    h1 { font-weight:normal; }
    1.40 +    h2 { margin-bottom:.8em; }
    1.41 +    h2 span { font-size:80%; color:#666; font-weight:normal; }
    1.42 +    h3 { margin:1em 0 .5em 0; }
    1.43 +    h4 { margin:0 0 .5em 0; font-weight: normal; }
    1.44 +    table { 
    1.45 +        border:1px solid #ccc; border-collapse: collapse; background:white; }
    1.46 +    tbody td, tbody th { vertical-align:top; padding:2px 3px; }
    1.47 +    thead th { 
    1.48 +        padding:1px 6px 1px 3px; background:#fefefe; text-align:left; 
    1.49 +        font-weight:normal; font-size:11px; border:1px solid #ddd; }
    1.50 +    tbody th { text-align:right; color:#666; padding-right:.5em; }
    1.51 +    table.vars { margin:5px 0 2px 40px; }
    1.52 +    table.vars td, table.req td { font-family:monospace; }
    1.53 +    table td.code { width:100%;}
    1.54 +    table td.code div { overflow:hidden; }
    1.55 +    table.source th { color:#666; }
    1.56 +    table.source td { 
    1.57 +        font-family:monospace; white-space:pre; border-bottom:1px solid #eee; }
    1.58 +    ul.traceback { list-style-type:none; }
    1.59 +    ul.traceback li.frame { margin-bottom:1em; }
    1.60 +    div.context { margin: 10px 0; }
    1.61 +    div.context ol { 
    1.62 +        padding-left:30px; margin:0 10px; list-style-position: inside; }
    1.63 +    div.context ol li { 
    1.64 +        font-family:monospace; white-space:pre; color:#666; cursor:pointer; }
    1.65 +    div.context ol.context-line li { color:black; background-color:#ccc; }
    1.66 +    div.context ol.context-line li span { float: right; }
    1.67 +    div.commands { margin-left: 40px; }
    1.68 +    div.commands a { color:black; text-decoration:none; }
    1.69 +    #summary { background: #ffc; }
    1.70 +    #summary h2 { font-weight: normal; color: #666; }
    1.71 +    #explanation { background:#eee; }
    1.72 +    #template, #template-not-exist { background:#f6f6f6; }
    1.73 +    #template-not-exist ul { margin: 0 0 0 20px; }
    1.74 +    #traceback { background:#eee; }
    1.75 +    #requestinfo { background:#f6f6f6; padding-left:120px; }
    1.76 +    #summary table { border:none; background:transparent; }
    1.77 +    #requestinfo h2, #requestinfo h3 { position:relative; margin-left:-100px; }
    1.78 +    #requestinfo h3 { margin-bottom:-1em; }
    1.79 +    .error { background: #ffc; }
    1.80 +    .specific { color:#cc3300; font-weight:bold; }
    1.81 +  </style>
    1.82 +  <script type="text/javascript">
    1.83 +  //<!--
    1.84 +    function getElementsByClassName(oElm, strTagName, strClassName){
    1.85 +        // Written by Jonathan Snook, http://www.snook.ca/jon; 
    1.86 +        // Add-ons by Robert Nyman, http://www.robertnyman.com
    1.87 +        var arrElements = (strTagName == "*" && document.all)? document.all :
    1.88 +        oElm.getElementsByTagName(strTagName);
    1.89 +        var arrReturnElements = new Array();
    1.90 +        strClassName = strClassName.replace(/\-/g, "\\-");
    1.91 +        var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$$)");
    1.92 +        var oElement;
    1.93 +        for(var i=0; i<arrElements.length; i++){
    1.94 +            oElement = arrElements[i];
    1.95 +            if(oRegExp.test(oElement.className)){
    1.96 +                arrReturnElements.push(oElement);
    1.97 +            }
    1.98 +        }
    1.99 +        return (arrReturnElements)
   1.100 +    }
   1.101 +    function hideAll(elems) {
   1.102 +      for (var e = 0; e < elems.length; e++) {
   1.103 +        elems[e].style.display = 'none';
   1.104 +      }
   1.105 +    }
   1.106 +    window.onload = function() {
   1.107 +      hideAll(getElementsByClassName(document, 'table', 'vars'));
   1.108 +      hideAll(getElementsByClassName(document, 'ol', 'pre-context'));
   1.109 +      hideAll(getElementsByClassName(document, 'ol', 'post-context'));
   1.110 +    }
   1.111 +    function toggle() {
   1.112 +      for (var i = 0; i < arguments.length; i++) {
   1.113 +        var e = document.getElementById(arguments[i]);
   1.114 +        if (e) {
   1.115 +          e.style.display = e.style.display == 'none' ? 'block' : 'none';
   1.116 +        }
   1.117 +      }
   1.118 +      return false;
   1.119 +    }
   1.120 +    function varToggle(link, id) {
   1.121 +      toggle('v' + id);
   1.122 +      var s = link.getElementsByTagName('span')[0];
   1.123 +      var uarr = String.fromCharCode(0x25b6);
   1.124 +      var darr = String.fromCharCode(0x25bc);
   1.125 +      s.innerHTML = s.innerHTML == uarr ? darr : uarr;
   1.126 +      return false;
   1.127 +    }
   1.128 +    //-->
   1.129 +  </script>
   1.130 +</head>
   1.131 +<body>
   1.132 +
   1.133 +$def dicttable (d, kls='req', id=None):
   1.134 +    $ items = d and d.items() or []
   1.135 +    $items.sort()
   1.136 +    $:dicttable_items(items, kls, id)
   1.137 +        
   1.138 +$def dicttable_items(items, kls='req', id=None):
   1.139 +    $if items:
   1.140 +        <table class="$kls"
   1.141 +        $if id: id="$id"
   1.142 +        ><thead><tr><th>Variable</th><th>Value</th></tr></thead>
   1.143 +        <tbody>
   1.144 +        $for k, v in items:
   1.145 +            <tr><td>$k</td><td class="code"><div>$prettify(v)</div></td></tr>
   1.146 +        </tbody>
   1.147 +        </table>
   1.148 +    $else:
   1.149 +        <p>No data.</p>
   1.150 +
   1.151 +<div id="summary">
   1.152 +  <h1>$exception_type at $ctx.path</h1>
   1.153 +  <h2>$exception_value</h2>
   1.154 +  <table><tr>
   1.155 +    <th>Python</th>
   1.156 +    <td>$frames[0].filename in $frames[0].function, line $frames[0].lineno</td>
   1.157 +  </tr><tr>
   1.158 +    <th>Web</th>
   1.159 +    <td>$ctx.method $ctx.home$ctx.path</td>
   1.160 +  </tr></table>
   1.161 +</div>
   1.162 +<div id="traceback">
   1.163 +<h2>Traceback <span>(innermost first)</span></h2>
   1.164 +<ul class="traceback">
   1.165 +$for frame in frames:
   1.166 +    <li class="frame">
   1.167 +    <code>$frame.filename</code> in <code>$frame.function</code>
   1.168 +    $if frame.context_line is not None:
   1.169 +        <div class="context" id="c$frame.id">
   1.170 +        $if frame.pre_context:
   1.171 +            <ol start="$frame.pre_context_lineno" class="pre-context" id="pre$frame.id">
   1.172 +            $for line in frame.pre_context:
   1.173 +                <li onclick="toggle('pre$frame.id', 'post$frame.id')">$line</li>
   1.174 +            </ol>
   1.175 +            <ol start="$frame.lineno" class="context-line"><li onclick="toggle('pre$frame.id', 'post$frame.id')">$frame.context_line <span>...</span></li></ol>
   1.176 +        $if frame.post_context:
   1.177 +            <ol start='${frame.lineno + 1}' class="post-context" id="post$frame.id">
   1.178 +            $for line in frame.post_context:
   1.179 +                <li onclick="toggle('pre$frame.id', 'post$frame.id')">$line</li>
   1.180 +            </ol>
   1.181 +      </div>
   1.182 +    
   1.183 +    $if frame.vars:
   1.184 +        <div class="commands">
   1.185 +        <a href='#' onclick="return varToggle(this, '$frame.id')"><span>&#x25b6;</span> Local vars</a>
   1.186 +        $# $inspect.formatargvalues(*inspect.getargvalues(frame['tb'].tb_frame))
   1.187 +        </div>
   1.188 +        $:dicttable(frame.vars, kls='vars', id=('v' + str(frame.id)))
   1.189 +      </li>
   1.190 +  </ul>
   1.191 +</div>
   1.192 +
   1.193 +<div id="requestinfo">
   1.194 +$if ctx.output or ctx.headers:
   1.195 +    <h2>Response so far</h2>
   1.196 +    <h3>HEADERS</h3>
   1.197 +    $:dicttable_items(ctx.headers)
   1.198 +
   1.199 +    <h3>BODY</h3>
   1.200 +    <p class="req" style="padding-bottom: 2em"><code>
   1.201 +    $ctx.output
   1.202 +    </code></p>
   1.203 +  
   1.204 +<h2>Request information</h2>
   1.205 +
   1.206 +<h3>INPUT</h3>
   1.207 +$:dicttable(web.input(_unicode=False))
   1.208 +
   1.209 +<h3 id="cookie-info">COOKIES</h3>
   1.210 +$:dicttable(web.cookies())
   1.211 +
   1.212 +<h3 id="meta-info">META</h3>
   1.213 +$ newctx = [(k, v) for (k, v) in ctx.iteritems() if not k.startswith('_') and not isinstance(v, dict)]
   1.214 +$:dicttable(dict(newctx))
   1.215 +
   1.216 +<h3 id="meta-info">ENVIRONMENT</h3>
   1.217 +$:dicttable(ctx.env)
   1.218 +</div>
   1.219 +
   1.220 +<div id="explanation">
   1.221 +  <p>
   1.222 +    You're seeing this error because you have <code>web.config.debug</code>
   1.223 +    set to <code>True</code>. Set that to <code>False</code> if you don't want to see this.
   1.224 +  </p>
   1.225 +</div>
   1.226 +
   1.227 +</body>
   1.228 +</html>
   1.229 +"""
   1.230 +
   1.231 +djangoerror_r = None
   1.232 +
   1.233 +def djangoerror():
   1.234 +    def _get_lines_from_file(filename, lineno, context_lines):
   1.235 +        """
   1.236 +        Returns context_lines before and after lineno from file.
   1.237 +        Returns (pre_context_lineno, pre_context, context_line, post_context).
   1.238 +        """
   1.239 +        try:
   1.240 +            source = open(filename).readlines()
   1.241 +            lower_bound = max(0, lineno - context_lines)
   1.242 +            upper_bound = lineno + context_lines
   1.243 +
   1.244 +            pre_context = \
   1.245 +                [line.strip('\n') for line in source[lower_bound:lineno]]
   1.246 +            context_line = source[lineno].strip('\n')
   1.247 +            post_context = \
   1.248 +                [line.strip('\n') for line in source[lineno + 1:upper_bound]]
   1.249 +
   1.250 +            return lower_bound, pre_context, context_line, post_context
   1.251 +        except (OSError, IOError, IndexError):
   1.252 +            return None, [], None, []    
   1.253 +    
   1.254 +    exception_type, exception_value, tback = sys.exc_info()
   1.255 +    frames = []
   1.256 +    while tback is not None:
   1.257 +        filename = tback.tb_frame.f_code.co_filename
   1.258 +        function = tback.tb_frame.f_code.co_name
   1.259 +        lineno = tback.tb_lineno - 1
   1.260 +
   1.261 +        # hack to get correct line number for templates
   1.262 +        lineno += tback.tb_frame.f_locals.get("__lineoffset__", 0)
   1.263 +        
   1.264 +        pre_context_lineno, pre_context, context_line, post_context = \
   1.265 +            _get_lines_from_file(filename, lineno, 7)
   1.266 +
   1.267 +        if '__hidetraceback__' not in tback.tb_frame.f_locals:
   1.268 +            frames.append(web.storage({
   1.269 +                'tback': tback,
   1.270 +                'filename': filename,
   1.271 +                'function': function,
   1.272 +                'lineno': lineno,
   1.273 +                'vars': tback.tb_frame.f_locals,
   1.274 +                'id': id(tback),
   1.275 +                'pre_context': pre_context,
   1.276 +                'context_line': context_line,
   1.277 +                'post_context': post_context,
   1.278 +                'pre_context_lineno': pre_context_lineno,
   1.279 +            }))
   1.280 +        tback = tback.tb_next
   1.281 +    frames.reverse()
   1.282 +    urljoin = urlparse.urljoin
   1.283 +    def prettify(x):
   1.284 +        try: 
   1.285 +            out = pprint.pformat(x)
   1.286 +        except Exception, e: 
   1.287 +            out = '[could not display: <' + e.__class__.__name__ + \
   1.288 +                  ': '+str(e)+'>]'
   1.289 +        return out
   1.290 +        
   1.291 +    global djangoerror_r
   1.292 +    if djangoerror_r is None:
   1.293 +        djangoerror_r = Template(djangoerror_t, filename=__file__, filter=websafe)
   1.294 +        
   1.295 +    t = djangoerror_r
   1.296 +    globals = {'ctx': web.ctx, 'web':web, 'dict':dict, 'str':str, 'prettify': prettify}
   1.297 +    t.t.func_globals.update(globals)
   1.298 +    return t(exception_type, exception_value, frames)
   1.299 +
   1.300 +def debugerror():
   1.301 +    """
   1.302 +    A replacement for `internalerror` that presents a nice page with lots
   1.303 +    of debug information for the programmer.
   1.304 +
   1.305 +    (Based on the beautiful 500 page from [Django](http://djangoproject.com/), 
   1.306 +    designed by [Wilson Miner](http://wilsonminer.com/).)
   1.307 +    """
   1.308 +    return web._InternalError(djangoerror())
   1.309 +
   1.310 +def emailerrors(to_address, olderror, from_address=None):
   1.311 +    """
   1.312 +    Wraps the old `internalerror` handler (pass as `olderror`) to 
   1.313 +    additionally email all errors to `to_address`, to aid in
   1.314 +    debugging production websites.
   1.315 +    
   1.316 +    Emails contain a normal text traceback as well as an
   1.317 +    attachment containing the nice `debugerror` page.
   1.318 +    """
   1.319 +    from_address = from_address or to_address
   1.320 +
   1.321 +    def emailerrors_internal():
   1.322 +        error = olderror()
   1.323 +        tb = sys.exc_info()
   1.324 +        error_name = tb[0]
   1.325 +        error_value = tb[1]
   1.326 +        tb_txt = ''.join(traceback.format_exception(*tb))
   1.327 +        path = web.ctx.path
   1.328 +        request = web.ctx.method + ' ' + web.ctx.home + web.ctx.fullpath
   1.329 +        
   1.330 +        message = "\n%s\n\n%s\n\n" % (request, tb_txt)
   1.331 +        
   1.332 +        sendmail(
   1.333 +            "your buggy site <%s>" % from_address,
   1.334 +            "the bugfixer <%s>" % to_address,
   1.335 +            "bug: %(error_name)s: %(error_value)s (%(path)s)" % locals(),
   1.336 +            message,
   1.337 +            attachments=[
   1.338 +                dict(filename="bug.html", content=safestr(djangoerror()))
   1.339 +            ],
   1.340 +        )
   1.341 +        return error
   1.342 +    
   1.343 +    return emailerrors_internal
   1.344 +
   1.345 +if __name__ == "__main__":
   1.346 +    urls = (
   1.347 +        '/', 'index'
   1.348 +    )
   1.349 +    from application import application
   1.350 +    app = application(urls, globals())
   1.351 +    app.internalerror = debugerror
   1.352 +    
   1.353 +    class index:
   1.354 +        def GET(self):
   1.355 +            thisdoesnotexist
   1.356 +
   1.357 +    app.run()