8 from cgi
import parse_qs
9 from urllib
import unquote_plus
, quote
, unquote
10 from urlparse
import urlparse
11 from xml
.sax
.saxutils
import escape
13 from Cheetah
.Template
import Template
15 from plugin
import GetPlugin
17 SCRIPTDIR
= os
.path
.dirname(__file__
)
19 class TivoHTTPServer(SocketServer
.ThreadingMixIn
, BaseHTTPServer
.HTTPServer
):
22 def __init__(self
, server_address
, RequestHandlerClass
):
23 BaseHTTPServer
.HTTPServer
.__init
__(self
, server_address
,
25 self
.daemon_threads
= True
27 def add_container(self
, name
, settings
):
28 if self
.containers
.has_key(name
) or name
== 'TiVoConnect':
29 raise "Container Name in use"
31 settings
['content_type'] = GetPlugin(settings
['type']).CONTENT_TYPE
32 self
.containers
[name
] = settings
34 print 'Unable to add container', name
37 self
.containers
.clear()
38 for section
, settings
in config
.getShares():
39 self
.add_container(section
, settings
)
41 def set_beacon(self
, beacon
):
44 class TivoHTTPHandler(BaseHTTPServer
.BaseHTTPRequestHandler
):
48 def address_string(self
):
49 host
, port
= self
.client_address
[:2]
53 tsn
= self
.headers
.getheader('TiVo_TCD_ID',
54 self
.headers
.getheader('tsn', ''))
56 ip
= self
.address_string()
59 if not tsn
in self
.tivo_names
:
60 self
.tivo_names
[tsn
] = self
.server
.beacon
.get_name(ip
)
62 basepath
= unquote_plus(self
.path
).split('/')[1]
65 for name
, container
in self
.server
.containers
.items():
67 plugin
= GetPlugin(container
['type'])
68 plugin
.send_file(self
, container
, name
)
71 ## Not a file not a TiVo command fuck them
72 if not self
.path
.startswith('/TiVoConnect'):
76 o
= urlparse("http://fake.host" + self
.path
)
77 query
= parse_qs(o
[4])
80 if query
.has_key('Command') and len(query
['Command']) >= 1:
82 command
= query
['Command'][0]
84 # If we are looking at the root container
85 if (command
== "QueryContainer" and
86 (not query
.has_key('Container') or
87 query
['Container'][0] == '/')):
91 if query
.has_key('Container'):
92 # Dispatch to the container plugin
93 basepath
= unquote(query
['Container'][0].split('/')[0])
94 for name
, container
in self
.server
.containers
.items():
96 plugin
= GetPlugin(container
['type'])
97 if hasattr(plugin
, command
):
98 method
= getattr(plugin
, command
)
104 # If we made it here it means we couldn't match the request to
106 self
.unsupported(query
)
108 def root_container(self
):
109 tsn
= self
.headers
.getheader('TiVo_TCD_ID', '')
110 tsnshares
= config
.getShares(tsn
)
112 for section
, settings
in tsnshares
:
114 settings
['content_type'] = \
115 GetPlugin(settings
['type']).CONTENT_TYPE
116 tsncontainers
[section
] = settings
117 except Exception, msg
:
118 print section
, '-', msg
119 t
= Template(file=os
.path
.join(SCRIPTDIR
, 'templates',
120 'root_container.tmpl'))
121 t
.containers
= tsncontainers
122 t
.hostname
= socket
.gethostname()
125 self
.send_response(200)
130 self
.send_response(200)
131 self
.send_header('Content-type', 'text/html')
133 t
= Template(file=os
.path
.join(SCRIPTDIR
, 'templates',
136 for section
, settings
in config
.getShares():
137 if 'type' in settings
and settings
['type'] == 'admin':
138 t
.admin
+= ('<a href="/TiVoConnect?Command=Admin&Container=' +
140 '">pyTivo Web Configuration</a><br>' +
141 '<a href="/TiVoConnect?Command=NPL&Container=' +
142 quote(section
) + '">pyTivo ToGo</a><br>')
144 t
.admin
= ('<br><b>No Admin plugin installed in pyTivo.conf</b>' +
145 '<br> If you wish to use the admin plugin add the ' +
146 'following lines to pyTivo.conf<br><br>' +
147 '[Admin]<br>type=admin')
149 t
.shares
= 'Video shares:<br/>'
150 for section
, settings
in config
.getShares():
151 if settings
.get('type') == 'video':
152 t
.shares
+= ('<a href="TiVoConnect?Command=QueryContainer&' +
153 'Container=' + quote(section
) + '">' + section
+
158 def unsupported(self
, query
):
159 self
.send_response(404)
160 self
.send_header('Content-type', 'text/html')
162 t
= Template(file=os
.path
.join(SCRIPTDIR
, 'templates',
167 if __name__
== '__main__':
169 httpd
= TivoHTTPServer(('', 9032), TivoHTTPHandler
)
170 httpd
.add_container('test', 'x-container/tivo-videos',
171 r
'C:\Documents and Settings\Armooo' +
172 r
'\Desktop\pyTivo\test')
173 httpd
.serve_forever()