[Dextrose] Initial feedback implementation

Aleksey Lim alsroot at member.fsf.org
Mon Jan 17 21:43:37 EST 2011


Hi all,

This is an initial feedback implementation that might be improved
later (eg icons and what feedback should contain).

There are new gconf keys:

  /desktop/sugar/feedback/enabled
  /desktop/sugar/feedback/server_host
  /desktop/sugar/feedback/server_port
  /desktop/sugar/feedback/auto_submit_delay

There is frame icon in device tray with two palette menu options:

* send personalized (contact info) reports with additional message
* send anonymous reports (if exist) immediately

For now reports are unhandled reports in shell/activities, failed start/exit of activities.
All reports are being sent via HTTPS POST requests to the server.

Simple server implementation:

import cgi
import json
import socket
import logging
import tarfile
from cStringIO import StringIO
from SocketServer import ThreadingMixIn, TCPServer, BaseServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
from OpenSSL import SSL


pemfile = 'feedback.sugarlabs.org.pem'
host = 'localhost'
port = 8080


class RequestHandler(SimpleHTTPRequestHandler):

    def setup(self):
        self.connection = self.request
        self.rfile = socket._fileobject(self.request, 'rb', self.rbufsize)
        self.wfile = socket._fileobject(self.request, 'wb', self.wbufsize)

    def do_GET(self):
        self._reply(403, 'Only POST requests are allowed')

    def do_POST(self):
        ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))

        if ctype != 'multipart/form-data':
            self._reply(403, 'Only multipart/form-data is accepted')
            return

        body = cgi.parse_multipart(self.rfile, pdict)
        tar_content = body.get('report')
        if not tar_content:
            self._reply(403, 'No "report" form parameter')
            return

        try:
            tar = tarfile.open(fileobj=StringIO(tar_content[0]), mode='r:gz')
            print tar.extractfile('report').read()
            self._reply(200, 'Report was accepted')
        except Exception:
            logging.exception('Cannot process request')
            self._reply(403, 'Cannot process request')

    def _reply(self, code, message):
        self.send_response(code)
        self.send_header('Content-type', 'text/html')
        self.send_header('Content-length', len(message))
        self.end_headers()

        self.wfile.write(message)

        self.wfile.flush()
        self.connection.shutdown()


class Server(ThreadingMixIn, TCPServer):

    def __init__(self, server_address, HandlerClass):
        BaseServer.__init__(self, server_address, HandlerClass)

        ctx = SSL.Context(SSL.SSLv23_METHOD)
        ctx.use_privatekey_file(pemfile)
        ctx.use_certificate_file(pemfile)
        self.socket = SSL.Connection(ctx,
                socket.socket(self.address_family, self.socket_type))

        self.allow_reuse_address = True
        self.server_bind()
        self.server_activate()


srv = Server((host, port), RequestHandler)
srv.serve_forever()

srv_thread = threading.Thread(target=srv.serve_forever)
srv_thread.start()

-- 
Aleksey


More information about the Dextrose mailing list