thirdparty/google_appengine/lib/webob/docs/comment-example-code/example.py
changeset 109 620f9b141567
equal deleted inserted replaced
108:261778de26ff 109:620f9b141567
       
     1 import os
       
     2 import urllib
       
     3 import time
       
     4 import re
       
     5 from cPickle import load, dump
       
     6 from webob import Request, Response, html_escape
       
     7 from webob import exc
       
     8     
       
     9 class Commenter(object):
       
    10 
       
    11     def __init__(self, app, storage_dir):
       
    12         self.app = app
       
    13         self.storage_dir = storage_dir
       
    14         if not os.path.exists(storage_dir):
       
    15             os.makedirs(storage_dir)
       
    16 
       
    17     def __call__(self, environ, start_response):
       
    18         req = Request(environ)
       
    19         if req.path_info_peek() == '.comments':
       
    20             return self.process_comment(req)(environ, start_response)
       
    21         # This is the base path of *this* middleware:
       
    22         base_url = req.application_url
       
    23         resp = req.get_response(self.app)
       
    24         if resp.content_type != 'text/html' or resp.status_int != 200:
       
    25             # Not an HTML response, we don't want to
       
    26             # do anything to it
       
    27             return resp(environ, start_response)
       
    28         # Make sure the content isn't gzipped:
       
    29         resp.decode_content()
       
    30         comments = self.get_data(req.url)
       
    31         body = resp.body
       
    32         body = self.add_to_end(body, self.format_comments(comments))
       
    33         body = self.add_to_end(body, self.submit_form(base_url, req))
       
    34         resp.body = body
       
    35         return resp(environ, start_response)
       
    36 
       
    37     def get_data(self, url):
       
    38         # Double-quoting makes the filename safe
       
    39         filename = self.url_filename(url)
       
    40         if not os.path.exists(filename):
       
    41             return []
       
    42         else:
       
    43             f = open(filename, 'rb')
       
    44             data = load(f)
       
    45             f.close()
       
    46             return data
       
    47 
       
    48     def save_data(self, url, data):
       
    49         filename = self.url_filename(url)
       
    50         f = open(filename, 'wb')
       
    51         dump(data, f)
       
    52         f.close()
       
    53 
       
    54     def url_filename(self, url):
       
    55         return os.path.join(self.storage_dir, urllib.quote(url, ''))
       
    56 
       
    57     _end_body_re = re.compile(r'</body.*?>', re.I|re.S)
       
    58 
       
    59     def add_to_end(self, html, extra_html):
       
    60         """
       
    61         Adds extra_html to the end of the html page (before </body>)
       
    62         """
       
    63         match = self._end_body_re.search(html)
       
    64         if not match:
       
    65             return html + extra_html
       
    66         else:
       
    67             return html[:match.start()] + extra_html + html[match.start():]
       
    68 
       
    69     def format_comments(self, comments):
       
    70         if not comments:
       
    71             return ''
       
    72         text = []
       
    73         text.append('<hr>')
       
    74         text.append('<h2><a name="comment-area"></a>Comments (%s):</h2>' % len(comments))
       
    75         for comment in comments:
       
    76             text.append('<h3><a href="%s">%s</a> at %s:</h3>' % (
       
    77                 html_escape(comment['homepage']), html_escape(comment['name']),
       
    78                 time.strftime('%c', comment['time'])))
       
    79             # Susceptible to XSS attacks!:
       
    80             text.append(comment['comments'])
       
    81         return ''.join(text)
       
    82 
       
    83     def submit_form(self, base_path, req):
       
    84         return '''<h2>Leave a comment:</h2>
       
    85         <form action="%s/.comments" method="POST">
       
    86          <input type="hidden" name="url" value="%s">
       
    87          <table width="100%%">
       
    88           <tr><td>Name:</td>
       
    89               <td><input type="text" name="name" style="width: 100%%"></td></tr>
       
    90           <tr><td>URL:</td>
       
    91               <td><input type="text" name="homepage" style="width: 100%%"></td></tr>
       
    92          </table>
       
    93          Comments:<br>
       
    94          <textarea name="comments" rows=10 style="width: 100%%"></textarea><br>
       
    95          <input type="submit" value="Submit comment">
       
    96         </form>
       
    97         ''' % (base_path, html_escape(req.url))
       
    98 
       
    99     def process_comment(self, req):
       
   100         try:
       
   101             url = req.params['url']
       
   102             name = req.params['name']
       
   103             homepage = req.params['homepage']
       
   104             comments = req.params['comments']
       
   105         except KeyError, e:
       
   106             resp = exc.HTTPBadRequest('Missing parameter: %s' % e)
       
   107             return resp
       
   108         data = self.get_data(url)
       
   109         data.append(dict(
       
   110             name=name,
       
   111             homepage=homepage,
       
   112             comments=comments,
       
   113             time=time.gmtime()))
       
   114         self.save_data(url, data)
       
   115         resp = exc.HTTPSeeOther(location=url+'#comment-area')
       
   116         return resp
       
   117 
       
   118 if __name__ == '__main__':
       
   119     import optparse
       
   120     parser = optparse.OptionParser(
       
   121         usage='%prog --port=PORT BASE_DIRECTORY'
       
   122         )
       
   123     parser.add_option(
       
   124         '-p', '--port',
       
   125         default='8080',
       
   126         dest='port',
       
   127         type='int',
       
   128         help='Port to serve on (default 8080)')
       
   129     parser.add_option(
       
   130         '--comment-data',
       
   131         default='./comments',
       
   132         dest='comment_data',
       
   133         help='Place to put comment data into (default ./comments/)')
       
   134     options, args = parser.parse_args()
       
   135     if not args:
       
   136         parser.error('You must give a BASE_DIRECTORY')
       
   137     base_dir = args[0]
       
   138     from paste.urlparser import StaticURLParser
       
   139     app = StaticURLParser(base_dir)
       
   140     app = Commenter(app, options.comment_data)
       
   141     from wsgiref.simple_server import make_server
       
   142     httpd = make_server('localhost', options.port, app)
       
   143     print 'Serving on http://localhost:%s' % options.port
       
   144     try:
       
   145         httpd.serve_forever()
       
   146     except KeyboardInterrupt:
       
   147         print '^C'
       
   148 
       
   149     
       
   150