9 from Cheetah
.Filters
import Filter
10 from lrucache
import LRUCache
12 if os
.path
.sep
== '/':
14 unquote
= urllib
.unquote_plus
16 quote
= lambda x
: urllib
.quote(x
.replace(os
.path
.sep
, '/'))
17 unquote
= lambda x
: os
.path
.normpath(urllib
.unquote_plus(x
))
20 CONTENT_TYPE
= 'text/html'
24 module_name
= '.'.join(['plugins', name
, name
])
25 module
= __import__(module_name
, globals(), locals(), name
)
26 plugin
= getattr(module
, module
.CLASS_NAME
)()
29 print 'Error no', name
, 'plugin exists. Check the type ' \
30 'setting for your share.'
33 class EncodeUnicode(Filter
):
34 def filter(self
, val
, **kw
):
35 """Encode Unicode strings, by default in UTF-8"""
37 encoding
= kw
.get('encoding', 'utf8')
41 val
= val
.decode('utf8')
43 if sys
.platform
== 'darwin':
44 val
= val
.decode('macroman')
46 val
= val
.decode('iso8859-1')
47 elif type(val
) != unicode:
49 return val
.encode(encoding
)
53 random_lock
= threading
.Lock()
57 recurse_cache
= LRUCache(5)
58 dir_cache
= LRUCache(10)
60 def __new__(cls
, *args
, **kwds
):
61 it
= cls
.__dict
__.get('__it__')
64 cls
.__it
__ = it
= object.__new
__(cls
)
65 it
.init(*args
, **kwds
)
71 def send_file(self
, handler
, path
, query
):
72 handler
.send_response(200)
74 f
= open(unicode(path
, 'utf-8'), 'rb')
75 shutil
.copyfileobj(f
, handler
.wfile
)
78 def get_local_base_path(self
, handler
, query
):
80 subcname
= query
['Container'][0]
81 container
= handler
.server
.containers
[subcname
.split('/')[0]]
83 return os
.path
.normpath(container
['path'])
85 def get_local_path(self
, handler
, query
):
87 subcname
= query
['Container'][0]
88 container
= handler
.server
.containers
[subcname
.split('/')[0]]
90 path
= os
.path
.normpath(container
['path'])
91 for folder
in subcname
.split('/')[1:]:
94 path
= os
.path
.join(path
, folder
)
97 def item_count(self
, handler
, query
, cname
, files
, last_start
=0):
98 """Return only the desired portion of the list, as specified by
99 ItemCount, AnchorItem and AnchorOffset. 'files' is either a
100 list of strings, OR a list of objects with a 'name' attribute.
102 def no_anchor(handler
, anchor
):
103 handler
.server
.logger
.warning('Anchor not found: ' + anchor
)
105 totalFiles
= len(files
)
108 if totalFiles
and 'ItemCount' in query
:
109 count
= int(query
['ItemCount'][0])
111 if 'AnchorItem' in query
:
112 bs
= '/TiVoConnect?Command=QueryContainer&Container='
113 local_base_path
= self
.get_local_base_path(handler
, query
)
115 anchor
= query
['AnchorItem'][0]
116 if anchor
.startswith(bs
):
117 anchor
= anchor
.replace(bs
, '/', 1)
118 anchor
= unquote(anchor
)
119 anchor
= anchor
.replace(os
.path
.sep
+ cname
, local_base_path
, 1)
120 if not '://' in anchor
:
121 anchor
= os
.path
.normpath(anchor
)
123 if type(files
[0]) == str:
126 filenames
= [x
.name
for x
in files
]
128 index
= filenames
.index(anchor
, last_start
)
132 index
= filenames
.index(anchor
, 0, last_start
)
134 no_anchor(handler
, anchor
)
136 no_anchor(handler
, anchor
) # just use index = 0
141 if 'AnchorOffset' in query
:
142 index
+= int(query
['AnchorOffset'][0])
145 index
= (index
+ count
) % len(files
)
147 files
= files
[index
:index
+ count
]
149 return files
, totalFiles
, index
151 def get_files(self
, handler
, query
, filterFunction
=None, force_alpha
=False):
154 def __init__(self
, name
, isdir
):
157 st
= os
.stat(unicode(name
, 'utf-8'))
158 self
.mdate
= int(st
.st_mtime
)
159 self
.size
= st
.st_size
162 def __init__(self
, files
):
168 def build_recursive_list(path
, recurse
=True):
170 path
= unicode(path
, 'utf-8')
172 for f
in os
.listdir(path
):
173 if f
.startswith('.'):
175 f
= os
.path
.join(path
, f
)
176 isdir
= os
.path
.isdir(f
)
177 f
= f
.encode('utf-8')
178 if recurse
and isdir
:
179 files
.extend(build_recursive_list(f
))
181 if not filterFunction
or filterFunction(f
, file_type
):
182 files
.append(FileData(f
, isdir
))
187 subcname
= query
['Container'][0]
188 cname
= subcname
.split('/')[0]
189 path
= self
.get_local_path(handler
, query
)
191 file_type
= query
.get('Filter', [''])[0]
193 recurse
= query
.get('Recurse', ['No'])[0] == 'Yes'
196 rc
= self
.recurse_cache
199 if path
in rc
and rc
.mtime(path
) + 300 >= time
.time():
202 updated
= os
.stat(unicode(path
, 'utf-8'))[8]
203 if path
in dc
and dc
.mtime(path
) >= updated
:
206 if path
.startswith(p
) and rc
.mtime(p
) < updated
:
210 filelist
= SortList(build_recursive_list(path
, recurse
))
218 if x
.isdir
== y
.isdir
:
219 return name_sort(x
, y
)
221 return y
.isdir
- x
.isdir
224 return cmp(x
.name
, y
.name
)
227 return cmp(y
.mdate
, x
.mdate
)
229 sortby
= query
.get('SortOrder', ['Normal'])[0]
230 if filelist
.unsorted
or filelist
.sortby
!= sortby
:
232 filelist
.files
.sort(dir_sort
)
233 elif sortby
== '!CaptureDate':
234 filelist
.files
.sort(date_sort
)
236 filelist
.files
.sort(name_sort
)
238 filelist
.sortby
= sortby
239 filelist
.unsorted
= False
241 files
= filelist
.files
[:]
244 files
, total
, start
= self
.item_count(handler
, query
, cname
, files
,
247 filelist
.last_start
= start
248 return files
, total
, start