From eec0125ef10dee571bfcb7caa06a604a77993e2f Mon Sep 17 00:00:00 2001 From: Eric von Bayer Date: Mon, 5 Oct 2009 18:04:31 -0700 Subject: [PATCH] Generalized webserver functionality to allow serving http://:/plugin//content/ --- httpserver.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- plugin.py | 8 ++++++++ pyTivo.conf.dist | 22 +++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) mode change 100644 => 100755 httpserver.py mode change 100644 => 100755 pyTivo.conf.dist diff --git a/httpserver.py b/httpserver.py old mode 100644 new mode 100755 index a42a3e6..9df6cc4 --- a/httpserver.py +++ b/httpserver.py @@ -6,12 +6,14 @@ import os import re import socket import time +import mimetypes + from urllib import unquote_plus, quote from xml.sax.saxutils import escape from Cheetah.Template import Template import config -from plugin import GetPlugin, EncodeUnicode +from plugin import GetPlugin, GetPluginPath, EncodeUnicode SCRIPTDIR = os.path.dirname(__file__) @@ -20,6 +22,8 @@ VIDEO_FORMATS = """ video/x-tivo-mpeg """ +RE_PLUGIN_CONTENT = re.compile( r"/plugin/([^/]+)/content/(.+)" ) + class TivoHTTPServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): containers = {} @@ -78,8 +82,60 @@ class TivoHTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler): path = self.path query = {} + regm = RE_PLUGIN_CONTENT.match( path ) + if path == '/TiVoConnect': self.handle_query(query, tsn) + + # Handle general plugin content requests of the form + # /plugin//content/ + elif regm != None: + try: + # Protect ourself from path exploits + file_bits = regm.group(2).split( "/" ) + for bit in file_bits: + if bit == "..": + raise + + # Get the plugin path + plugin_path = GetPluginPath( regm.group(1) ) + + # Build up the actual path based on the plugin path + filen = os.path.join( plugin_path, "content", *file_bits ) + + # If it's not a file, then just error out + if not os.path.isfile( filen ): + raise + + # Read in the full file + handle = open( filen, "rb" ) + try: + text = handle.read() + handle.close() + except: + handle.close() + raise + + # Send the header + self.send_response(200) + self.send_header( "Content-type", \ + mimetypes.guess_type( filen ) ) + self.send_header( "Content-length", \ + os.path.getsize( filen ) ) + self.end_headers() + + # Send the body of the file + self.wfile.write( text ) + self.wfile.flush() + return + + except: + self.send_response(404) + self.end_headers() + self.wfile.write( "File not found" ) + self.wfile.flush() + return + else: ## Get File path = unquote_plus(path) diff --git a/plugin.py b/plugin.py index 5ea070d..d86e831 100644 --- a/plugin.py +++ b/plugin.py @@ -30,6 +30,14 @@ def GetPlugin(name): 'setting for your share.' return Error +def GetPluginPath(name): + try: + module_name = '.'.join(['plugins', name, name]) + module = __import__(module_name, globals(), locals(), name) + return getattr(module, 'SCRIPTDIR') + except ImportError: + return None + class EncodeUnicode(Filter): def filter(self, val, **kw): """Encode Unicode strings, by default in UTF-8""" diff --git a/pyTivo.conf.dist b/pyTivo.conf.dist old mode 100644 new mode 100755 index 6314018..5b1d916 --- a/pyTivo.conf.dist +++ b/pyTivo.conf.dist @@ -46,6 +46,14 @@ ffmpeg=/usr/bin/ffmpeg #height=1080 #ffmpeg_tmpl=%(video_codec)s %(video_fps)s %(video_br)s %(max_video_br)s %(buff_size)s %(aspect_ratio)s %(audio_br)s %(audio_fr)s %(audio_ch)s %(audio_codec)s %(ffmpeg_pram)s %(format)s +# Togo settings: +# Set this up if you wish to have TiVo ToGo support. This allows you to +# copy videos from your TiVo via a web page. +# +#tivo_mak= +#togo_path= + + # Per tivo options # section named _tivo_TSN with the tsn in all caps #[_tivo_00000DEADBEEF] @@ -80,3 +88,17 @@ path=/home/armooo/Videos #[MyTelevision] #type=video #path=d:\television + +# A sample DVD Video Share: +# Meta-data is read out of a details.txt placed in the directory that contains +# VIDEO_TS (this is only needed if you want descriptions, actors, etc). It +# pretends the folder that contains a VIDEO_TS is the name of the movie, it +# makes episode names for all the titles over 10s underneath of it. Only type +# and path parameters are required. +# +#[DVDs] +#type=dvdvideo +#path= +#fast_index=false +#title_min=10.0 +#force_alpha=false -- 2.11.4.GIT