1 import os
, shutil
, random
, threading
, urllib
2 from urlparse
import urlparse
6 unquote
= urllib
.unquote_plus
8 quote
= lambda x
: urllib
.quote(x
.replace(os
.path
.sep
, '/'))
9 unquote
= lambda x
: urllib
.unquote_plus(x
).replace('/', os
.path
.sep
)
12 CONTENT_TYPE
= 'text/html'
15 module_name
= '.'.join(['plugins', name
, name
])
16 module
= __import__(module_name
, globals(), locals(), name
)
17 plugin
= getattr(module
, module
.CLASS_NAME
)()
20 # print 'Error no', name, 'plugin exists. Check the type ' \
21 # 'setting for your share.'
26 random_lock
= threading
.Lock()
30 def __new__(cls
, *args
, **kwds
):
31 it
= cls
.__dict
__.get('__it__')
34 cls
.__it
__ = it
= object.__new
__(cls
)
35 it
.init(*args
, **kwds
)
41 def send_file(self
, handler
, container
, name
):
42 o
= urlparse("http://fake.host" + handler
.path
)
44 handler
.send_response(200)
46 f
= file(container
['path'] + path
[len(name
) + 1:], 'rb')
47 shutil
.copyfileobj(f
, handler
.wfile
)
49 def get_local_base_path(self
, handler
, query
):
51 subcname
= query
['Container'][0]
52 container
= handler
.server
.containers
[subcname
.split('/')[0]]
54 return os
.path
.normpath(container
['path'])
56 def get_local_path(self
, handler
, query
):
58 subcname
= query
['Container'][0]
59 container
= handler
.server
.containers
[subcname
.split('/')[0]]
61 path
= os
.path
.normpath(container
['path'])
62 for folder
in subcname
.split('/')[1:]:
65 path
= os
.path
.join(path
, folder
)
68 def item_count(self
, handler
, query
, cname
, files
, last_start
=0):
69 """Return only the desired portion of the list, as specified by
70 ItemCount, AnchorItem and AnchorOffset. 'files' is either a
71 list of strings, OR a list of objects with a 'name' attribute.
73 totalFiles
= len(files
)
76 if totalFiles
and query
.has_key('ItemCount'):
77 count
= int(query
['ItemCount'][0])
79 if query
.has_key('AnchorItem'):
80 bs
= '/TiVoConnect?Command=QueryContainer&Container='
81 local_base_path
= self
.get_local_base_path(handler
, query
)
83 anchor
= query
['AnchorItem'][0]
84 if anchor
.startswith(bs
):
85 anchor
= anchor
.replace(bs
, '/', 1)
86 anchor
= unquote(anchor
)
87 anchor
= anchor
.replace(os
.path
.sep
+ cname
, local_base_path
, 1)
88 if not '://' in anchor
:
89 anchor
= os
.path
.normpath(anchor
)
91 if type(files
[0]) == str:
94 filenames
= [x
.name
for x
in files
]
96 index
= filenames
.index(anchor
, last_start
)
100 index
= filenames
.index(anchor
, 0, last_start
)
102 print 'Anchor not found:', anchor
104 print 'Anchor not found:', anchor
# just use index = 0
109 if query
.has_key('AnchorOffset'):
110 index
+= int(query
['AnchorOffset'][0])
114 files
= files
[index
:index
+ count
]
117 if index
+ count
< 0:
119 files
= files
[index
+ count
:index
]
122 else: # No AnchorItem
125 files
= files
[:count
]
127 index
= count
% len(files
)
128 files
= files
[count
:]
130 return files
, totalFiles
, index
132 def get_files(self
, handler
, query
, filterFunction
=None):
134 def build_recursive_list(path
, recurse
=True):
137 for file in os
.listdir(path
):
138 if file.startswith('.'):
140 file = os
.path
.join(path
, file)
141 if recurse
and os
.path
.isdir(file):
142 files
.extend(build_recursive_list(file))
144 if not filterFunction
or filterFunction(file, file_type
):
150 subcname
= query
['Container'][0]
151 cname
= subcname
.split('/')[0]
152 path
= self
.get_local_path(handler
, query
)
154 file_type
= query
.get('Filter', [''])[0]
156 recurse
= query
.get('Recurse',['No'])[0] == 'Yes'
157 files
= build_recursive_list(path
, recurse
)
159 totalFiles
= len(files
)
162 xdir
= os
.path
.isdir(os
.path
.join(path
, x
))
163 ydir
= os
.path
.isdir(os
.path
.join(path
, y
))
166 return name_sort(x
, y
)
173 if query
.get('SortOrder',['Normal'])[0] == 'Random':
174 seed
= query
.get('RandomSeed', ['1'])[0]
175 self
.random_lock
.acquire()
177 random
.shuffle(files
)
178 self
.random_lock
.release()
183 return self
.item_count(handler
, query
, cname
, files
)