g3rpcserver.py :  » Network » Rufus-BitTorrent-Client » Rufus_0.7.0_src » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » Rufus BitTorrent Client 
Rufus BitTorrent Client » Rufus_0.7.0_src » g3rpcserver.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
#-----------------------------------------------------------------------------
# Name:        g3rpcserver.py
# Purpose:     
#
# Author:      Jeremy Arendt
#
# Created:     2004/20/02
# RCS-ID:      $Id: g3rpcserver.py,v 1.8 2005/11/21 00:26:03 inigo Exp $
# Copyright:   (c) 2002
# Licence:     See G3.LICENCE
#-----------------------------------------------------------------------------
import SocketServer
from xmlrpcserver import RequestHandler
from traceback import print_exc
from threading import Thread
from BitTorrent import version
from base64 import decodestring
from Cookie import SimpleCookie
from time import gmtime,strftime,sleep
from btconfig import BTConfig
import socket
import urlparse
import base64
import wx
import re
from urllib import unquote,quote
from os import path

class HtmlRenderer:
    def __init__(self, btsessions=None, myip=None, password=""):
        self.myip = myip
        self.password = password
        self.btsessions = btsessions
        self.html = []

    def FmtFileSize(self, bytes):
        if bytes > 2**30:
            return '%.2f GB' % (bytes/1073741824.0)
        elif bytes > 2**20:
            return '%.1f MB' % (bytes/1048576.0)
        elif bytes > 2**10:
            return '%.1f KB' % (bytes/1024.0)
        else:
            return '%d B' % bytes

    def Session2HTML(self, btsession):
        d = btsession.GetStatusData()
        s = btsession.GetStaticData()
        id = btsession.GetId()
        ipriority = btsession.GetQRank()

        filename = btsession.GetFilename()
        
        if btsession.GetFilesize() > 0:
            filesize = self.FmtFileSize( btsession.GetFilesize() )
        else:
            filesize = ""
        
        if btsession.IsRunning() and not btsession.IsPaused():
            action = "<a href='javascript:Stop(%d);'>Stop</a>" % id
        else:
            action = "<a href='javascript:Start(%d);'>Start</a>" % id
            
        if d == None or s == None:
            return ("<tr><td align='center'>%s <td>%s <td align='right'>%s"\
                    "<td>In Queue" % (action, filename, filesize)) + "<td><br>" * 5
            
        icompleted = d['fractionDone']
        iurate = d['urate']
        idrate = d['drate']
        iutotal = d['utotal']
        idtotal = d['dtotal']
        priority = str(ipriority)

        if btsession.IsComplete() and not idtotal:
            idtotal = btsession.GetFilesize()
        elif idtotal == None:
            idtotal = 0
        
        if iutotal == None:
            iutotal = 0
        
        dtotal = self.FmtFileSize(idtotal)
        utotal = self.FmtFileSize(iutotal)
            
        try:
            share_ratio = "%0.2f" % ((float(iutotal)+1) / (float(idtotal)+1))
        except ZeroDivisionError:
            share_ratio = "0"
                            
        if btsession.IsChecking():
            activity = 'Checking'                            
        elif btsession.IsComplete() and btsession.IsPaused():
            activity = 'Complete'
        elif btsession.IsComplete():
            activity = 'Seeding'
        elif btsession.IsStopped():
            activity = 'Stopped'
        elif btsession.IsPaused():
            activity = 'Paused'
        else:
            activity = 'Downloading'

        if d['timeleft'] == None or d['timeleft'] == -1:
            if btsession.IsComplete():
                timeleft = 'Done'
            else:
                timeleft = 'Unknown'
        else:
            if d['timeleft'] < 86400:
                t = gmtime(int(d['timeleft']))
                timeleft = strftime("%H:%M:%S", t)
            else:
                timeleft = "%.1f Days" % (float(d['timeleft']) / 86400)

        if idrate > 0:
            drate = '%.0f KB/s' % (float(idrate) / (1 << 10))
        else:
            drate = '0 KB/s'

        if iurate > 0:
            urate = '%.0f KB/s' % (float(iurate) / (1 << 10))
        else:
            urate = '0 KB/s'
        
        if d['avg_progress']:
            avg_progress = "%d" % int(d['avg_progress'] * 100)
        else:
            avg_progress = "0"
            
        if d['dist_copies']:
            dist_copies = "%0.2f" % d['dist_copies']
        else:
            dist_copies = "0"


        if d['seeds']:
            seeds = "%d" % d['seeds']
        else:
            seeds = "0"
        
        if d['peers']:
            peers = "%d" % d['peers']
        else:
            peers = "0"

        if peers != 0 and seeds != 0:
            leechers = int(peers) - int(seeds)
        else:
            leechers = 0

        completed = "%d%c" % (int(icompleted*100), '%')
        
        return "<tr><td align='center'>%s <td>%s <td align='right'>%s <td>%s" \
               "<td>%s <td align='right'>%s <td align='right'>%s <td>%s <td align='right'>%s" \
               "<td align='right'>%s <td align='right'>%s <td align='right'>%s" \
                % (action, filename, filesize, activity, completed, drate, urate, timeleft, share_ratio, seeds, leechers, peers )
    
    def Header(self):
        head = """
<img src='webui.bmp'> 
<h1>Rufus %s Web Interface</h1>
        """ % version
        return head
    
    def JavaScript(self):
        js = """
<script type="text/javascript" language="javascript">
    function Reload() {
        window.document.reload();
    }

    function Stop(id) {
        window.document.stopform.stop.value = id;
        window.document.stopform.submit();
    }

    function Start(id) {
        window.document.startform.start.value = id;

        window.document.startform.submit();
    }
</script>"""
        return js

    def StyleSheet(self): 
        ss = """
<style type='text/css'>

    a {

        color:#027185;

        font-family:Verdana,Arial,Helvetica;

        font-size: 9pt;
        font-weight:bold;
        text-decoration: none;

    }

    h1 { color:#c00000;font-family:Verdana,Arial,Helvetica; font-size: 10pt; font-weight:bold; }

    p { color:#000000; font-family:Verdana,Arial,Helvetica; font-size: 8pt; }

    
    table { font-family:Verdana,Arial,Helvetica; black; font-size: 10pt;}
    th { font-family:Verdana,Arial,Helvetica; border: single black; font-size: 10pt; 
        font-weight:bold; text-align: left;}
    td { font-family:Verdana,Arial,Helvetica; border: single black; font-size: 8pt; }

</style>"""
        
        return ss
    
        
    def RenderContent(self):
        html = self.html
        btsessions = self.btsessions
        A = self.html.append
        A( self.StyleSheet() )
        A("<html>")
        A( self.Header() )

        input_form = """
<form name="add" action="/" method=post>

    <p>
    <input type="hidden" name="pass" value="%s">
    <table>
      <tr>
        <td align="right">Add Torrent from URL: </td>
        <td>    <input type="text" name="addurl" maxLength=256 size=60 value="http://"></td>
      </tr>
      <tr>
        <td align="right">Referer: </td>
        <td><input type="text" name="referer" maxLength=256 size=60 value=""></td>
      </tr>
      <tr>
        <td></td>
        <td><input type="submit" value="Add"></td>
      </tr>
    </table>
    </p>

 </form>""" % (self.password)
             
        A( input_form )

        refresh_form = """
<form name="refresh" action="/" method=post>

    <p>

    <input type="hidden" name="pass" value="%s">
    <input type="submit" value="Refresh">
    </p>

 </form>""" % (self.password)
             
        A( refresh_form )

        A( "<table border='1' cellspacing='0' cellpadding='2'" )
        A( "<tr><th>Action <th>Filename <th>Filesize <th>Activity <th>Done <th>KB/s Dn <th>KB/s Up <th>ETA <th>Share Ratio <th>Seeds <th>Leechers <th>Peers </tr>" )
        
        for s in btsessions:
            A( self.Session2HTML(s) )
            A( "</tr>" )
        A( "</table>" )
        
        A( refresh_form )

        hStop_form = """
<form name="stopform" action="/" method=post>
    <input type="hidden" name="pass" value="%s">

    <input type="hidden" name="stop" value="-1">
 </form>""" % (self.password)
        A( hStop_form )
        
        hStart_form = """
<form name="startform" action="/" method=post>
    <input type="hidden" name="pass" value="%s">

    <input type="hidden" name="start" value="-1">
 </form>""" % (self.password)
        A( hStart_form )
        
        A( self.JavaScript() )
        A("</html>")
        
    def RenderLogin(self):
        html = self.html
        btsessions = self.btsessions
        A = self.html.append
        
        A( self.StyleSheet() )
        A("<html>")
        A( self.Header() )

        body = """
 <form action="/" method=post>

    <p>

    <label for="pass">Enter Password: </LABEL>
    <input type="password" name="pass">

    <input type="submit" value="Login">
    </p>

 </form>"""
         
        A( body )
        A("</html>")
        
    def GetHtml(self):
        if len(self.html) > 0:
            return "\n".join(self.html)
        else:
            return ""

