root/plugin.py

Revision a1c35312398cd2c714b53f8f2555fdb852ccb408, 6.0 kB (checked in by Jason Michalski <armooo@armooo.net>, 5 months ago)

Adding back in failed plugin errors

  • Property mode set to 100644
Line 
1 import os, shutil, random, threading, urllib
2 from urlparse import urlparse
3
4 if os.path.sep == '/':
5     quote = urllib.quote
6     unquote = urllib.unquote_plus
7 else:
8     quote = lambda x: urllib.quote(x.replace(os.path.sep, '/'))
9     unquote = lambda x: urllib.unquote_plus(x).replace('/', os.path.sep)
10
11 class Error:
12     CONTENT_TYPE = 'text/html'
13
14 def GetPlugin(name):
15     try:
16         module_name = '.'.join(['plugins', name, name])
17         module = __import__(module_name, globals(), locals(), name)
18         plugin = getattr(module, module.CLASS_NAME)()
19         return plugin
20     except ImportError:
21         print 'Error no', name, 'plugin exists. Check the type ' \
22         'setting for your share.'
23         return Error
24
25 class Plugin(object):
26
27     random_lock = threading.Lock()
28
29     CONTENT_TYPE = ''
30
31     def __new__(cls, *args, **kwds):
32         it = cls.__dict__.get('__it__')
33         if it is not None:
34             return it
35         cls.__it__ = it = object.__new__(cls)
36         it.init(*args, **kwds)
37         return it
38
39     def init(self):
40         pass
41
42     def send_file(self, handler, container, name):
43         o = urlparse("http://fake.host" + handler.path)
44         path = unquote(o[2])
45         handler.send_response(200)
46         handler.end_headers()
47         f = file(container['path'] + path[len(name) + 1:], 'rb')
48         shutil.copyfileobj(f, handler.wfile)
49
50     def get_local_base_path(self, handler, query):
51
52         subcname = query['Container'][0]
53         container = handler.server.containers[subcname.split('/')[0]]
54
55         return os.path.normpath(container['path'])
56
57     def get_local_path(self, handler, query):
58
59         subcname = query['Container'][0]
60         container = handler.server.containers[subcname.split('/')[0]]
61
62         path = os.path.normpath(container['path'])
63         for folder in subcname.split('/')[1:]:
64             if folder == '..':
65                 return False
66             path = os.path.join(path, folder)
67         return path
68
69     def item_count(self, handler, query, cname, files, last_start=0):
70         """Return only the desired portion of the list, as specified by
71            ItemCount, AnchorItem and AnchorOffset. 'files' is either a
72            list of strings, OR a list of objects with a 'name' attribute.
73         """
74         totalFiles = len(files)
75         index = 0
76
77         if totalFiles and query.has_key('ItemCount'):
78             count = int(query['ItemCount'][0])
79
80             if query.has_key('AnchorItem'):
81                 bs = '/TiVoConnect?Command=QueryContainer&Container='
82                 local_base_path = self.get_local_base_path(handler, query)
83
84                 anchor = query['AnchorItem'][0]
85                 if anchor.startswith(bs):
86                     anchor = anchor.replace(bs, '/', 1)
87                 anchor = unquote(anchor)
88                 anchor = anchor.replace(os.path.sep + cname, local_base_path, 1)
89                 if not '://' in anchor:
90                     anchor = os.path.normpath(anchor)
91
92                 if type(files[0]) == str:
93                     filenames = files
94                 else:
95                     filenames = [x.name for x in files]
96                 try:
97                     index = filenames.index(anchor, last_start)
98                 except ValueError:
99                     if last_start:
100                         try:
101                             index = filenames.index(anchor, 0, last_start)
102                         except ValueError:
103                             print 'Anchor not found:', anchor
104                     else:
105                         print 'Anchor not found:', anchor  # just use index = 0
106
107                 if count > 0:
108                     index += 1
109
110                 if query.has_key('AnchorOffset'):
111                     index += int(query['AnchorOffset'][0])
112
113                 #foward count
114                 if count >= 0:
115                     files = files[index:index + count]
116                 #backwards count
117                 else:
118                     if index + count < 0:
119                         count = -index
120                     files = files[index + count:index]
121                     index += count
122
123             else# No AnchorItem
124
125                 if count >= 0:
126                     files = files[:count]
127                 else:
128                     index = count % len(files)
129                     files = files[count:]
130
131         return files, totalFiles, index
132
133     def get_files(self, handler, query, filterFunction=None):
134
135         def build_recursive_list(path, recurse=True):
136             files = []
137             try:
138                 for file in os.listdir(path):
139                     if file.startswith('.'):
140                         continue
141                     file = os.path.join(path, file)
142                     if recurse and os.path.isdir(file):
143                         files.extend(build_recursive_list(file))
144                     else:
145                        if not filterFunction or filterFunction(file, file_type):
146                            files.append(file)
147             except:
148                 pass
149             return files
150
151         subcname = query['Container'][0]
152         cname = subcname.split('/')[0]
153         path = self.get_local_path(handler, query)
154
155         file_type = query.get('Filter', [''])[0]
156
157         recurse = query.get('Recurse',['No'])[0] == 'Yes'
158         files = build_recursive_list(path, recurse)
159
160         totalFiles = len(files)
161
162         def dir_sort(x, y):
163             xdir = os.path.isdir(os.path.join(path, x))
164             ydir = os.path.isdir(os.path.join(path, y))
165
166             if xdir == ydir:
167                 return name_sort(x, y)
168             else:
169                 return ydir - xdir
170
171         def name_sort(x, y):
172             return cmp(x, y)
173
174         if query.get('SortOrder',['Normal'])[0] == 'Random':
175             seed = query.get('RandomSeed', ['1'])[0]
176             self.random_lock.acquire()
177             random.seed(seed)
178             random.shuffle(files)
179             self.random_lock.release()
180         else:
181             files.sort(dir_sort)
182
183         # Trim the list
184         return self.item_count(handler, query, cname, files)
Note: See TracBrowser for help on using the browser.