reconnect fritz.Box also before downloading from uploaded.to without account
[enigma2-plugins.git] / rsdownloader / src / plugin.py
1 ##\r
2 ## RS Downloader\r
3 ## by AliAbdul\r
4 ##\r
5 ##\r
6 from base64 import encodestring\r
7 from Components.ActionMap import ActionMap\r
8 from Components.config import config, ConfigInteger, ConfigText, ConfigYesNo, ConfigClock, ConfigSubsection, getConfigListEntry\r
9 from Components.ConfigList import ConfigListScreen
10 from Components.Console import Console as eConsole\r
11 from Components.Label import Label\r
12 from Components.Language import language\r
13 from Components.MenuList import MenuList\r
14 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest\r
15 from Components.ScrollLabel import ScrollLabel\r
16 from container.decrypt import decrypt\r
17 from enigma import eListboxPythonMultiContent, eTimer, gFont, RT_HALIGN_CENTER, RT_HALIGN_RIGHT\r
18 from os import environ, listdir, remove\r
19 from Plugins.Plugin import PluginDescriptor\r
20 from Screens.ChoiceBox import ChoiceBox
21 from Screens.Console import Console as ConsoleScreen\r
22 from Screens.MessageBox import MessageBox\r
23 from Screens.Screen import Screen\r
24 from Screens.VirtualKeyBoard import VirtualKeyBoard\r
25 from time import localtime, sleep, strftime, time\r
26 from Tools.Directories import fileExists, resolveFilename, SCOPE_SKIN_IMAGE, SCOPE_LANGUAGE, SCOPE_PLUGINS\r
27 from Tools.Downloader import HTTPProgressDownloader\r
28 from Tools.LoadPixmap import LoadPixmap\r
29 from twisted.internet import reactor\r
30 from twisted.python import failure\r
31 from twisted.web.client import getPage
32 from urllib2 import Request\r
33 from urlparse import urlparse, urlunparse
34 from xml.etree.cElementTree import parse\r
35 import gettext, re, socket, urllib, urllib2\r
36 \r
37 ##############################################################################\r
38 \r
39 config.plugins.RSDownloader = ConfigSubsection()\r
40 config.plugins.RSDownloader.onoff = ConfigYesNo(default=True)\r
41 config.plugins.RSDownloader.username = ConfigText(default="", fixed_size=False)\r
42 config.plugins.RSDownloader.password = ConfigText(default="", fixed_size=False)\r
43 config.plugins.RSDownloader.lists_directory = ConfigText(default="/media/hdd/rs/lists/", fixed_size=False)\r
44 config.plugins.RSDownloader.downloads_directory = ConfigText(default="/media/hdd/rs/downloads", fixed_size=False)\r
45 config.plugins.RSDownloader.ignore_time = ConfigYesNo(default=False)\r
46 config.plugins.RSDownloader.start_time = ConfigClock(default=time())\r
47 config.plugins.RSDownloader.end_time = ConfigClock(default=time())\r
48 config.plugins.RSDownloader.download_monday = ConfigYesNo(default=True)\r
49 config.plugins.RSDownloader.download_tuesday = ConfigYesNo(default=True)\r
50 config.plugins.RSDownloader.download_wednesday = ConfigYesNo(default=True)\r
51 config.plugins.RSDownloader.download_thursday = ConfigYesNo(default=True)\r
52 config.plugins.RSDownloader.download_friday = ConfigYesNo(default=True)\r
53 config.plugins.RSDownloader.download_saturday = ConfigYesNo(default=True)\r
54 config.plugins.RSDownloader.download_sunday = ConfigYesNo(default=True)\r
55 config.plugins.RSDownloader.count_downloads = ConfigInteger(default=3, limits=(1, 10))\r
56 config.plugins.RSDownloader.count_maximal_downloads = ConfigInteger(default=40, limits=(1, 1000))\r
57 config.plugins.RSDownloader.write_log = ConfigYesNo(default=True)\r
58 config.plugins.RSDownloader.reconnect_fritz = ConfigYesNo(default=False)\r
59 config.plugins.RSDownloader.autorestart_failed = ConfigYesNo(default=False)\r
60 config.plugins.RSDownloader.mark_small_as_failed = ConfigYesNo(default=True)\r
61 config.plugins.RSDownloader.unrar_password = ConfigText(default="", fixed_size=False)\r
62 config.plugins.RSDownloader.reconnect_start_time = ConfigClock(default=time())\r
63 config.plugins.RSDownloader.reconnect_end_time = ConfigClock(default=time())\r
64 config.plugins.Netload = ConfigSubsection()\r
65 config.plugins.Netload.username = ConfigText(default="", fixed_size=False)\r
66 config.plugins.Netload.password = ConfigText(default="", fixed_size=False)\r
67 config.plugins.Uploaded = ConfigSubsection()\r
68 config.plugins.Uploaded.username = ConfigText(default="", fixed_size=False)\r
69 config.plugins.Uploaded.password = ConfigText(default="", fixed_size=False)\r
70 \r
71 ##############################################################################\r
72 \r
73 def localeInit():\r
74         lang = language.getLanguage()\r
75         environ["LANGUAGE"] = lang[:2]\r
76         gettext.bindtextdomain("enigma2", resolveFilename(SCOPE_LANGUAGE))\r
77         gettext.textdomain("enigma2")\r
78         gettext.bindtextdomain("RSDownloader", "%s%s"%(resolveFilename(SCOPE_PLUGINS), "Extensions/RSDownloader/locale/"))\r
79 \r
80 def _(txt):\r
81         t = gettext.dgettext("RSDownloader", txt)\r
82         if t == txt:\r
83                 t = gettext.gettext(txt)\r
84         return t\r
85 \r
86 localeInit()\r
87 language.addCallback(localeInit)\r
88 \r
89 ##############################################################################\r
90 \r
91 def writeLog(message):\r
92         if config.plugins.RSDownloader.write_log.value:\r
93                 try:\r
94                         f = open("/tmp/rapidshare.log", "a")\r
95                         f.write(strftime("%c", localtime(time())) + " - " + message + "\n")\r
96                         f.close()\r
97                 except:\r
98                         pass\r
99 \r
100 ##############################################################################\r
101 \r
102 def _parse(url):\r
103         url = url.strip()\r
104         parsed = urlparse(url)\r
105         scheme = parsed[0]\r
106         path = urlunparse(('','') + parsed[2:])\r
107         host, port = parsed[1], 80\r
108         if '@' in host:\r
109                 username, host = host.split('@')\r
110                 if ':' in username:\r
111                         username, password = username.split(':')\r
112                 else:\r
113                         password = ""\r
114         else:\r
115                 username = ""\r
116                 password = ""\r
117         if ':' in host:\r
118                 host, port = host.split(':')\r
119                 port = int(port)\r
120         if path == "":\r
121                 path = "/"\r
122         return scheme, host, port, path, username, password\r
123 \r
124 class ProgressDownload:\r
125         def __init__(self, url, outputfile, contextFactory=None, *args, **kwargs):\r
126                 scheme, host, port, path, username, password = _parse(url)\r
127                 if username and password:\r
128                         url = scheme + '://' + host + ':' + str(port) + path\r
129                         basicAuth = encodestring("%s:%s"%(username, password))\r
130                         authHeader = "Basic " + basicAuth.strip()\r
131                         AuthHeaders = {"Authorization": authHeader}\r
132                         if kwargs.has_key("headers"):\r
133                                 kwargs["headers"].update(AuthHeaders)\r
134                         else:\r
135                                 kwargs["headers"] = AuthHeaders\r
136                 self.factory = HTTPProgressDownloader(url, outputfile, *args, **kwargs)\r
137                 self.connection = reactor.connectTCP(host, port, self.factory)\r
138 \r
139         def start(self):\r
140                 return self.factory.deferred\r
141 \r
142         def stop(self):\r
143                 self.connection.disconnect()\r
144 \r
145         def addProgress(self, progress_callback):\r
146                 self.factory.progress_callback = progress_callback\r
147 \r
148 ##############################################################################\r
149 \r
150 def get(url):\r
151         try:\r
152                 data = urllib2.urlopen(url)\r
153                 return data.read()\r
154         except:\r
155                 return ""\r
156    \r
157 def post(url, data):\r
158         try:\r
159                 return urllib2.urlopen(url, data).read()\r
160         except:\r
161                 return ""\r
162 \r
163 def matchGet(rex, string):\r
164         match = re.search(rex, string)\r
165         if match:\r
166                 if len(match.groups()) == 0:\r
167                         return string[match.span()[0]:match.span()[1]]\r
168                 if len(match.groups()) == 1:\r
169                         return match.groups()[0]\r
170         else:\r
171                 return False\r
172 \r
173 ##############################################################################\r
174 \r
175 def reconnect(host='fritz.box', port=49000):\r
176         writeLog("Reconnecting fritz.Box...")\r
177         http_body = '\r\n'.join((\r
178                 '<?xml version="1.0" encoding="utf-8"?>',\r
179                 '<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">',\r
180                 '  <s:Body>',\r
181                 '    <u:ForceTermination xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"/>',\r
182                 '  </s:Body>',\r
183                 '</s:Envelope>'))\r
184         http_data = '\r\n'.join((\r
185                 'POST /upnp/control/WANIPConn1 HTTP/1.1',\r
186                 'Host: %s:%d'%(host, port),\r
187                 'SoapAction: urn:schemas-upnp-org:service:WANIPConnection:1#ForceTermination',\r
188                 'Content-Type: text/xml; charset="utf-8"',\r
189                 'Content-Length: %d'%len(http_body),\r
190                 '',\r
191                 http_body))\r
192         try:\r
193                 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\r
194                 s.connect((host, port))\r
195                 s.send(http_data)\r
196                 s.close()\r
197         except:\r
198                 pass\r
199 \r
200 ##############################################################################
201
202 std_headers = {
203         'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2',
204         'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
205         'Accept': 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
206         'Accept-Language': 'en-us,en;q=0.5',
207 }\r
208 \r
209 class RSDownload:\r
210         def __init__(self, url):\r
211                 writeLog("Adding: %s"%url)\r
212                 self.url = url\r
213                 self.download = None\r
214                 self.downloading = False\r
215                 self.progress = 0\r
216                 self.size = 0\r
217                 self.status = _("Waiting")\r
218                 self.name = self.url.split("/")[-1]\r
219                 self.finishCallbacks = []\r
220 \r
221         def start(self):\r
222                 writeLog("Downloading: %s"%self.url)\r
223                 self.downloading = True\r
224                 self.progress = 0\r
225                 self.size = 0\r
226                 username = config.plugins.RSDownloader.username.value\r
227                 password = config.plugins.RSDownloader.password.value\r
228                 nl_username = config.plugins.Netload.username.value\r
229                 nl_password = config.plugins.Netload.password.value\r
230                 ul_username = config.plugins.Uploaded.username.value\r
231                 ul_password = config.plugins.Uploaded.password.value\r
232                 if self.url.__contains__("rapidshare.com") and username == "" and password == "":\r
233                         writeLog("Free RS-Download: %s"%self.url)\r
234                         self.status = _("Checking")\r
235                         if config.plugins.RSDownloader.reconnect_fritz.value and self.mayReconnect():\r
236                                 reconnect()\r
237                                 sleep(3)\r
238                         data = get(self.url)\r
239                         url = matchGet('<form[^>]+action="([^"]+)', data)\r
240                         if not url:\r
241                                 writeLog("Failed: %s"%self.url)\r
242                                 self.httpFailed(True, "Failed to get download page url: %s"%self.url)\r
243                         else:\r
244                                 data = post(url, "dl.start=Free")\r
245                                 seconds = matchGet('var c=([0-9]+)', data)\r
246                                 if not seconds:\r
247                                         self.httpFailed(True, "Failed to get download page url: %s"%self.url)\r
248                                 else:\r
249                                         writeLog("Free RS-Download... must wait %s seconds: %s"%(seconds, self.url))\r
250                                         self.status = "%s %s"%(_("Waiting"), seconds)\r
251                                         url = matchGet('"dlf" action="([^"]+)', data)\r
252                                         if not url:\r
253                                                 self.httpFailed(True, "Failed to get download page url: %s"%self.url)\r
254                                         else:\r
255                                                 self.freeDownloadUrl = url\r
256                                                 self.freeDownloadTimer = eTimer()\r
257                                                 self.freeDownloadTimer.callback.append(self.freeDownloadStart)\r
258                                                 self.freeDownloadTimer.start((int(seconds) + 2) * 1000, 1)
259                 elif self.url.__contains__("uploaded.to") or self.url.__contains__("ul.to") and ul_username == "" and ul_password == "":
260                         writeLog("Free Uploaded.to-Download: %s"%self.url)\r
261                         self.status = _("Checking")\r
262                         if config.plugins.RSDownloader.reconnect_fritz.value and self.mayReconnect():\r
263                                 reconnect()\r
264                                 sleep(3)\r
265                         data = get(self.url)
266                         tmp = re.search(r"Or wait (\d+) minutes", data)
267                         if tmp:
268                                 minutes = tmp.group(1)
269                                 writeLog("Free Uploaded.to-Download... must wait %s minutes: %s"%(minutes, self.url))
270                                 self.status = "%s %s"%(_("Waiting"), minutes)\r
271                                 self.freeDownloadTimer = eTimer()\r
272                                 self.freeDownloadTimer.callback.append(self.start)\r
273                                 self.freeDownloadTimer.start((int(minutes) + 1) * 60000, 1)
274                         else:
275                                 url = re.search(r".*<form name=\"download_form\" method=\"post\" action=\"(.*)\">", data).group(1)
276                                 self.name = re.search(r"<td><b>\s+(.+)\s", data).group(1) + re.search(r"</td><td>(\..+)</td></tr>", data).group(1)\r
277                                 self.status = _("Downloading")\r
278                                 self.download = ProgressDownload(url, ("%s/%s"%(config.plugins.RSDownloader.downloads_directory.value, self.name)).replace("//", "/"))\r
279                                 self.download.addProgress(self.httpProgress)\r
280                                 self.download.start().addCallback(self.httpFinished).addErrback(self.httpFailed)\r
281                 elif self.url.__contains__("youtube.com"):\r
282                         writeLog("Getting youtube video link: %s"%self.url)\r
283                         self.status = _("Checking")\r
284                         downloadLink = self.getYoutubeDownloadLink()\r
285                         if downloadLink:\r
286                                 self.status = _("Downloading")\r
287                                 writeLog("Downloading video: %s"%downloadLink)\r
288                                 req = urllib2.Request(downloadLink)\r
289                                 url_handle = urllib2.urlopen(req)\r
290                                 headers = url_handle.info()\r
291                                 if headers.getheader("content-type") == "video/mp4":\r
292                                         ext = "mp4"\r
293                                 else:\r
294                                         ext = "flv"\r
295                                 self.download = ProgressDownload(downloadLink, ("%s/%s.%s"%(config.plugins.RSDownloader.downloads_directory.value, self.name, ext)).replace("//", "/"))\r
296                                 self.download.addProgress(self.httpProgress)\r
297                                 self.download.start().addCallback(self.httpFinished).addErrback(self.httpFailed)\r
298                         else:\r
299                                 self.httpFailed(True, "Failed to get video url: %s"%self.url)\r
300                 else:\r
301                         if self.url.__contains__("rapidshare.com") and username != "" and password != "":\r
302                                 url = self.url.replace("http://", "http://" + username + ":" + password + "@")
303                         elif (self.url.__contains__("uploaded.to") or self.url.__contains__("ul.to")) and ul_username != "" and ul_password != "":
304                                 url = self.url.replace("http://", "http://" + ul_username + ":" + ul_password + "@")
305                         elif self.url.__contains__("netload.in") and nl_username != "" and nl_password != "":
306                                 url = self.url.replace("http://", "http://" + nl_username + ":" + nl_password + "@")\r
307                         else:\r
308                                 url = self.url\r
309                         self.status = _("Downloading")\r
310                         self.download = ProgressDownload(url, ("%s/%s"%(config.plugins.RSDownloader.downloads_directory.value, self.name)).replace("//", "/").replace(".html", ""))\r
311                         self.download.addProgress(self.httpProgress)\r
312                         self.download.start().addCallback(self.httpFinished).addErrback(self.httpFailed)\r
313 \r
314         def freeDownloadStart(self):\r
315                 self.status = _("Downloading")\r
316                 self.download = ProgressDownload(self.freeDownloadUrl, ("%s/%s"%(config.plugins.RSDownloader.downloads_directory.value, self.name)).replace("//", "/").replace(".html", ""))\r
317                 self.download.addProgress(self.httpProgress)\r
318                 self.download.start().addCallback(self.httpFinished).addErrback(self.httpFailed)\r
319 \r
320         def stop(self):\r
321                 self.progress = 0\r
322                 self.downloading = False\r
323                 self.status = _("Waiting")\r
324                 if self.download:\r
325                         writeLog("Stopping download: %s"%self.url)\r
326                         self.download.stop()\r
327 \r
328         def httpProgress(self, recvbytes, totalbytes):\r
329                 if self.size == 0:\r
330                         self.size = int((totalbytes / 1024) / 1024)\r
331                 self.progress = int(100.0 * float(recvbytes) / float(totalbytes))\r
332 \r
333         def httpFinished(self, string=None):\r
334                 if string is not None:\r
335                         writeLog("Failed: %s"%self.url)\r
336                         writeLog("Error: %s"%string)\r
337                 self.status = _("Checking")\r
338                 self.checkTimer = eTimer()\r
339                 self.checkTimer.callback.append(self.doCheckTimer)\r
340                 self.checkTimer.start(10000, 1)\r
341 \r
342         def doCheckTimer(self):\r
343                 if (self.size == 0) or (self.progress < 100) or ((config.plugins.RSDownloader.mark_small_as_failed.value == True) and (self.size < 1)):\r
344                         self.status = _("Failed")\r
345                         if config.plugins.RSDownloader.autorestart_failed.value:\r
346                                 self.restartFailedTimer = eTimer()\r
347                                 self.restartFailedTimer.callback.append(self.restartFailedCheck)\r
348                                 self.restartFailedTimer.start(10000*60, 1)\r
349                 elif self.progress == 100:\r
350                         self.status = _("Finished")
351                         writeLog("Finished: %s"%self.url)\r
352                 self.downloading = False\r
353                 self.execFinishCallbacks()\r
354 \r
355         def restartFailedCheck(self):\r
356                 if self.status == _("Failed"): # check if user didn't restart already\r
357                         self.download = None\r
358                         self.status = _("Waiting")\r
359 \r
360         def execFinishCallbacks(self):\r
361                 for x in self.finishCallbacks:\r
362                         x()\r
363 \r
364         def httpFailed(self, failure=None, error=""):\r
365                 if failure:\r
366                         if error == "":\r
367                                 error = failure.getErrorMessage()\r
368                         if error != "" and not error.startswith("[Errno 2]"):\r
369                                 writeLog("Failed: %s"%self.url)\r
370                                 writeLog("Error: %s"%error)\r
371                                 self.status = _("Checking")\r
372                 self.checkTimer = eTimer()\r
373                 self.checkTimer.callback.append(self.doCheckTimer)\r
374                 self.checkTimer.start(10000, 1)
375
376         def getTubeId(self):
377                 url = self.url
378                 if url.__contains__("&feature="):
379                         idx = url.index("&feature=")
380                         url = url[:idx]
381                 split = url.split("=")
382                 ret = split.pop()
383                 if ret == 'youtube_gdata':
384                         tmpval = split.pop()
385                         if tmpval.endswith("&feature"):
386                                 tmp = tmpval.split("&")
387                                 ret = tmp.pop(0)
388                 return ret\r
389 \r
390         def getYoutubeDownloadLink(self):
391                 html = get(self.url)\r
392                 if html != "":\r
393                         reonecat = re.compile(r'<title>(.+?)</title>', re.DOTALL)\r
394                         titles = reonecat.findall(html)\r
395                         if titles:\r
396                                 self.name = titles[0]
397                                 if self.name.__contains__("\t- "):\r
398                                         idx = self.name.index("\t- ")\r
399                                         self.name = (self.name[idx+3:]).replace("&amp;", "&").replace("\t", "").replace("\n", "")
400                 mrl = None
401                 isHDAvailable = False
402                 video_id = str(self.getTubeId())
403                 watch_url = "http://www.youtube.com/watch?v="+video_id
404                 watchrequest = Request(watch_url, None, std_headers)
405                 try:
406                         watchvideopage = urllib2.urlopen(watchrequest).read()
407                 except:
408                         watchvideopage = ""
409                 if "isHDAvailable = true" in watchvideopage:
410                         isHDAvailable = True
411                 info_url = 'http://www.youtube.com/get_video_info?&video_id=%s&el=detailpage&ps=default&eurl=&gl=US&hl=en'%video_id
412                 inforequest = Request(info_url, None, std_headers)
413                 try:
414                         infopage = urllib2.urlopen(inforequest).read()
415                 except:
416                         infopage = ""
417                 mobj = re.search(r'(?m)&token=([^&]+)(?:&|$)', infopage)
418                 if mobj:
419                         token = urllib.unquote(mobj.group(1))
420                         myurl = 'http://www.youtube.com/get_video?video_id=%s&t=%s&eurl=&el=detailpage&ps=default&gl=US&hl=en'%(video_id, token)
421                         if isHDAvailable is True:
422                                 mrl = '%s&fmt=%s'%(myurl, '22')
423                         else:
424                                 mrl = '%s&fmt=%s'%(myurl, '18')\r
425                 return mrl\r
426 \r
427 ##############################################################################\r
428 \r
429 class RS:\r
430         def __init__(self):\r
431                 self.downloads = []\r
432                 self.checkTimer = eTimer()\r
433                 self.checkTimer.callback.append(self.startDownloading)\r
434                 self.checkTimer.start(5000*60, False)
435
436         def mayReconnect(self):
437                 start = config.plugins.RSDownloader.reconnect_start_time.value\r
438                 end = config.plugins.RSDownloader.reconnect_end_time.value
439                 t = localtime()\r
440                 hour_now = t[3]\r
441                 minute_now = t[4]\r
442                 hour_start = start[0]\r
443                 minute_start = start[1]\r
444                 hour_end = end[0]\r
445                 minute_end = end[1]\r
446                 if start == end: # Same start and end-time\r
447                         return True\r
448                 elif hour_end < hour_start: # Different days!!!\r
449                         if hour_now > hour_start or hour_now < hour_end:\r
450                                 return True\r
451                         elif hour_now == hour_start and minute_now > minute_start:\r
452                                 return True\r
453                         elif hour_now == hour_end and minute_now < minute_end:\r
454                                 return True\r
455                         else:\r
456                                 return False\r
457                 elif hour_now > hour_start and hour_now < hour_end: # Same day...\r
458                         return True\r
459                 elif hour_now == hour_start and minute_now > minute_start: # Same day, same start-hour...\r
460                         return True\r
461                 elif hour_now == hour_end and minute_now < minute_end: # Same day, same end-hour...\r
462                         return True\r
463                 else:\r
464                         return False\r
465 \r
466         def mayDownload(self):\r
467                 if config.plugins.RSDownloader.onoff.value == False:\r
468                         writeLog("RS Downloader is turned off...")\r
469                         return False\r
470                 elif config.plugins.RSDownloader.ignore_time.value:\r
471                         return True\r
472                 else:\r
473                         start = config.plugins.RSDownloader.start_time.value\r
474                         end = config.plugins.RSDownloader.end_time.value\r
475                         t = localtime()\r
476                         weekday = t[6]\r
477                         if weekday == 0 and config.plugins.RSDownloader.download_monday.value == False:\r
478                                 return False\r
479                         elif weekday == 1 and config.plugins.RSDownloader.download_tuesday.value == False:\r
480                                 return False\r
481                         elif weekday == 2 and config.plugins.RSDownloader.download_wednesday.value == False:\r
482                                 return False\r
483                         elif weekday == 3 and config.plugins.RSDownloader.download_thursday.value == False:\r
484                                 return False\r
485                         elif weekday == 4 and config.plugins.RSDownloader.download_friday.value == False:\r
486                                 return False\r
487                         elif weekday == 5 and config.plugins.RSDownloader.download_saturday.value == False:\r
488                                 return False\r
489                         elif weekday == 6 and config.plugins.RSDownloader.download_sunday.value == False:\r
490                                 return False\r
491                         else:\r
492                                 hour_now = t[3]\r
493                                 minute_now = t[4]\r
494                                 hour_start = start[0]\r
495                                 minute_start = start[1]\r
496                                 hour_end = end[0]\r
497                                 minute_end = end[1]\r
498                                 if start == end: # Same start and end-time\r
499                                         return True\r
500                                 elif hour_end < hour_start: # Different days!!!\r
501                                         if hour_now > hour_start or hour_now < hour_end:\r
502                                                 return True\r
503                                         elif hour_now == hour_start and minute_now > minute_start:\r
504                                                 return True\r
505                                         elif hour_now == hour_end and minute_now < minute_end:\r
506                                                 return True\r
507                                         else:\r
508                                                 return False\r
509                                 elif hour_now > hour_start and hour_now < hour_end: # Same day...\r
510                                         return True\r
511                                 elif hour_now == hour_start and minute_now > minute_start: # Same day, same start-hour...\r
512                                         return True\r
513                                 elif hour_now == hour_end and minute_now < minute_end: # Same day, same end-hour...\r
514                                         return True\r
515                                 else:\r
516                                         return False\r
517 \r
518         def allDownloadsFinished(self):\r
519                 allDone = True\r
520                 for download in self.downloads:\r
521                         if (download.status != _("Failed")) and (download.status != _("Finished")):\r
522                                 allDone = False
523                                 break\r
524                 return allDone\r
525 \r
526         def startDownloading(self):\r
527                 if self.mayDownload() == True:\r
528                         if self.allDownloadsFinished() == True:\r
529                                 self.readLists()\r
530                         downloadCount = 0\r
531                         for download in self.downloads:\r
532                                 if download.downloading == True:\r
533                                         downloadCount += 1 # Count the downloaded files
534                         # Get next download
535                         download = None\r
536                         for next in self.downloads:\r
537                                 if next.downloading == False and next.status.startswith(_("Waiting")):\r
538                                         download = next\r
539                                         break
540                         if download:
541                                 # Check URL of next download
542                                 onlyOneAllowed = True
543                                 if download.url.__contains__("rapidshare.com"):\r
544                                         if config.plugins.RSDownloader.username.value != "" and config.plugins.RSDownloader.password.value != "":
545                                                 onlyOneAllowed = False
546                                 elif download.url.__contains__("uploaded.to") or download.url.__contains__("ul.to"):\r
547                                         if config.plugins.Uploaded.username.value != "" and config.plugins.Uploaded.password.value != "":
548                                                 onlyOneAllowed = False
549                                 elif download.url.__contains__("netload.in"):\r
550                                         if config.plugins.Netload.username.value != "" and config.plugins.Netload.password.value != "":
551                                                 onlyOneAllowed = False
552                                 if onlyOneAllowed and downloadCount == 0:\r
553                                         download.start() # Start only first download in the list\r
554                                 elif onlyOneAllowed == False:\r
555                                         mayDownloadCount = config.plugins.RSDownloader.count_downloads.value - downloadCount\r
556                                         for download in self.downloads:\r
557                                                 if download.downloading == False:\r
558                                                         if mayDownloadCount > 0 and download.status == _("Waiting"):\r
559                                                                 download.start()\r
560                                                                 mayDownloadCount -= 1\r
561 \r
562         def addDownload(self, url):\r
563                 error = False\r
564                 for download in self.downloads:\r
565                         if download.url == url:\r
566                                 error = True\r
567                 if error:\r
568                         return False\r
569                 else:\r
570                         download = RSDownload(url)\r
571                         download.finishCallbacks.append(self.cleanLists)\r
572                         self.downloads.append(download)\r
573                         return True\r
574 \r
575         def readLists(self):\r
576                 writeLog("Reading all lists...")\r
577                 path = config.plugins.RSDownloader.lists_directory.value\r
578                 if not path.endswith("/"):\r
579                         path = path + "/"\r
580                 writeLog("Directory: " + path)\r
581                 try:\r
582                         file_list = listdir(path)
583                         file_list.sort()\r
584                         writeLog("Count of lists: " + str(len(file_list)))\r
585                 except:\r
586                         file_list = []\r
587                         writeLog("Could not find any list!")
588                 added_downloads = 0\r
589                 for x in file_list:\r
590                         list = path + x\r
591                         if list.endswith(".txt"):\r
592                                 try:\r
593                                         writeLog("Reading list %s..."%list)\r
594                                         f = open(list, "r")\r
595                                         count = 0\r
596                                         for l in f:\r
597                                                 if l.startswith("http://"):
598                                                         if added_downloads < config.plugins.RSDownloader.count_maximal_downloads.value:\r
599                                                                 if (self.addDownload(l.replace("\n", "").replace("\r", ""))) == True:\r
600                                                                         count += 1
601                                                                         added_downloads += 1
602                                                         else:
603                                                                 break\r
604                                         f.close()\r
605                                         if count == 0:\r
606                                                 writeLog("Empty list or downloads already in download list: %s"%list)\r
607                                         else:\r
608                                                 writeLog("Added %d files from list %s..."%(count, list))\r
609                                 except:\r
610                                         writeLog("Error while reading list %s!"%list)\r
611                         else:\r
612                                 writeLog("No *.txt file: %s!"%list)\r
613 \r
614         def cleanLists(self):\r
615                 writeLog("Cleaning lists...")\r
616                 path = config.plugins.RSDownloader.lists_directory.value\r
617                 if not path.endswith("/"):\r
618                         path = path + "/"\r
619                 try:\r
620                         file_list = listdir(path)\r
621                 except:\r
622                         file_list = []
623                 
624                 finished_downloads = []
625                 for download in self.downloads:\r
626                         if download.status == _("Finished"):
627                                 finished_downloads.append(download)\r
628                 for x in file_list:\r
629                         list = path + x
630                         if list.endswith(".txt"):\r
631                                 try:\r
632                                         f = open(list, "r")\r
633                                         content = f.read()\r
634                                         f.close()
635                                         for finished in finished_downloads:\r
636                                                 if content.__contains__(finished.url):\r
637                                                         content = content.replace(finished.url, "")\r
638                                                         content = content.replace("\n\n", "\n").replace("\r\r", "\r")\r
639                                         f = open(list, "w")\r
640                                         f.write(content)\r
641                                         f.close()\r
642                                 except:\r
643                                         writeLog("Error while cleaning list %s!"%list)\r
644                 self.startDownloading()\r
645 \r
646         def removeDownload(self, url):\r
647                 tmp = []\r
648                 for download in self.downloads:\r
649                         if download.url == url:\r
650                                 download.stop()\r
651                         else:\r
652                                 tmp.append(download)\r
653                 del self.downloads\r
654                 self.downloads = tmp\r
655                 self.removeFromLists(url)\r
656 \r
657         def removeFromLists(self, url):\r
658                 path = config.plugins.RSDownloader.lists_directory.value\r
659                 if not path.endswith("/"):\r
660                         path = path + "/"\r
661                 try:\r
662                         file_list = listdir(path)\r
663                 except:\r
664                         file_list = []\r
665                 for x in file_list:\r
666                         list = path + x\r
667                         try:\r
668                                 f = open(list, "r")\r
669                                 content = f.read()\r
670                                 f.close()\r
671                                 if content.__contains__(url):\r
672                                         content = content.replace(url, "")\r
673                                         content = content.replace("\n\n", "\n").replace("\r\r", "\r")\r
674                                 f = open(list, "w")\r
675                                 f.write(content)\r
676                                 f.close()\r
677                         except:\r
678                                 pass\r
679 \r
680         def clearFinishedDownload(self, url):\r
681                 idx = 0\r
682                 for x in self.downloads:\r
683                         if x.url == url:\r
684                                 del self.downloads[idx]\r
685                                 break\r
686                         else:\r
687                                 idx += 1\r
688 \r
689         def clearFinishedDownloads(self):\r
690                 tmp = []\r
691                 for download in self.downloads:\r
692                         if download.status != _("Finished"):\r
693                                 tmp.append(download)\r
694                 del self.downloads\r
695                 self.downloads = tmp\r
696 \r
697         def deleteFailedDownloads(self):\r
698                 tmp = []\r
699                 for download in self.downloads:\r
700                         if download.status == _("Failed"):\r
701                                 self.removeFromLists(download.url)\r
702                         else:\r
703                                 tmp.append(download)\r
704                 del self.downloads\r
705                 self.downloads = tmp
706
707         def abortAllDownloads(self):\r
708                 tmp = []\r
709                 for download in self.downloads:\r
710                         if download.status == _("Downloading"):\r
711                                 download.stop()\r
712                                 download.download = None\r
713                                 download.downloading = False\r
714                                 download.progress = 0\r
715                                 download.size = 0\r
716                                 download.status = _("Waiting")\r
717                         tmp.append(download)\r
718                 del self.downloads\r
719                 self.downloads = tmp\r
720                 self.startDownloading()\r
721 \r
722         def restartFailedDownloads(self):\r
723                 tmp = []\r
724                 for download in self.downloads:\r
725                         if download.status == _("Failed"):\r
726                                 download.download = None\r
727                                 download.downloading = False\r
728                                 download.progress = 0\r
729                                 download.size = 0\r
730                                 download.status = _("Waiting")\r
731                         tmp.append(download)\r
732                 del self.downloads\r
733                 self.downloads = tmp\r
734                 self.startDownloading()\r
735 \r
736 rapidshare = RS()\r
737 \r
738 ##############################################################################\r
739 \r
740 class ChangedScreen(Screen):\r
741         def __init__(self, session, parent=None):\r
742                 Screen.__init__(self, session, parent)\r
743                 self.onLayoutFinish.append(self.setScreenTitle)\r
744 \r
745         def setScreenTitle(self):\r
746                 self.setTitle(_("RS Downloader"))\r
747 \r
748 ##############################################################################\r
749 \r
750 class RSConfig(ConfigListScreen, ChangedScreen):\r
751         skin = """\r
752                 <screen position="center,center" size="560,450" title="RS Downloader">\r
753                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />\r
754                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />\r
755                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />\r
756                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />\r
757                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
758                         <widget name="config" position="0,45" size="560,400" scrollbarMode="showOnDemand" />\r
759                 </screen>"""\r
760 \r
761         def __init__(self, session):\r
762                 ChangedScreen.__init__(self, session)\r
763                 \r
764                 self["key_green"] = Label(_("Save"))\r
765                 \r
766                 ConfigListScreen.__init__(self, [\r
767                         getConfigListEntry(_("Download in the background:"), config.plugins.RSDownloader.onoff),\r
768                         getConfigListEntry(_("Username:"), config.plugins.RSDownloader.username),\r
769                         getConfigListEntry(_("Password:"), config.plugins.RSDownloader.password),\r
770                         getConfigListEntry(_("Username (netload.in):"), config.plugins.Netload.username),\r
771                         getConfigListEntry(_("Password (netload.in):"), config.plugins.Netload.password),\r
772                         getConfigListEntry(_("Username (uploaded.to):"), config.plugins.Uploaded.username),\r
773                         getConfigListEntry(_("Password (uploaded.to):"), config.plugins.Uploaded.password),\r
774                         getConfigListEntry(_("Lists directory:"), config.plugins.RSDownloader.lists_directory),\r
775                         getConfigListEntry(_("Downloads directory:"), config.plugins.RSDownloader.downloads_directory),\r
776                         getConfigListEntry(_("Ignore download times:"), config.plugins.RSDownloader.ignore_time),\r
777                         getConfigListEntry(_("Allow downloading on monday:"), config.plugins.RSDownloader.download_monday),\r
778                         getConfigListEntry(_("Allow downloading on tuesday:"), config.plugins.RSDownloader.download_tuesday),\r
779                         getConfigListEntry(_("Allow downloading on wednesday:"), config.plugins.RSDownloader.download_wednesday),\r
780                         getConfigListEntry(_("Allow downloading on thursday:"), config.plugins.RSDownloader.download_thursday),\r
781                         getConfigListEntry(_("Allow downloading on friday:"), config.plugins.RSDownloader.download_friday),\r
782                         getConfigListEntry(_("Allow downloading on saturday:"), config.plugins.RSDownloader.download_saturday),\r
783                         getConfigListEntry(_("Allow downloading on sunday:"), config.plugins.RSDownloader.download_sunday),\r
784                         getConfigListEntry(_("Don't download before:"), config.plugins.RSDownloader.start_time),\r
785                         getConfigListEntry(_("Don't download after:"), config.plugins.RSDownloader.end_time),\r
786                         getConfigListEntry(_("Maximal downloads:"), config.plugins.RSDownloader.count_downloads),\r
787                         getConfigListEntry(_("Take x downloads to list:"), config.plugins.RSDownloader.count_maximal_downloads),\r
788                         getConfigListEntry(_("Write log:"), config.plugins.RSDownloader.write_log),\r
789                         getConfigListEntry(_("Reconnect fritz.Box before downloading:"), config.plugins.RSDownloader.reconnect_fritz),\r
790                         getConfigListEntry(_("Don't reconnect before:"), config.plugins.RSDownloader.reconnect_start_time),\r
791                         getConfigListEntry(_("Don't reconnect after:"), config.plugins.RSDownloader.reconnect_end_time),\r
792                         getConfigListEntry(_("Restart failed after 10 minutes:"), config.plugins.RSDownloader.autorestart_failed),
793                         getConfigListEntry(_("Mark files < 1 MB as failed:"), config.plugins.RSDownloader.mark_small_as_failed)])\r
794                 \r
795                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"], {"green": self.save, "cancel": self.exit}, -1)\r
796 \r
797         def save(self):\r
798                 for x in self["config"].list:\r
799                         x[1].save()\r
800                 self.close()\r
801 \r
802         def exit(self):\r
803                 for x in self["config"].list:\r
804                         x[1].cancel()\r
805                 self.close()\r
806 \r
807 ##############################################################################\r
808 \r
809 class RSSearch(Screen):\r
810         skin = """\r
811                 <screen position="center,center" size="560,450" title="Searching... please wait!">\r
812                         <widget name="list" position="0,0" size="570,450" scrollbarMode="showOnDemand" />\r
813                 </screen>"""\r
814 \r
815         def __init__(self, session, searchFor):\r
816                 Screen.__init__(self, session)\r
817                 self.session = session\r
818                 \r
819                 self.searchFor = searchFor.replace(" ", "%2B")\r
820                 self.maxPage = 1\r
821                 self.curPage = 1\r
822                 self.files = []\r
823                 \r
824                 self["list"] = MenuList([])\r
825                 \r
826                 self["actions"] = ActionMap(["OkCancelActions", "InfobarChannelSelection"],\r
827                         {\r
828                                 "historyBack": self.previousPage,\r
829                                 "historyNext": self.nextPage,\r
830                                 "ok": self.okClicked,\r
831                                 "cancel": self.close\r
832                         }, -1)\r
833                 \r
834                 self.onLayoutFinish.append(self.search)\r
835 \r
836         def okClicked(self):\r
837                 if len(self.files) > 0:\r
838                         idx = self["list"].getSelectedIndex()\r
839                         url = self.files[idx]\r
840                         try:\r
841                                 f = open(("%s/search.txt" % config.plugins.RSDownloader.lists_directory.value).replace("//", "/"), "a")\r
842                                 f.write("%s\n"%url)\r
843                                 f.close()\r
844                                 self.session.open(MessageBox, (_("Added %s to the download-list.") % url), MessageBox.TYPE_INFO)\r
845                         except:\r
846                                 self.session.open(MessageBox, (_("Error while adding %s to the download-list!") % url), MessageBox.TYPE_ERROR)\r
847 \r
848         def search(self):\r
849                 getPage("http://rapidshare-search-engine.com/index-s_submit=Search&sformval=1&s_type=0&what=1&s=%s&start=%d.html"%(self.searchFor, self.curPage)).addCallback(self.searchCallback).addErrback(self.searchError)\r
850 \r
851         def searchCallback(self, html=""):\r
852                 list = []\r
853                 files = []\r
854                 \r
855                 if html.__contains__("Nothing found, sorry."):\r
856                         self.session.open(MessageBox, (_("Error while searching http://rapidshare-search-engine.com!\n\nError: Nothing found, sorry.")), MessageBox.TYPE_ERROR)\r
857                         self.instance.setTitle(_("Nothing found, sorry."))\r
858                 else:\r
859                         tmp = html\r
860                         while tmp.__contains__("goPg('"):\r
861                                 idx = tmp.index("goPg('")\r
862                                 tmp = tmp[idx+6:]\r
863                                 idx = tmp.index("'")\r
864                                 pageNumber = tmp[:idx]\r
865                                 \r
866                                 try:\r
867                                         pageNumber = int(pageNumber)\r
868                                         if pageNumber > self.maxPage:\r
869                                                 self.maxPage = pageNumber\r
870                                 except:\r
871                                         pass\r
872                                 \r
873                                 self.instance.setTitle(_("Page %d / %d. Push < > to switch the page...")%(self.curPage, self.maxPage))\r
874                         \r
875                         while html.__contains__('title="Download"'):\r
876                                 idx = html.index('title="Download"')\r
877                                 html = html[idx:]\r
878                                 idx = html.index('value="')\r
879                                 html = html[idx+7:]\r
880                                 idx = html.index('"')\r
881                                 size = html[:idx]\r
882                                 idx = html.index('http://rapidshare.com/')\r
883                                 html = html[idx:]\r
884                                 idx = html.index('"')\r
885                                 url = html[:idx]\r
886                                 \r
887                                 files.append(url) \r
888                                 try:\r
889                                         urllist = url.split("/")\r
890                                         idx = len(urllist) - 1\r
891                                         name = urllist[idx]\r
892                                         list.append("%s - %s"%(size, name))\r
893                                 except:\r
894                                         list.append("%s - %s"%(size, url))\r
895                 \r
896                 self.files = files\r
897                 self["list"].setList(list)\r
898 \r
899         def searchError(self, error=""):\r
900                 self.session.open(MessageBox, (_("Error while searching http://rapidshare-search-engine.com!\n\nError: %s")%str(error)), MessageBox.TYPE_ERROR)\r
901 \r
902         def previousPage(self):\r
903                 if self.curPage > 1:\r
904                         self.curPage -= 1\r
905                         self.instance.setTitle(_("Loading previous page... please wait!"))\r
906                         self.search()\r
907 \r
908         def nextPage(self):\r
909                 if self.curPage < self.maxPage:\r
910                         self.curPage += 1\r
911                         self.instance.setTitle(_("Loading next page... please wait!"))\r
912                         self.search()\r
913 \r
914 ##############################################################################\r
915 \r
916 class RSLogScreen(ChangedScreen):\r
917         skin = """\r
918                 <screen position="center,center" size="560,450" title="RS Downloader">\r
919                         <widget name="label" position="0,0" size="560,450" font="Regular;20" />\r
920                 </screen>"""\r
921 \r
922         def __init__(self, session):\r
923                 ChangedScreen.__init__(self, session)\r
924                 \r
925                 try:\r
926                         f = open("/tmp/rapidshare.log")\r
927                         log = f.read()\r
928                         f.close()\r
929                 except:\r
930                         log = ""\r
931                 self["label"] = ScrollLabel(log)\r
932                 \r
933                 self["actions"] = ActionMap(["WizardActions"],\r
934                         {\r
935                                 "ok": self.close,\r
936                                 "back": self.close,\r
937                                 "up": self["label"].pageUp,\r
938                                 "down": self["label"].pageDown,\r
939                                 "left": self["label"].pageUp,\r
940                                 "right": self["label"].pageDown\r
941                         }, -1)\r
942 \r
943 ##############################################################################\r
944 \r
945 class RSContainerSelector(ChangedScreen):\r
946         skin = """\r
947                 <screen position="center,center" size="560,450" title="RS Downloader">\r
948                         <widget name="list" position="0,0" size="560,450" />\r
949                 </screen>"""\r
950 \r
951         def __init__(self, session, list):\r
952                 ChangedScreen.__init__(self, session)\r
953                 self["list"] = MenuList(list)\r
954                 self["actions"] = ActionMap(["OkCancelActions"], {"ok": self.okClicked, "cancel": self.close}, -1)\r
955 \r
956         def okClicked(self):\r
957                 cur = self["list"].getCurrent()\r
958                 self.close(cur)\r
959 \r
960 ##############################################################################
961
962 class UnrarEntry:
963         def __init__(self, name, password, package=None):
964                 self.name = name
965                 self.password = password
966                 self.working = False
967                 self.finishCallback = None
968                 self.console = None
969                 self.command = None
970                 self.package = None
971                 self.list = ("%s/%s"%(config.plugins.RSDownloader.lists_directory.value, self.name)).replace("//", "/")
972                 if package is None:
973                         try:
974                                 f = open(self.list, "r")
975                                 while True:\r
976                                         line = f.readline()\r
977                                         if line == '':\r
978                                                 break
979                                         elif line.startswith("http://") and (line.__contains__("part1.rar") or line.__contains__("part01.rar") or line.__contains__("part001.rar")):
980                                                 package = line.split("/")[-1]
981                                                 package = package.replace("\n", "").replace("\r", "")
982                                                 package = ("%s/%s"%(config.plugins.RSDownloader.downloads_directory.value, package)).replace("//", "/")
983                                                 break
984                                 f.close()
985                         except:
986                                 pass
987                 if package:
988                         self.package = package
989                         if self.password:
990                                 self.command = "unrar -p%s -o+ x %s %s"%(self.password, package, config.plugins.RSDownloader.downloads_directory.value)
991                         else:
992                                 self.command = "unrar -o+ x %s %s"%(package, config.plugins.RSDownloader.downloads_directory.value)
993                 else:
994                         writeLog("Error finding rar-archives in list: %s"%self.name)
995
996         def startUnrar(self):
997                 self.working = True
998                 if not self.console:
999                         self.console = eConsole()
1000                 self.console.ePopen(self.command, self.unrarDataAvailable)
1001
1002         def unrarDataAvailable(self, result, retval, extra_args):
1003                 self.working = False
1004                 try:
1005                         fileName = ("%s/%s_unrar.txt"%(config.plugins.RSDownloader.downloads_directory.value, self.name)).replace("//", "/")
1006                         f = open(fileName, "w")
1007                         f.write(result)
1008                         f.close()
1009                 except:
1010                         print "[RS Downloader] Result of unrar:",result
1011                 self.finishCallback(self.name)
1012
1013         def allDownloaded(self):
1014                 try:
1015                         f = open(self.list, "r")
1016                         content = f.read()
1017                         f.close()
1018                 except:
1019                         content = ""
1020                 if content.__contains__("http://"):
1021                         return False
1022                 else:
1023                         return True
1024
1025 ##############################################################################
1026
1027 class Unrar:
1028         def __init__(self):
1029                 self.list = []
1030                 self.timer = eTimer()
1031                 self.timer.callback.append(self.checkUnrar)
1032                 self.timer.start(30000, 1)
1033                 self.xmlFile = ("%s/unrar.xml"%config.plugins.RSDownloader.lists_directory.value).replace("//", "/")
1034                 
1035         def addToList(self, name, password, package=None):
1036                 entry = UnrarEntry(name, password, package)
1037                 self.list.append(entry)
1038
1039         def deleteEntry(self, name):
1040                 idx = 0
1041                 ret = True
1042                 for x in self.list:
1043                         if x.name == name:
1044                                 if x.working:
1045                                         ret = False
1046                                 else:
1047                                         del self.list[idx]
1048                                         break
1049                         idx += 1
1050                 return ret
1051
1052         def checkUnrar(self):
1053                 if len(self.list) > 0:
1054                         self.startUnrar()
1055                 else:
1056                         self.timer.start(30000, 1)
1057
1058         def isWorking(self):
1059                 ret = False
1060                 for x in self.list:
1061                         if x.working:
1062                                 ret = True
1063                                 break
1064                 return ret
1065
1066         def getFirstEmptyList(self):
1067                 entry = None
1068                 for x in self.list:
1069                         if (x.allDownloaded() == True):
1070                                 entry = x
1071                                 break
1072                 return entry
1073
1074         def startUnrar(self):
1075                 ret = self.isWorking()
1076                 if ret == False:
1077                         entry = self.getFirstEmptyList()
1078                         if entry:
1079                                 if entry.command:
1080                                         writeLog("Start unpacking: %s"%entry.name)
1081                                         entry.finishCallback = self.cleanFinishedEntry
1082                                         entry.startUnrar()
1083                                 else:
1084                                         self.deleteEntry(entry.name)
1085                                         self.timer.start(30000, 1)
1086                         else:
1087                                 self.timer.start(30000, 1)
1088                 else:
1089                         self.timer.start(30000, 1)
1090
1091         def cleanFinishedEntry(self, name):
1092                 writeLog("Unpacking finished: %s"%name)
1093                 self.deleteEntry(name)
1094                 self.checkUnrar()
1095
1096         def decode_charset(self, str, charset):
1097                 try:
1098                         uni = unicode(str, charset, 'strict')
1099                 except:
1100                         uni = str
1101                 return uni
1102
1103         def loadXml(self):
1104                 if fileExists(self.xmlFile):
1105                         menu = parse(self.xmlFile).getroot()
1106                         for item in menu.findall("entry"):
1107                                 name = item.get("name") or None
1108                                 password = item.get("password") or None
1109                                 package = item.get("package") or None
1110                                 if name and password:
1111                                         name = self.decode_charset(name, "utf-8")
1112                                         password = self.decode_charset(password, "utf-8")
1113                                         self.addToList(str(name), str(password), str(package))
1114
1115         def writeXml(self):
1116                 xml = '<unrar>\n'
1117                 for x in self.list:
1118                         name = self.decode_charset(x.name, "utf-8")
1119                         password = self.decode_charset(x.password, "utf-8")
1120                         xml += '\t<entry name="%s" password="%s" package="%s" />\n'%(name.encode("utf-8"), password.encode("utf-8"), x.package)
1121                 xml += '</unrar>\n'
1122                 try:
1123                         f = open(self.xmlFile, "w")
1124                         f.write(xml)
1125                         f.close()
1126                 except:
1127                         writeLog("Error writing unrar xml file: %s"%self.xmlFile)
1128 unrar = Unrar()
1129
1130 ##############################################################################
1131
1132 class UnrarPackageSelector(ChangedScreen):\r
1133         skin = """\r
1134                 <screen position="center,center" size="560,450" title="RS Downloader">\r
1135                         <widget name="list" position="0,0" size="560,450" />\r
1136                 </screen>"""\r
1137 \r
1138         def __init__(self, session):\r
1139                 ChangedScreen.__init__(self, session)
1140                 \r
1141                 self["list"] = MenuList([])
1142                 \r
1143                 self["actions"] = ActionMap(["OkCancelActions"],
1144                         {
1145                                 "ok": self.okClicked,
1146                                 "cancel": self.close
1147                         }, -1)
1148                 
1149                 self.onLayoutFinish.append(self.updateList)
1150
1151         def updateList(self):\r
1152                 try:\r
1153                         names = listdir(config.plugins.RSDownloader.lists_directory.value)\r
1154                 except:\r
1155                         names = []\r
1156                 list = []\r
1157                 for name in names:\r
1158                         if name.lower().endswith(".txt"):
1159                                 added = False
1160                                 for x in unrar.list:
1161                                         if x.name == name:
1162                                                 added = True
1163                                 if added == False:\r
1164                                         list.append(name)\r
1165                 list.sort()
1166                 self["list"].setList(list)\r
1167 \r
1168         def okClicked(self):\r
1169                 cur = self["list"].getCurrent()
1170                 if cur:
1171                         self.name = cur
1172                         self.session.openWithCallback(self.okClickedCallback, VirtualKeyBoard, title=_("Enter unrar password:"), text=config.plugins.RSDownloader.unrar_password.value)
1173
1174         def okClickedCallback(self, callback=None):
1175                 if callback is None:
1176                         callback = ""
1177                 config.plugins.RSDownloader.unrar_password.value = callback
1178                 config.plugins.RSDownloader.unrar_password.save()\r
1179                 self.close([self.name, callback])
1180
1181 ##############################################################################
1182
1183 class UnrarManager(ChangedScreen):\r
1184         skin = """\r
1185                 <screen position="center,center" size="560,450" title="RS Downloader">\r
1186                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />\r
1187                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />\r
1188                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />\r
1189                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />\r
1190                         <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
1191                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
1192                         <widget name="list" position="0,40" size="560,375" scrollbarMode="showNever" />\r
1193                 </screen>"""\r
1194 \r
1195         def __init__(self, session):\r
1196                 ChangedScreen.__init__(self, session)\r
1197                 self.session = session
1198                 \r
1199                 self["key_red"] = Label(_("Delete"))\r
1200                 self["key_green"] = Label(_("Add"))\r
1201                 self["list"] = MenuList([])
1202                 \r
1203                 self["actions"] = ActionMap(["ColorActions", "OkCancelActions"],
1204                         {
1205                                 "red": self.delete,
1206                                 "green": self.add,
1207                                 "cancel": self.close
1208                         }, prio=-1)
1209                 \r
1210                 self.onLayoutFinish.append(self.updateList)
1211
1212         def updateList(self):
1213                 list = []
1214                 for x in unrar.list:
1215                         list.append(x.name)
1216                 list.sort()
1217                 self["list"].setList(list)
1218
1219         def delete(self):
1220                 cur = self["list"].getCurrent()
1221                 if cur:
1222                         ret = unrar.deleteEntry(cur)
1223                         if ret:
1224                                 self.updateList()
1225                         else:
1226                                 self.session.open(MessageBox, _("Unrar is already working!"), MessageBox.TYPE_ERROR)
1227
1228         def add(self):
1229                 self.session.openWithCallback(self.addCallback, UnrarPackageSelector)
1230
1231         def addCallback(self, callback=None):
1232                 if callback:
1233                         unrar.addToList(callback[0], callback[1])
1234                         self.updateList()\r
1235
1236 ##############################################################################
1237 \r
1238 class RSList(MenuList):\r
1239         def __init__(self, list):\r
1240                 MenuList.__init__(self, list, False, eListboxPythonMultiContent)\r
1241                 self.l.setItemHeight(25)\r
1242                 self.l.setFont(0, gFont("Regular", 20))\r
1243 \r
1244 ##############################################################################\r
1245 \r
1246 def RSListEntry(download):\r
1247         res = [(download)]\r
1248         res.append(MultiContentEntryText(pos=(0, 0), size=(170, 25), font=0, text=download.name))\r
1249         res.append(MultiContentEntryText(pos=(175, 0), size=(75, 25), font=0, text="%d%s"%(download.size, "MB"), flags=RT_HALIGN_CENTER))\r
1250         res.append(MultiContentEntryPixmapAlphaTest(pos=(260, 9), size=(84, 7), png=LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/progress_bg.png"))))\r
1251         res.append(MultiContentEntryPixmapAlphaTest(pos=(260, 10), size=(int(0.84 * download.progress), 5), png=LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/progress_small.png"))))\r
1252         res.append(MultiContentEntryText(pos=(360, 0), size=(60, 25), font=0, text="%d%s"%(download.progress, "%"), flags=RT_HALIGN_CENTER))\r
1253         res.append(MultiContentEntryText(pos=(420, 0), size=(140, 25), font=0, text=download.status, flags=RT_HALIGN_RIGHT))\r
1254         return res\r
1255 \r
1256 ##############################################################################\r
1257 \r
1258 class RSMain(ChangedScreen):\r
1259         skin = """\r
1260                 <screen position="center,center" size="560,450" title="RS Downloader">\r
1261                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />\r
1262                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />\r
1263                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />\r
1264                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />\r
1265                         <ePixmap pixmap="skin_default/buttons/key_menu.png" position="10,420" size="35,25" transparent="1" alphatest="on" />\r
1266                         <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
1267                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
1268                         <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />
1269                         <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
1270                         <widget name="key_menu" position="50,422" size="300,25" font="Regular;20" transparent="1" />\r
1271                         <widget name="list" position="0,40" size="560,375" scrollbarMode="showNever" />\r
1272                 </screen>"""\r
1273 \r
1274         def __init__(self, session):\r
1275                 ChangedScreen.__init__(self, session)\r
1276                 self.session = session\r
1277                 \r
1278                 self["key_red"] = Label(_("Delete"))\r
1279                 self["key_green"] = Label(_("Search"))\r
1280                 self["key_yellow"] = Label(_("Add"))\r
1281                 self["key_blue"] = Label(_("Config"))\r
1282                 self["key_menu"] = Label(_("Menu"))\r
1283                 self["list"] = RSList([])\r
1284                 \r
1285                 self.refreshTimer = eTimer()\r
1286                 self.refreshTimer.callback.append(self.updateList)\r
1287                 \r
1288                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "InfobarMenuActions"],\r
1289                         {\r
1290                                 "mainMenu": self.menu,\r
1291                                 "cancel": self.close,\r
1292                                 "red": self.delete,\r
1293                                 "green": self.search,\r
1294                                 "yellow": self.add,\r
1295                                 "blue": self.config\r
1296                         }, prio=-1)\r
1297                 \r
1298                 self.onLayoutFinish.append(self.updateList)\r
1299 \r
1300         def menu(self):\r
1301                 list = []\r
1302                 list.append((_("Delete download"), self.delete))\r
1303                 list.append((_("Use search engine"), self.search))\r
1304                 list.append((_("Add downloads from txt files"), self.add))\r
1305                 list.append((_("Add files from container"), self.addContainer))\r
1306                 list.append((_("Delete failed downloads"), self.deleteFailed))\r
1307                 list.append((_("Abort all downloads"), self.abortDownloads))\r
1308                 list.append((_("Restart failed downloads"), self.restartFailed))\r
1309                 list.append((_("Clear finished downloads"), self.clearFinished))\r
1310                 list.append((_("Show log"), self.showLog))\r
1311                 list.append((_("Delete log"), self.deleteLog))
1312                 if fileExists("/usr/bin/unrar"):
1313                         list.append((_("Open unrar Manager"), self.openUnrarManager))
1314                 else:
1315                         list.append((_("Install unrar"), self.installUnrar))\r
1316                 list.append((_("Close plugin"), self.close))\r
1317                 self.session.openWithCallback(self.menuCallback, ChoiceBox, title=_("Please choose a function..."), list=list)\r
1318 \r
1319         def menuCallback(self, callback=None):\r
1320                 if callback is not None:\r
1321                         callback[1]()\r
1322 \r
1323         def deleteFailed(self):\r
1324                 rapidshare.deleteFailedDownloads()
1325
1326         def abortDownloads(self):
1327                 rapidshare.abortAllDownloads()\r
1328 \r
1329         def restartFailed(self):\r
1330                 rapidshare.restartFailedDownloads()\r
1331 \r
1332         def clearFinished(self):\r
1333                 rapidshare.clearFinishedDownloads()\r
1334 \r
1335         def showLog(self):\r
1336                 self.session.open(RSLogScreen)\r
1337 \r
1338         def deleteLog(self):\r
1339                 try:\r
1340                         remove("/tmp/rapidshare.log")\r
1341                 except:\r
1342                         pass
1343
1344         def openUnrarManager(self):
1345                 self.session.open(UnrarManager)
1346
1347         def installUnrar(self):
1348                 self.session.open(ConsoleScreen, title=_("Installing unrar..."), cmdlist=["ipkg install http://www.lt-forums.org/ali/downloads/unrar_3.4.3-r0_mipsel.ipk"])\r
1349 \r
1350         def updateList(self):\r
1351                 list = []\r
1352                 for download in rapidshare.downloads:\r
1353                         list.append(RSListEntry(download))\r
1354                 self["list"].setList(list)\r
1355                 self.refreshTimer.start(2000, 1)\r
1356 \r
1357         def delete(self):\r
1358                 cur = self["list"].getCurrent()\r
1359                 if cur:\r
1360                         cur = cur[0]\r
1361                         if cur.status == _("Finished"):\r
1362                                 rapidshare.clearFinishedDownload(cur.url)\r
1363                         else:\r
1364                                 self.session.openWithCallback(self.deleteCallback, MessageBox, (_("Delete %s?")%cur.name))\r
1365 \r
1366         def deleteCallback(self, callback):\r
1367                 if callback:\r
1368                         rapidshare.removeDownload(self["list"].getCurrent()[0].url)\r
1369                         self.refreshTimer.stop()\r
1370                         self.updateList()\r
1371 \r
1372         def search(self):\r
1373                 self.session.openWithCallback(self.searchCallback, VirtualKeyBoard, title=_("Search http://rapidshare-search-engine.com for:"))\r
1374 \r
1375         def searchCallback(self, callback):\r
1376                 if callback is not None and callback != "":\r
1377                         self.session.openWithCallback(self.searchScreenCallback, RSSearch, callback)\r
1378 \r
1379 \r
1380         def searchScreenCallback(self):\r
1381                 self.refreshTimer.stop()\r
1382                 rapidshare.startDownloading()\r
1383                 self.updateList()\r
1384 \r
1385         def add(self):\r
1386                 self.refreshTimer.stop()\r
1387                 rapidshare.startDownloading()\r
1388                 self.updateList()\r
1389 \r
1390         def config(self):\r
1391                 self.session.openWithCallback(self.configCallback, RSConfig)\r
1392 \r
1393         def configCallback(self):\r
1394                 if config.plugins.RSDownloader.onoff.value:\r
1395                         rapidshare.startDownloading()\r
1396                 else:\r
1397                         for download in rapidshare.downloads:\r
1398                                 if download.downloading:\r
1399                                         download.stop()\r
1400                 self.updateList()\r
1401 \r
1402         def addContainer(self):\r
1403                 try:\r
1404                         file_list = listdir(config.plugins.RSDownloader.lists_directory.value)\r
1405                 except:\r
1406                         file_list = []\r
1407                 list = []\r
1408                 for file in file_list:\r
1409                         if file.lower().endswith(".ccf") or file.lower().endswith(".dlc") or file.lower().endswith(".rsdf"):\r
1410                                 list.append(file)\r
1411                 list.sort()\r
1412                 self.session.openWithCallback(self.addContainerCallback, RSContainerSelector, list)\r
1413 \r
1414         def addContainerCallback(self, callback=None):\r
1415                 if callback:\r
1416                         file = "%s/%s"%(config.plugins.RSDownloader.lists_directory.value, callback)\r
1417                         file = file.replace("//", "/")\r
1418                         links = decrypt(file)
1419                         if links:\r
1420                                 try:\r
1421                                         f = open(("%s/%s.txt" % (config.plugins.RSDownloader.lists_directory.value, callback)).replace("//", "/"), "w")\r
1422                                         for link in links:\r
1423                                                 if link.endswith(".html"):\r
1424                                                         link = link[:-5]\r
1425                                                 elif link.endswith(".htm"):\r
1426                                                         link = link[:-4]\r
1427                                                 f.write("%s\n"%link)\r
1428                                         f.close()
1429                                         remove(file)\r
1430                                 except:\r
1431                                         pass\r
1432                                 self.refreshTimer.stop()\r
1433                                 rapidshare.startDownloading()\r
1434                                 self.updateList()
1435                         else:
1436                                 self.session.open(MessageBox, (_("Error while decrypting %s!") % callback), MessageBox.TYPE_ERROR)\r
1437 \r
1438 ##############################################################################\r
1439 \r
1440 def autostart(reason, **kwargs):\r
1441         if reason == 0:\r
1442                 rapidshare.startDownloading()
1443                 unrar.loadXml()
1444         elif reason == 1:
1445                 unrar.writeXml()\r
1446 \r
1447 ##############################################################################\r
1448 \r
1449 def main(session, **kwargs):\r
1450         session.open(RSMain)\r
1451 \r
1452 ##############################################################################\r
1453 \r
1454 def Plugins(**kwargs):\r
1455         return [\r
1456                 PluginDescriptor(where=PluginDescriptor.WHERE_AUTOSTART, fnc=autostart),\r
1457                 PluginDescriptor(name=_("RS Downloader"), description=_("Download files from rapidshare"), where=[PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU], icon="rs.png", fnc=main)]\r
1458 \r