class G3RequestHandler(RequestHandler):
    def ServeContent(self, password, store_cookie=False):
        ip = self.client_address[0]
        
        write = self.wfile.write
        self.send_response(200)
        self.send_header("Content-Type", "text/html")
        if store_cookie:
            self.send_header("Set-Cookie", "p='%s'"%password)
        self.end_headers()
        btsessions = self.server.btsessions
        btsessions_lock = self.server.btsessions_lock
        
        btsessions_lock.acquire(True)
        print 'Locking lock in rpcserver'
        try:
            renderer = HtmlRenderer(btsessions, self.myip, password)
            renderer.RenderContent()
            write( renderer.GetHtml() )
            print 'Releasing lock in rpcserver'
        except:
            print_exc()
        btsessions_lock.release()
        return

    def ServeLogin(self, password):
        write = self.wfile.write
        self.send_response(200)
        self.send_header("Content-Type", "text/html")
        self.end_headers()
        btsessions = self.server.btsessions
        btsessions_lock = self.server.btsessions_lock
        
        try:
            renderer = HtmlRenderer(myip=self.myip, password=password)
            renderer.RenderLogin()
            write( renderer.GetHtml() )
        except:
            pass
        
        return 
    
    def Post2Params(self, path):
        parts = path.split('&')
        params = {}
        for p in parts:
            split = p.split('=')
            if len(split) == 2:
                params[ split[0] ] = split[1]
        
        return params

    def Servebmp(self, filename):
        bmp = open(path.join(self.server.btconfig.Get('path'), "images/webui.bmp")).read()   ## tweak By Jukka Lehtomaki :P
        
        write = self.wfile.write
        self.send_response(200)
        self.send_header("Content-Type", "image/bmp")
        self.send_header("Content-Length", str(len(bmp)))
        self.end_headers()
        write(bmp)
        
    def do_POST(self):
        ## looks in the header to see what type of post (yes a bit lame... but it works for now)
        ## this needs much improving
        if self.headers["content-type"].count('xml') > 0:
            self.xml_do_POST()
        else:
            if self.server.btconfig['use_web_interface'] != True:
                return
            self.myip = socket.gethostbyaddr(socket.gethostname())[2][0]
            password = self.server.btconfig['web_interface_pass']
            
            password =  str(password)
            password.encode('utf-8')
            
            print self.headers
            btsessions = self.server.btsessions
            btsessions_lock = self.server.btsessions_lock

            try:
                # get arguments
                data = self.rfile.read(int(self.headers["content-length"]))
                params = self.Post2Params(data)
                passwd = params.get('pass')

                # password must not equal default password
                if password != "password" and passwd == password:
                    if params.get('start') != None:
                        btsessions_lock.acquire(True)
                        try:
                            id = int(params.get('start'))
                            for s in btsessions:
                                if s.GetId() == id:
                                    s.Resume()
                                    break
                        except:
                            pass
                        btsessions_lock.release()
                        sleep(3)
    
                    if params.get('stop') != None:
                        btsessions_lock.acquire(True)
                        try:
                            id = int(params.get('stop'))
                            for s in btsessions:
                                if s.GetId() == id:
                                    s.Stop()
                                    break
                        except:
                            pass
                        btsessions_lock.release()
    
                    if params.get('addurl') != None:
                        self.AddTorrent_URL( unquote( params.get('addurl') ), unquote( params.get('referer') ) )
                        sleep(3)                
                    self.ServeContent(passwd)
                    return
    
            except KeyError:
                pass

            self.ServeLogin(password)

    def do_GET(self):
        if self.server.btconfig['use_web_interface'] != True:
            return
        self.myip = socket.gethostbyaddr(socket.gethostname())[2][0]
        password = self.server.btconfig['web_interface_pass']
        try:

            if '.bmp' in self.path:
                m = re.compile('(?<=[/]).+').search(self.path)
                if m:
                    filename = m.group().split('?')[0]
                else:
                    return
                self.Servebmp(filename)
                return 

        except KeyError:
            pass

        self.ServeLogin(password)
    

    def call(self, method, params):
        print method, params
        valid_methods = ["FriendRenounce", "FriendAnnounce", "GetVersion", "AddTorrent"]
        try:

            server_method = getattr(self, method)
            if method in valid_methods:

                return server_method(params[0])

        except:
            raise AttributeError, "Invalid Request: %s" % method
        return 0
    
    def log_request(self, code='', size=''):
        pass    # don't want to see these in stdout
        
    def FriendRenounce(self, p):
        ip = self.client_address[0]
        try:
            #0:peerid, 1:port, 2:infohash
            self.server.UpdateFunc(ip, decodestring(p[0]), 9, [ p[1], decodestring(p[2]) ])
            return 1
        except:
            return 0
        
    def FriendAnnounce(self, p):
        ip = self.client_address[0]
        try:
            #0:peerid, 1:port, 2:infohash
            self.server.UpdateFunc(ip, decodestring(p[0]), 0, [ p[1], decodestring(p[2]) ])
            return 1
        except:
            return 0
    
    def GetVersion(self, p):
        return version
        
    # Accept requests from localhost ONLY
    def AddTorrent(self, responsefile):
        ip = self.client_address[0]
        if ip != '127.0.0.1':
            return -1
        try:
            self.server.AddTorrentFunc(responsefile)
            return 1
        except:
            return 0

    def AddTorrent_URL(self, url, referer):
        try:
            self.server.AddTorrentFunc(url, referer, 1)
            return 1
        except:
            return 0

