1 import time
, os
, BaseHTTPServer
, SocketServer
, socket
, re
2 from urllib
import unquote_plus
, quote
, unquote
3 from urlparse
import urlparse
4 from cgi
import parse_qs
5 from Cheetah
.Template
import Template
6 from plugin
import GetPlugin
8 from xml
.sax
.saxutils
import escape
11 SCRIPTDIR
= os
.path
.dirname(__file__
)
13 hack83
= config
.getHack83()
15 class TivoHTTPServer(SocketServer
.ThreadingMixIn
, BaseHTTPServer
.HTTPServer
):
18 def __init__(self
, server_address
, RequestHandlerClass
):
19 BaseHTTPServer
.HTTPServer
.__init
__(self
, server_address
,
21 self
.daemon_threads
= True
23 def add_container(self
, name
, settings
):
24 if self
.containers
.has_key(name
) or name
== 'TiVoConnect':
25 raise "Container Name in use"
27 settings
['content_type'] = GetPlugin(settings
['type']).CONTENT_TYPE
28 self
.containers
[name
] = settings
30 print 'Unable to add container', name
33 self
.containers
.clear()
34 for section
, settings
in config
.getShares():
35 self
.add_container(section
, settings
)
37 class TivoHTTPHandler(BaseHTTPServer
.BaseHTTPRequestHandler
):
40 def address_string(self
):
41 host
, port
= self
.client_address
[:2]
45 tsn
= self
.headers
.getheader('TiVo_TCD_ID', self
.headers
.getheader('tsn', ''))
46 ip
= self
.address_string()
49 basepath
= unquote_plus(self
.path
).split('/')[1]
52 for name
, container
in self
.server
.containers
.items():
54 plugin
= GetPlugin(container
['type'])
55 plugin
.send_file(self
, container
, name
)
58 ## Not a file not a TiVo command fuck them
59 if not self
.path
.startswith('/TiVoConnect'):
63 o
= urlparse("http://fake.host" + self
.path
)
64 query
= parse_qs(o
[4])
67 if query
.has_key('Command') and len(query
['Command']) >= 1:
69 command
= query
['Command'][0]
71 # If we are looking at the root container
72 if command
== "QueryContainer" and \
73 (not query
.has_key('Container') or query
['Container'][0] == '/'):
77 if query
.has_key('Container'):
78 # Dispatch to the container plugin
79 basepath
= unquote(query
['Container'][0].split('/')[0])
80 for name
, container
in self
.server
.containers
.items():
82 plugin
= GetPlugin(container
['type'])
83 if hasattr(plugin
, command
):
84 method
= getattr(plugin
, command
)
90 # If we made it here it means we couldn't match the request to
92 self
.unsupported(query
)
94 def root_container(self
):
95 tsn
= self
.headers
.getheader('TiVo_TCD_ID', '')
96 tsnshares
= config
.getShares(tsn
)
98 for section
, settings
in tsnshares
:
100 settings
['content_type'] = \
101 GetPlugin(settings
['type']).CONTENT_TYPE
102 tsncontainers
[section
] = settings
103 except Exception, msg
:
104 print section
, '-', msg
105 t
= Template(file=os
.path
.join(SCRIPTDIR
, 'templates',
106 'root_container.tmpl'))
107 t
.containers
= tsncontainers
108 t
.hostname
= socket
.gethostname()
111 self
.send_response(200)
116 self
.send_response(200)
117 self
.send_header('Content-type', 'text/html')
119 t
= Template(file=os
.path
.join(SCRIPTDIR
, 'templates',
122 for section
, settings
in config
.getShares():
123 if 'type' in settings
and settings
['type'] == 'admin':
124 t
.admin
+= '<a href="/TiVoConnect?Command=Admin&Container=' + quote(section
)\
125 + '">pyTivo Web Configuration</a><br>'\
126 + '<a href="/TiVoConnect?Command=NPL&Container=' + quote(section
)\
127 + '">pyTivo ToGo</a><br>'
129 t
.admin
= '<br><b>No Admin plugin installed in pyTivo.conf</b><br> If you wish to use'\
130 + ' the admin plugin add the following lines to pyTivo.conf<br><br>'\
131 + '[Admin]<br>type=admin'
133 t
.shares
= 'Video shares:<br/>'
134 for section
, settings
in config
.getShares():
135 if settings
.get('type') == 'video':
136 t
.shares
+= '<a href="TiVoConnect?Command=QueryContainer&Container=' + quote(section
)\
137 + '">' + section
+ '</a><br/>'
142 def unsupported(self
, query
):
143 if hack83
and 'Command' in query
and 'Filter' in query
:
144 logger
= logging
.getLogger('pyTivo.hack83')
146 logger
.debug('Unsupported request checking to see if it is video.')
147 command
= query
['Command'][0]
148 plugin
= GetPlugin('video')
149 if ''.join(query
['Filter']).find('video') >= 0 and \
150 hasattr(plugin
, command
):
151 logger
.debug('Unsupported request yup it is video send to video plugin for it to sort out.')
152 method
= getattr(plugin
, command
)
156 self
.send_response(404)
157 self
.send_header('Content-type', 'text/html')
159 t
= Template(file=os
.path
.join(SCRIPTDIR
, 'templates',
164 if __name__
== '__main__':
166 httpd
= TivoHTTPServer(('', 9032), TivoHTTPHandler
)
167 httpd
.add_container('test', 'x-container/tivo-videos',
168 r
'C:\Documents and Settings\Armooo\Desktop\pyTivo\test')
169 httpd
.serve_forever()