class G3RPCServer(SocketServer.TCPServer):
    def __init__(self, btconfig, errorfunc, friendupdatefunc, addtorrentfunc, 
            btsessions, btsessions_lock, images):
        self.btconfig = btconfig
        self.bound = False
        self.ErrorFunc = errorfunc
        self.UpdateFunc = friendupdatefunc
        self.AddTorrentFunc = addtorrentfunc
        self.btsessions = btsessions
        self.btsessions_lock = btsessions_lock
        self.images = images
        self._aborted = False

        try:
            SocketServer.TCPServer.__init__(self, ("", btconfig.Get('web_interface_port')), G3RequestHandler)
            self.bound = True
        except:
            self.ErrorFunc("ERROR", "Could not bind socket for xml rpc - Address in use", -2)
          
    def Start(self):
        t = Thread(target = self.ListenForever, name = "G3RPCServer", args = [])
        t.setDaemon(True)
        t.start()

    def Stop(self):
        self._aborted = True
        import httplib
        try:
            req = httplib.HTTP('%s:%d' % ("127.0.0.1", self.btconfig.Get('web_interface_port')))
            req.connect()
            del req
        except:
            pass

    def ListenForever(self):
        try:
            if self.bound:
                print "G3XMLRPCServer Started"
                while not self._aborted:
                    self.handle_request()
                print "G3XMLRPCServer Stopped"
        except:
            print_exc()
    
def dummy_errorfunc(name, msg, type):
    print name, ' ', msg

def dummy_update(ip, peerid, msgtype, data):
    print ip, ' ', peerid, ' ', str(msgtype), ' ', data
    
def dummy_addtorrent(responsefile):
    print responsefile
    
if __name__ == "__main__":

    server = G3RPCServer(dummy_errorfunc, dummy_update, dummy_addtorrent)
    server.ListenForever()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.