summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--module/database/File.py875
-rw-r--r--module/plugins/Addon.py185
-rw-r--r--module/plugins/Captcha.py51
-rw-r--r--module/plugins/OCR.py318
-rw-r--r--module/plugins/accounts/BackinNet.py16
-rw-r--r--module/plugins/accounts/CloudzillaTo.py37
-rw-r--r--module/plugins/accounts/DropboxCom.py38
-rw-r--r--module/plugins/accounts/ExashareCom.py16
-rw-r--r--module/plugins/accounts/JunkyvideoCom.py16
-rw-r--r--module/plugins/accounts/MultihostersCom.py16
-rw-r--r--module/plugins/accounts/NoPremiumPl.py81
-rw-r--r--module/plugins/accounts/PutdriveCom.py16
-rw-r--r--module/plugins/accounts/RapideoPl.py80
-rw-r--r--module/plugins/accounts/RapiduNet.py66
-rw-r--r--module/plugins/accounts/SmoozedCom.py62
-rw-r--r--module/plugins/accounts/UploadableCh.py34
-rw-r--r--module/plugins/accounts/WebshareCz.py68
-rw-r--r--module/plugins/addon/ClickAndLoad.py74
-rw-r--r--module/plugins/addon/ExtractArchive.py509
-rw-r--r--module/plugins/addon/MergeFiles.py85
-rw-r--r--module/plugins/addon/SkipRev.py98
-rw-r--r--module/plugins/addon/UnSkipOnFail.py95
-rw-r--r--module/plugins/addon/UpdateManager.py306
-rw-r--r--module/plugins/captcha/AdYouLike.py107
-rw-r--r--module/plugins/captcha/AdsCaptcha.py77
-rw-r--r--module/plugins/captcha/ReCaptcha.py73
-rw-r--r--module/plugins/captcha/SolveMedia.py50
-rw-r--r--module/plugins/container/CCF.py49
-rw-r--r--module/plugins/container/DLC.py72
-rw-r--r--module/plugins/container/LinkList.py69
-rw-r--r--module/plugins/container/RSDF.py52
-rw-r--r--module/plugins/crypter/BitshareCom.py24
-rw-r--r--module/plugins/crypter/C1NeonCom.py19
-rw-r--r--module/plugins/crypter/CloudzillaToFolder.py39
-rw-r--r--module/plugins/crypter/CrockoCom.py23
-rw-r--r--module/plugins/crypter/CryptItCom.py19
-rw-r--r--module/plugins/crypter/DataHu.py43
-rw-r--r--module/plugins/crypter/DdlstorageCom.py20
-rw-r--r--module/plugins/crypter/DepositfilesCom.py23
-rw-r--r--module/plugins/crypter/Dereferer.py17
-rw-r--r--module/plugins/crypter/DevhostStFolder.py57
-rw-r--r--module/plugins/crypter/DlProtectCom.py68
-rw-r--r--module/plugins/crypter/DontKnowMe.py17
-rw-r--r--module/plugins/crypter/DuploadOrg.py19
-rw-r--r--module/plugins/crypter/EasybytezCom.py23
-rw-r--r--module/plugins/crypter/FilebeerInfo.py19
-rw-r--r--module/plugins/crypter/FilecloudIo.py24
-rw-r--r--module/plugins/crypter/FilecryptCc.py182
-rw-r--r--module/plugins/crypter/FilefactoryCom.py31
-rw-r--r--module/plugins/crypter/FilerNet.py27
-rw-r--r--module/plugins/crypter/FilesonicCom.py18
-rw-r--r--module/plugins/crypter/FilestubeCom.py24
-rw-r--r--module/plugins/crypter/FiletramCom.py25
-rw-r--r--module/plugins/crypter/FiredriveCom.py19
-rw-r--r--module/plugins/crypter/FreakhareCom.py41
-rw-r--r--module/plugins/crypter/FreetexthostCom.py30
-rw-r--r--module/plugins/crypter/FshareVn.py23
-rw-r--r--module/plugins/crypter/Go4UpCom.py49
-rw-r--r--module/plugins/crypter/HotfileCom.py19
-rw-r--r--module/plugins/crypter/ILoadTo.py19
-rw-r--r--module/plugins/crypter/ImgurComAlbum.py30
-rw-r--r--module/plugins/crypter/LinkSaveIn.py22
-rw-r--r--module/plugins/crypter/LofCc.py19
-rw-r--r--module/plugins/crypter/MBLinkInfo.py20
-rw-r--r--module/plugins/crypter/MegaCoNzFolder.py32
-rw-r--r--module/plugins/crypter/MegaRapidCz.py23
-rw-r--r--module/plugins/crypter/MegauploadCom.py18
-rw-r--r--module/plugins/crypter/Movie2KTo.py19
-rw-r--r--module/plugins/crypter/MultiUpOrg.py41
-rw-r--r--module/plugins/crypter/MultiuploadCom.py18
-rw-r--r--module/plugins/crypter/NetfolderIn.py73
-rw-r--r--module/plugins/crypter/NosvideoCom.py24
-rw-r--r--module/plugins/crypter/OronCom.py19
-rw-r--r--module/plugins/crypter/PastebinCom.py24
-rw-r--r--module/plugins/crypter/RSLayerCom.py19
-rw-r--r--module/plugins/crypter/RelinkUs.py293
-rw-r--r--module/plugins/crypter/SecuredIn.py19
-rw-r--r--module/plugins/crypter/SharingmatrixCom.py18
-rw-r--r--module/plugins/crypter/SpeedLoadOrg.py19
-rw-r--r--module/plugins/crypter/StealthTo.py19
-rw-r--r--module/plugins/crypter/TnyCz.py30
-rw-r--r--module/plugins/crypter/TrailerzoneInfo.py19
-rw-r--r--module/plugins/crypter/TurbobitNet.py47
-rw-r--r--module/plugins/crypter/TusfilesNet.py46
-rw-r--r--module/plugins/crypter/UploadableCh.py27
-rw-r--r--module/plugins/crypter/UploadedTo.py37
-rw-r--r--module/plugins/crypter/WiiReloadedOrg.py19
-rw-r--r--module/plugins/crypter/WuploadCom.py18
-rw-r--r--module/plugins/crypter/XFileSharingPro.py55
-rw-r--r--module/plugins/hooks/AlldebridCom.py29
-rw-r--r--module/plugins/hooks/AndroidPhoneNotify.py80
-rw-r--r--module/plugins/hooks/BypassCaptcha.py135
-rw-r--r--module/plugins/hooks/Captcha9Kw.py251
-rw-r--r--module/plugins/hooks/CaptchaBrotherhood.py167
-rw-r--r--module/plugins/hooks/ClickAndLoad.py124
-rw-r--r--module/plugins/hooks/DeathByCaptcha.py214
-rw-r--r--module/plugins/hooks/DebridItaliaCom.py28
-rw-r--r--module/plugins/hooks/EasybytezCom.py32
-rw-r--r--module/plugins/hooks/ExpertDecoders.py96
-rw-r--r--module/plugins/hooks/FastixRu.py31
-rw-r--r--module/plugins/hooks/FreeWayMe.py27
-rw-r--r--module/plugins/hooks/ImageTyperz.py153
-rw-r--r--module/plugins/hooks/JustPremium.py46
-rw-r--r--module/plugins/hooks/LinkdecrypterCom.py25
-rw-r--r--module/plugins/hooks/LinksnappyCom.py29
-rw-r--r--module/plugins/hooks/MegaDebridEu.py35
-rw-r--r--module/plugins/hooks/MultihostersCom.py18
-rw-r--r--module/plugins/hooks/MultishareCz.py31
-rw-r--r--module/plugins/hooks/MyfastfileCom.py30
-rw-r--r--module/plugins/hooks/NoPremiumPl.py31
-rw-r--r--module/plugins/hooks/OverLoadMe.py31
-rw-r--r--module/plugins/hooks/PremiumTo.py29
-rw-r--r--module/plugins/hooks/PremiumizeMe.py40
-rw-r--r--module/plugins/hooks/PutdriveCom.py18
-rw-r--r--module/plugins/hooks/RPNetBiz.py38
-rw-r--r--module/plugins/hooks/RapideoPl.py31
-rw-r--r--module/plugins/hooks/RealdebridCom.py29
-rw-r--r--module/plugins/hooks/RehostTo.py29
-rw-r--r--module/plugins/hooks/SimplyPremiumCom.py31
-rw-r--r--module/plugins/hooks/SimplydebridCom.py26
-rw-r--r--module/plugins/hooks/SmoozedCom.py26
-rw-r--r--module/plugins/hooks/UnrestrictLi.py30
-rw-r--r--module/plugins/hooks/WindowsPhoneNotify.py96
-rw-r--r--module/plugins/hooks/XFileSharingPro.py110
-rw-r--r--module/plugins/hooks/ZeveraCom.py27
-rw-r--r--module/plugins/hoster/AlldebridCom.py78
-rw-r--r--module/plugins/hoster/AndroidfilehostCom.py63
-rw-r--r--module/plugins/hoster/BasketbuildCom.py61
-rw-r--r--module/plugins/hoster/BayfilesCom.py18
-rw-r--r--module/plugins/hoster/BezvadataCz.py94
-rw-r--r--module/plugins/hoster/BillionuploadsCom.py22
-rw-r--r--module/plugins/hoster/BitshareCom.py158
-rw-r--r--module/plugins/hoster/BoltsharingCom.py18
-rw-r--r--module/plugins/hoster/CatShareNet.py62
-rw-r--r--module/plugins/hoster/CloudzerNet.py20
-rw-r--r--module/plugins/hoster/CloudzillaTo.py61
-rw-r--r--module/plugins/hoster/CramitIn.py23
-rw-r--r--module/plugins/hoster/CrockoCom.py66
-rw-r--r--module/plugins/hoster/CyberlockerCh.py18
-rw-r--r--module/plugins/hoster/CzshareCom.py161
-rw-r--r--module/plugins/hoster/DataHu.py34
-rw-r--r--module/plugins/hoster/DataportCz.py57
-rw-r--r--module/plugins/hoster/DateiTo.py82
-rw-r--r--module/plugins/hoster/DdlstorageCom.py19
-rw-r--r--module/plugins/hoster/DebridItaliaCom.py43
-rw-r--r--module/plugins/hoster/DepositfilesCom.py115
-rw-r--r--module/plugins/hoster/DevhostSt.py36
-rw-r--r--module/plugins/hoster/DlFreeFr.py140
-rw-r--r--module/plugins/hoster/DodanePl.py18
-rw-r--r--module/plugins/hoster/DuploadOrg.py18
-rw-r--r--module/plugins/hoster/EasybytezCom.py24
-rw-r--r--module/plugins/hoster/EdiskCz.py56
-rw-r--r--module/plugins/hoster/EgoFilesCom.py18
-rw-r--r--module/plugins/hoster/EnteruploadCom.py18
-rw-r--r--module/plugins/hoster/EpicShareNet.py18
-rw-r--r--module/plugins/hoster/EuroshareEu.py67
-rw-r--r--module/plugins/hoster/ExashareCom.py38
-rw-r--r--module/plugins/hoster/ExtabitCom.py78
-rw-r--r--module/plugins/hoster/FastixRu.py66
-rw-r--r--module/plugins/hoster/FastshareCz.py79
-rw-r--r--module/plugins/hoster/FileApeCom.py18
-rw-r--r--module/plugins/hoster/FileSharkPl.py133
-rw-r--r--module/plugins/hoster/FileStoreTo.py37
-rw-r--r--module/plugins/hoster/FilebeerInfo.py18
-rw-r--r--module/plugins/hoster/FilecloudIo.py126
-rw-r--r--module/plugins/hoster/FileomCom.py33
-rw-r--r--module/plugins/hoster/FilepostCom.py133
-rw-r--r--module/plugins/hoster/FilepupNet.py47
-rw-r--r--module/plugins/hoster/FilerNet.py74
-rw-r--r--module/plugins/hoster/FilerioCom.py23
-rw-r--r--module/plugins/hoster/FileserveCom.py216
-rw-r--r--module/plugins/hoster/FileshareInUa.py18
-rw-r--r--module/plugins/hoster/FilesonicCom.py19
-rw-r--r--module/plugins/hoster/FilezyNet.py18
-rw-r--r--module/plugins/hoster/FiredriveCom.py18
-rw-r--r--module/plugins/hoster/FourSharedCom.py62
-rw-r--r--module/plugins/hoster/FreakshareCom.py180
-rw-r--r--module/plugins/hoster/FreeWayMe.py53
-rw-r--r--module/plugins/hoster/FreevideoCz.py18
-rw-r--r--module/plugins/hoster/GigapetaCom.py64
-rw-r--r--module/plugins/hoster/GooIm.py37
-rw-r--r--module/plugins/hoster/GoogledriveCom.py65
-rw-r--r--module/plugins/hoster/HellshareCz.py35
-rw-r--r--module/plugins/hoster/HellspyCz.py18
-rw-r--r--module/plugins/hoster/HotfileCom.py21
-rw-r--r--module/plugins/hoster/HugefilesNet.py25
-rw-r--r--module/plugins/hoster/HundredEightyUploadCom.py19
-rw-r--r--module/plugins/hoster/IFileWs.py18
-rw-r--r--module/plugins/hoster/IcyFilesCom.py18
-rw-r--r--module/plugins/hoster/IfileIt.py18
-rw-r--r--module/plugins/hoster/IfolderRu.py76
-rw-r--r--module/plugins/hoster/JumbofilesCom.py36
-rw-r--r--module/plugins/hoster/JunocloudMe.py24
-rw-r--r--module/plugins/hoster/Keep2ShareCc.py112
-rw-r--r--module/plugins/hoster/KickloadCom.py18
-rw-r--r--module/plugins/hoster/KingfilesNet.py78
-rw-r--r--module/plugins/hoster/LemUploadsCom.py18
-rw-r--r--module/plugins/hoster/LetitbitNet.py155
-rw-r--r--module/plugins/hoster/LinksnappyCom.py58
-rw-r--r--module/plugins/hoster/LoadTo.py68
-rw-r--r--module/plugins/hoster/LomafileCom.py19
-rw-r--r--module/plugins/hoster/LuckyShareNet.py74
-rw-r--r--module/plugins/hoster/MegaCoNz.py217
-rw-r--r--module/plugins/hoster/MegaDebridEu.py89
-rw-r--r--module/plugins/hoster/MegaFilesSe.py18
-rw-r--r--module/plugins/hoster/MegaRapidCz.py65
-rw-r--r--module/plugins/hoster/MegareleaseOrg.py19
-rw-r--r--module/plugins/hoster/MegasharesCom.py113
-rw-r--r--module/plugins/hoster/MegauploadCom.py18
-rw-r--r--module/plugins/hoster/MegavideoCom.py19
-rw-r--r--module/plugins/hoster/MovReelCom.py21
-rw-r--r--module/plugins/hoster/MultihostersCom.py15
-rw-r--r--module/plugins/hoster/MultishareCz.py54
-rw-r--r--module/plugins/hoster/MyfastfileCom.py39
-rw-r--r--module/plugins/hoster/MystoreTo.py45
-rw-r--r--module/plugins/hoster/NahrajCz.py18
-rw-r--r--module/plugins/hoster/NarodRu.py66
-rw-r--r--module/plugins/hoster/NitroflareCom.py107
-rw-r--r--module/plugins/hoster/NoPremiumPl.py103
-rw-r--r--module/plugins/hoster/NosuploadCom.py42
-rw-r--r--module/plugins/hoster/NovafileCom.py29
-rw-r--r--module/plugins/hoster/NowDownloadSx.py64
-rw-r--r--module/plugins/hoster/NowVideoSx.py44
-rw-r--r--module/plugins/hoster/OneFichierCom.py61
-rw-r--r--module/plugins/hoster/OronCom.py19
-rw-r--r--module/plugins/hoster/OverLoadMe.py76
-rw-r--r--module/plugins/hoster/PandaplaNet.py18
-rw-r--r--module/plugins/hoster/PotloadCom.py18
-rw-r--r--module/plugins/hoster/PremiumTo.py55
-rw-r--r--module/plugins/hoster/PremiumizeMe.py60
-rw-r--r--module/plugins/hoster/PromptfileCom.py45
-rw-r--r--module/plugins/hoster/PrzeklejPl.py18
-rw-r--r--module/plugins/hoster/PutdriveCom.py15
-rw-r--r--module/plugins/hoster/QuickshareCz.py89
-rw-r--r--module/plugins/hoster/RPNetBiz.py80
-rw-r--r--module/plugins/hoster/RapideoPl.py103
-rw-r--r--module/plugins/hoster/RapidfileshareNet.py25
-rw-r--r--module/plugins/hoster/RapidgatorNet.py172
-rw-r--r--module/plugins/hoster/RapiduNet.py86
-rw-r--r--module/plugins/hoster/RarefileNet.py23
-rw-r--r--module/plugins/hoster/RealdebridCom.py79
-rw-r--r--module/plugins/hoster/RehostTo.py28
-rw-r--r--module/plugins/hoster/RemixshareCom.py60
-rw-r--r--module/plugins/hoster/RgHostNet.py26
-rw-r--r--module/plugins/hoster/SafesharingEu.py21
-rw-r--r--module/plugins/hoster/SecureUploadEu.py21
-rw-r--r--module/plugins/hoster/SendspaceCom.py61
-rw-r--r--module/plugins/hoster/Share4WebCom.py22
-rw-r--r--module/plugins/hoster/Share76Com.py18
-rw-r--r--module/plugins/hoster/ShareFilesCo.py18
-rw-r--r--module/plugins/hoster/SharebeesCom.py18
-rw-r--r--module/plugins/hoster/ShareonlineBiz.py187
-rw-r--r--module/plugins/hoster/SharingmatrixCom.py19
-rw-r--r--module/plugins/hoster/ShragleCom.py19
-rw-r--r--module/plugins/hoster/SimplyPremiumCom.py81
-rw-r--r--module/plugins/hoster/SimplydebridCom.py48
-rw-r--r--module/plugins/hoster/SmoozedCom.py63
-rw-r--r--module/plugins/hoster/SockshareCom.py20
-rw-r--r--module/plugins/hoster/SpeedLoadOrg.py18
-rw-r--r--module/plugins/hoster/SpeedfileCz.py18
-rw-r--r--module/plugins/hoster/SpeedyshareCom.py44
-rw-r--r--module/plugins/hoster/StorageTo.py18
-rw-r--r--module/plugins/hoster/StreamcloudEu.py31
-rw-r--r--module/plugins/hoster/TurbobitNet.py167
-rw-r--r--module/plugins/hoster/TurbouploadCom.py18
-rw-r--r--module/plugins/hoster/TusfilesNet.py40
-rw-r--r--module/plugins/hoster/TwoSharedCom.py32
-rw-r--r--module/plugins/hoster/UlozTo.py158
-rw-r--r--module/plugins/hoster/UloziskoSk.py71
-rw-r--r--module/plugins/hoster/UnibytesCom.py73
-rw-r--r--module/plugins/hoster/UnrestrictLi.py85
-rw-r--r--module/plugins/hoster/UpleaCom.py59
-rw-r--r--module/plugins/hoster/UploadStationCom.py19
-rw-r--r--module/plugins/hoster/UploadableCh.py79
-rw-r--r--module/plugins/hoster/UploadboxCom.py18
-rw-r--r--module/plugins/hoster/UploadedTo.py120
-rw-r--r--module/plugins/hoster/UploadhereCom.py18
-rw-r--r--module/plugins/hoster/UploadheroCom.py76
-rw-r--r--module/plugins/hoster/UploadingCom.py99
-rw-r--r--module/plugins/hoster/UploadkingCom.py18
-rw-r--r--module/plugins/hoster/UpstoreNet.py72
-rw-r--r--module/plugins/hoster/UptoboxCom.py32
-rw-r--r--module/plugins/hoster/VeohCom.py54
-rw-r--r--module/plugins/hoster/VidPlayNet.py24
-rw-r--r--module/plugins/hoster/VimeoCom.py74
-rw-r--r--module/plugins/hoster/Vipleech4UCom.py18
-rw-r--r--module/plugins/hoster/WarserverCz.py18
-rw-r--r--module/plugins/hoster/WebshareCz.py63
-rw-r--r--module/plugins/hoster/WrzucTo.py52
-rw-r--r--module/plugins/hoster/WuploadCom.py19
-rw-r--r--module/plugins/hoster/X7To.py18
-rw-r--r--module/plugins/hoster/XFileSharingPro.py62
-rw-r--r--module/plugins/hoster/XdadevelopersCom.py38
-rw-r--r--module/plugins/hoster/YibaishiwuCom.py59
-rw-r--r--module/plugins/hoster/ZShareNet.py19
-rw-r--r--module/plugins/hoster/ZeveraCom.py34
-rw-r--r--module/plugins/hoster/ZippyshareCom.py65
-rw-r--r--module/plugins/internal/BasePlugin.py95
-rw-r--r--module/plugins/internal/CaptchaService.py522
-rw-r--r--module/plugins/internal/DeadCrypter.py31
-rw-r--r--module/plugins/internal/DeadHoster.py31
-rw-r--r--module/plugins/internal/Extractor.py139
-rw-r--r--module/plugins/internal/MultiHook.py308
-rw-r--r--module/plugins/internal/MultiHoster.py85
-rw-r--r--module/plugins/internal/SevenZip.py155
-rw-r--r--module/plugins/internal/SimpleCrypter.py157
-rw-r--r--module/plugins/internal/SimpleDereferer.py98
-rw-r--r--module/plugins/internal/SimpleHoster.py701
-rw-r--r--module/plugins/internal/UnRar.py248
-rw-r--r--module/plugins/internal/UnZip.py68
-rw-r--r--module/plugins/internal/UpdateManager.py300
-rw-r--r--module/plugins/internal/XFSCrypter.py45
-rw-r--r--module/plugins/internal/XFSHoster.py326
-rw-r--r--pyload/Core.py (renamed from module/Core.py)0
-rw-r--r--pyload/__init__.py (renamed from module/__init__.py)0
-rw-r--r--pyload/api/__init__.py (renamed from module/api/__init__.py)0
-rw-r--r--pyload/api/types.py (renamed from module/api/types.py)0
-rw-r--r--pyload/cli/AddPackage.py (renamed from module/cli/AddPackage.py)0
-rw-r--r--pyload/cli/Cli.py (renamed from module/cli/Cli.py)0
-rw-r--r--pyload/cli/Handler.py (renamed from module/cli/Handler.py)0
-rw-r--r--pyload/cli/ManageFiles.py (renamed from module/cli/ManageFiles.py)0
-rw-r--r--pyload/cli/__init__.py (renamed from module/cli/__init__.py)0
-rw-r--r--pyload/config/Parser.py (renamed from module/config/Parser.py)0
-rw-r--r--pyload/config/Setup.py (renamed from module/config/Setup.py)0
-rw-r--r--pyload/config/__init__.py (renamed from module/config/__init__.py)0
-rw-r--r--pyload/config/default.conf (renamed from module/config/default.conf)0
-rw-r--r--pyload/database/DatabaseBackend.py (renamed from module/database/DatabaseBackend.py)0
-rw-r--r--pyload/database/File.py875
-rw-r--r--pyload/database/Storage.py (renamed from module/database/Storage.py)0
-rw-r--r--pyload/database/User.py (renamed from module/database/User.py)0
-rw-r--r--pyload/database/__init__.py (renamed from module/database/__init__.py)0
-rw-r--r--pyload/datatype/File.py (renamed from module/datatype/File.py)0
-rw-r--r--pyload/datatype/Package.py (renamed from module/datatype/Package.py)0
-rw-r--r--pyload/datatype/__init__.py (renamed from module/datatype/__init__.py)0
-rw-r--r--pyload/manager/Account.py (renamed from module/manager/Account.py)0
-rw-r--r--pyload/manager/Addon.py (renamed from module/manager/Addon.py)0
-rw-r--r--pyload/manager/Captcha.py (renamed from module/manager/Captcha.py)0
-rw-r--r--pyload/manager/Event.py (renamed from module/manager/Event.py)0
-rw-r--r--pyload/manager/Plugin.py (renamed from module/manager/Plugin.py)0
-rw-r--r--pyload/manager/Remote.py (renamed from module/manager/Remote.py)0
-rw-r--r--pyload/manager/Thread.py (renamed from module/manager/Thread.py)0
-rw-r--r--pyload/manager/__init__.py (renamed from module/manager/__init__.py)0
-rw-r--r--pyload/manager/event/Scheduler.py (renamed from module/manager/event/Scheduler.py)0
-rw-r--r--pyload/manager/event/__init__.py (renamed from module/manager/event/__init__.py)0
-rw-r--r--pyload/manager/thread/Addon.py (renamed from module/manager/thread/Addon.py)0
-rw-r--r--pyload/manager/thread/Decrypter.py (renamed from module/manager/thread/Decrypter.py)0
-rw-r--r--pyload/manager/thread/Download.py (renamed from module/manager/thread/Download.py)0
-rw-r--r--pyload/manager/thread/Info.py (renamed from module/manager/thread/Info.py)0
-rw-r--r--pyload/manager/thread/Plugin.py (renamed from module/manager/thread/Plugin.py)0
-rw-r--r--pyload/manager/thread/Server.py (renamed from module/manager/thread/Server.py)0
-rw-r--r--pyload/manager/thread/__init__.py (renamed from module/manager/thread/__init__.py)0
-rw-r--r--pyload/network/Browser.py (renamed from module/network/Browser.py)0
-rw-r--r--pyload/network/Bucket.py (renamed from module/network/Bucket.py)0
-rw-r--r--pyload/network/CookieJar.py (renamed from module/network/CookieJar.py)0
-rw-r--r--pyload/network/HTTPChunk.py (renamed from module/network/HTTPChunk.py)0
-rw-r--r--pyload/network/HTTPDownload.py (renamed from module/network/HTTPDownload.py)0
-rw-r--r--pyload/network/HTTPRequest.py (renamed from module/network/HTTPRequest.py)0
-rw-r--r--pyload/network/JsEngine.py (renamed from module/network/JsEngine.py)0
-rw-r--r--pyload/network/RequestFactory.py (renamed from module/network/RequestFactory.py)0
-rw-r--r--pyload/network/XDCCRequest.py (renamed from module/network/XDCCRequest.py)0
-rw-r--r--pyload/network/__init__.py (renamed from module/network/__init__.py)0
-rw-r--r--pyload/plugin/Account.py (renamed from module/plugins/Account.py)0
-rw-r--r--pyload/plugin/Addon.py182
-rw-r--r--pyload/plugin/Captcha.py34
-rw-r--r--pyload/plugin/Container.py (renamed from module/plugins/Container.py)0
-rw-r--r--pyload/plugin/Crypter.py (renamed from module/plugins/Crypter.py)0
-rw-r--r--pyload/plugin/Extractor.py140
-rw-r--r--pyload/plugin/Hook.py15
-rw-r--r--pyload/plugin/Hoster.py (renamed from module/plugins/Hoster.py)0
-rw-r--r--pyload/plugin/OCR.py319
-rw-r--r--pyload/plugin/Plugin.py (renamed from module/plugins/Plugin.py)0
-rw-r--r--pyload/plugin/__init__.py (renamed from module/plugins/__init__.py)0
-rw-r--r--pyload/plugin/account/AlldebridCom.py (renamed from module/plugins/accounts/AlldebridCom.py)0
-rw-r--r--pyload/plugin/account/BackinNet.py16
-rw-r--r--pyload/plugin/account/BillionuploadsCom.py (renamed from module/plugins/accounts/BillionuploadsCom.py)0
-rw-r--r--pyload/plugin/account/BitshareCom.py (renamed from module/plugins/accounts/BitshareCom.py)0
-rw-r--r--pyload/plugin/account/CatShareNet.py (renamed from module/plugins/accounts/CatShareNet.py)0
-rw-r--r--pyload/plugin/account/CloudzillaTo.py37
-rw-r--r--pyload/plugin/account/CramitIn.py (renamed from module/plugins/accounts/CramitIn.py)0
-rw-r--r--pyload/plugin/account/CzshareCom.py (renamed from module/plugins/accounts/CzshareCom.py)0
-rw-r--r--pyload/plugin/account/DebridItaliaCom.py (renamed from module/plugins/accounts/DebridItaliaCom.py)0
-rw-r--r--pyload/plugin/account/DepositfilesCom.py (renamed from module/plugins/accounts/DepositfilesCom.py)0
-rw-r--r--pyload/plugin/account/DropboxCom.py35
-rw-r--r--pyload/plugin/account/EasybytezCom.py (renamed from module/plugins/accounts/EasybytezCom.py)0
-rw-r--r--pyload/plugin/account/EuroshareEu.py (renamed from module/plugins/accounts/EuroshareEu.py)0
-rw-r--r--pyload/plugin/account/ExashareCom.py16
-rw-r--r--pyload/plugin/account/FastixRu.py (renamed from module/plugins/accounts/FastixRu.py)0
-rw-r--r--pyload/plugin/account/FastshareCz.py (renamed from module/plugins/accounts/FastshareCz.py)0
-rw-r--r--pyload/plugin/account/File4SafeCom.py (renamed from module/plugins/accounts/File4SafeCom.py)0
-rw-r--r--pyload/plugin/account/FileParadoxIn.py (renamed from module/plugins/accounts/FileParadoxIn.py)0
-rw-r--r--pyload/plugin/account/FilecloudIo.py (renamed from module/plugins/accounts/FilecloudIo.py)0
-rw-r--r--pyload/plugin/account/FilefactoryCom.py (renamed from module/plugins/accounts/FilefactoryCom.py)0
-rw-r--r--pyload/plugin/account/FilejungleCom.py (renamed from module/plugins/accounts/FilejungleCom.py)0
-rw-r--r--pyload/plugin/account/FileomCom.py (renamed from module/plugins/accounts/FileomCom.py)0
-rw-r--r--pyload/plugin/account/FilerNet.py (renamed from module/plugins/accounts/FilerNet.py)0
-rw-r--r--pyload/plugin/account/FilerioCom.py (renamed from module/plugins/accounts/FilerioCom.py)0
-rw-r--r--pyload/plugin/account/FilesMailRu.py (renamed from module/plugins/accounts/FilesMailRu.py)0
-rw-r--r--pyload/plugin/account/FileserveCom.py (renamed from module/plugins/accounts/FileserveCom.py)0
-rw-r--r--pyload/plugin/account/FourSharedCom.py (renamed from module/plugins/accounts/FourSharedCom.py)0
-rw-r--r--pyload/plugin/account/FreakshareCom.py (renamed from module/plugins/accounts/FreakshareCom.py)0
-rw-r--r--pyload/plugin/account/FreeWayMe.py (renamed from module/plugins/accounts/FreeWayMe.py)0
-rw-r--r--pyload/plugin/account/FshareVn.py (renamed from module/plugins/accounts/FshareVn.py)0
-rw-r--r--pyload/plugin/account/Ftp.py (renamed from module/plugins/accounts/Ftp.py)0
-rw-r--r--pyload/plugin/account/HellshareCz.py (renamed from module/plugins/accounts/HellshareCz.py)0
-rw-r--r--pyload/plugin/account/Http.py (renamed from module/plugins/accounts/Http.py)0
-rw-r--r--pyload/plugin/account/HugefilesNet.py (renamed from module/plugins/accounts/HugefilesNet.py)0
-rw-r--r--pyload/plugin/account/HundredEightyUploadCom.py (renamed from module/plugins/accounts/HundredEightyUploadCom.py)0
-rw-r--r--pyload/plugin/account/JunkyvideoCom.py16
-rw-r--r--pyload/plugin/account/JunocloudMe.py (renamed from module/plugins/accounts/JunocloudMe.py)0
-rw-r--r--pyload/plugin/account/Keep2ShareCc.py (renamed from module/plugins/accounts/Keep2ShareCc.py)0
-rw-r--r--pyload/plugin/account/LetitbitNet.py (renamed from module/plugins/accounts/LetitbitNet.py)0
-rw-r--r--pyload/plugin/account/LinestorageCom.py (renamed from module/plugins/accounts/LinestorageCom.py)0
-rw-r--r--pyload/plugin/account/LinksnappyCom.py (renamed from module/plugins/accounts/LinksnappyCom.py)0
-rw-r--r--pyload/plugin/account/MegaDebridEu.py (renamed from module/plugins/accounts/MegaDebridEu.py)0
-rw-r--r--pyload/plugin/account/MegaRapidCz.py (renamed from module/plugins/accounts/MegaRapidCz.py)0
-rw-r--r--pyload/plugin/account/MegasharesCom.py (renamed from module/plugins/accounts/MegasharesCom.py)0
-rw-r--r--pyload/plugin/account/MovReelCom.py (renamed from module/plugins/accounts/MovReelCom.py)0
-rw-r--r--pyload/plugin/account/MultihostersCom.py16
-rw-r--r--pyload/plugin/account/MultishareCz.py (renamed from module/plugins/accounts/MultishareCz.py)0
-rw-r--r--pyload/plugin/account/MyfastfileCom.py (renamed from module/plugins/accounts/MyfastfileCom.py)0
-rw-r--r--pyload/plugin/account/NetloadIn.py (renamed from module/plugins/accounts/NetloadIn.py)0
-rw-r--r--pyload/plugin/account/NoPremiumPl.py82
-rw-r--r--pyload/plugin/account/NosuploadCom.py (renamed from module/plugins/accounts/NosuploadCom.py)0
-rw-r--r--pyload/plugin/account/NovafileCom.py (renamed from module/plugins/accounts/NovafileCom.py)0
-rw-r--r--pyload/plugin/account/NowVideoSx.py (renamed from module/plugins/accounts/NowVideoSx.py)0
-rw-r--r--pyload/plugin/account/OboomCom.py (renamed from module/plugins/accounts/OboomCom.py)0
-rw-r--r--pyload/plugin/account/OneFichierCom.py (renamed from module/plugins/accounts/OneFichierCom.py)0
-rw-r--r--pyload/plugin/account/OverLoadMe.py (renamed from module/plugins/accounts/OverLoadMe.py)0
-rw-r--r--pyload/plugin/account/PremiumTo.py (renamed from module/plugins/accounts/PremiumTo.py)0
-rw-r--r--pyload/plugin/account/PremiumizeMe.py (renamed from module/plugins/accounts/PremiumizeMe.py)0
-rw-r--r--pyload/plugin/account/PutdriveCom.py16
-rw-r--r--pyload/plugin/account/QuickshareCz.py (renamed from module/plugins/accounts/QuickshareCz.py)0
-rw-r--r--pyload/plugin/account/RPNetBiz.py (renamed from module/plugins/accounts/RPNetBiz.py)0
-rw-r--r--pyload/plugin/account/RapideoPl.py81
-rw-r--r--pyload/plugin/account/RapidfileshareNet.py (renamed from module/plugins/accounts/RapidfileshareNet.py)0
-rw-r--r--pyload/plugin/account/RapidgatorNet.py (renamed from module/plugins/accounts/RapidgatorNet.py)0
-rw-r--r--pyload/plugin/account/RapiduNet.py66
-rw-r--r--pyload/plugin/account/RarefileNet.py (renamed from module/plugins/accounts/RarefileNet.py)0
-rw-r--r--pyload/plugin/account/RealdebridCom.py (renamed from module/plugins/accounts/RealdebridCom.py)0
-rw-r--r--pyload/plugin/account/RehostTo.py (renamed from module/plugins/accounts/RehostTo.py)0
-rw-r--r--pyload/plugin/account/RyushareCom.py (renamed from module/plugins/accounts/RyushareCom.py)0
-rw-r--r--pyload/plugin/account/SafesharingEu.py (renamed from module/plugins/accounts/SafesharingEu.py)0
-rw-r--r--pyload/plugin/account/SecureUploadEu.py (renamed from module/plugins/accounts/SecureUploadEu.py)0
-rw-r--r--pyload/plugin/account/SendmywayCom.py (renamed from module/plugins/accounts/SendmywayCom.py)0
-rw-r--r--pyload/plugin/account/ShareonlineBiz.py (renamed from module/plugins/accounts/ShareonlineBiz.py)0
-rw-r--r--pyload/plugin/account/SimplyPremiumCom.py (renamed from module/plugins/accounts/SimplyPremiumCom.py)0
-rw-r--r--pyload/plugin/account/SimplydebridCom.py (renamed from module/plugins/accounts/SimplydebridCom.py)0
-rw-r--r--pyload/plugin/account/SmoozedCom.py62
-rw-r--r--pyload/plugin/account/StahnuTo.py (renamed from module/plugins/accounts/StahnuTo.py)0
-rw-r--r--pyload/plugin/account/StreamcloudEu.py (renamed from module/plugins/accounts/StreamcloudEu.py)0
-rw-r--r--pyload/plugin/account/TurbobitNet.py (renamed from module/plugins/accounts/TurbobitNet.py)0
-rw-r--r--pyload/plugin/account/TusfilesNet.py (renamed from module/plugins/accounts/TusfilesNet.py)0
-rw-r--r--pyload/plugin/account/UlozTo.py (renamed from module/plugins/accounts/UlozTo.py)0
-rw-r--r--pyload/plugin/account/UnrestrictLi.py (renamed from module/plugins/accounts/UnrestrictLi.py)0
-rw-r--r--pyload/plugin/account/UploadableCh.py34
-rw-r--r--pyload/plugin/account/UploadcCom.py (renamed from module/plugins/accounts/UploadcCom.py)0
-rw-r--r--pyload/plugin/account/UploadedTo.py (renamed from module/plugins/accounts/UploadedTo.py)0
-rw-r--r--pyload/plugin/account/UploadheroCom.py (renamed from module/plugins/accounts/UploadheroCom.py)0
-rw-r--r--pyload/plugin/account/UploadingCom.py (renamed from module/plugins/accounts/UploadingCom.py)0
-rw-r--r--pyload/plugin/account/UptoboxCom.py (renamed from module/plugins/accounts/UptoboxCom.py)0
-rw-r--r--pyload/plugin/account/VidPlayNet.py (renamed from module/plugins/accounts/VidPlayNet.py)0
-rw-r--r--pyload/plugin/account/WebshareCz.py68
-rw-r--r--pyload/plugin/account/XFileSharingPro.py (renamed from module/plugins/accounts/XFileSharingPro.py)0
-rw-r--r--pyload/plugin/account/YibaishiwuCom.py (renamed from module/plugins/accounts/YibaishiwuCom.py)0
-rw-r--r--pyload/plugin/account/ZeveraCom.py (renamed from module/plugins/accounts/ZeveraCom.py)0
-rw-r--r--pyload/plugin/account/__init__.py (renamed from module/plugins/accounts/__init__.py)0
-rw-r--r--pyload/plugin/addon/AndroidPhoneNotify.py75
-rw-r--r--pyload/plugin/addon/Checksum.py (renamed from module/plugins/addon/Checksum.py)0
-rw-r--r--pyload/plugin/addon/ClickAndLoad.py119
-rw-r--r--pyload/plugin/addon/DeleteFinished.py (renamed from module/plugins/addon/DeleteFinished.py)0
-rw-r--r--pyload/plugin/addon/DownloadScheduler.py (renamed from module/plugins/addon/DownloadScheduler.py)0
-rw-r--r--pyload/plugin/addon/ExternalScripts.py (renamed from module/plugins/addon/ExternalScripts.py)0
-rw-r--r--pyload/plugin/addon/ExtractArchive.py504
-rw-r--r--pyload/plugin/addon/HotFolder.py (renamed from module/plugins/addon/HotFolder.py)0
-rw-r--r--pyload/plugin/addon/IRCInterface.py (renamed from module/plugins/addon/IRCInterface.py)0
-rw-r--r--pyload/plugin/addon/JustPremium.py46
-rw-r--r--pyload/plugin/addon/MergeFiles.py85
-rw-r--r--pyload/plugin/addon/MultiHome.py (renamed from module/plugins/addon/MultiHome.py)0
-rw-r--r--pyload/plugin/addon/RestartFailed.py (renamed from module/plugins/addon/RestartFailed.py)0
-rw-r--r--pyload/plugin/addon/RestartSlow.py (renamed from module/plugins/addon/RestartSlow.py)0
-rw-r--r--pyload/plugin/addon/SkipRev.py93
-rw-r--r--pyload/plugin/addon/UnSkipOnFail.py90
-rw-r--r--pyload/plugin/addon/UpdateManager.py306
-rw-r--r--pyload/plugin/addon/WindowsPhoneNotify.py91
-rw-r--r--pyload/plugin/addon/XMPPInterface.py (renamed from module/plugins/addon/XMPPInterface.py)0
-rw-r--r--pyload/plugin/addon/__init__.py (renamed from module/plugins/addon/__init__.py)0
-rw-r--r--pyload/plugin/captcha/AdYouLike.py108
-rw-r--r--pyload/plugin/captcha/AdsCaptcha.py79
-rw-r--r--pyload/plugin/captcha/ReCaptcha.py208
-rw-r--r--pyload/plugin/captcha/SolveMedia.py113
-rw-r--r--pyload/plugin/captcha/__init__.py (renamed from module/plugins/captcha/__init__.py)0
-rw-r--r--pyload/plugin/container/CCF.py49
-rw-r--r--pyload/plugin/container/DLC.py72
-rw-r--r--pyload/plugin/container/RSDF.py52
-rw-r--r--pyload/plugin/container/TXT.py69
-rw-r--r--pyload/plugin/container/__init__.py (renamed from module/plugins/container/__init__.py)0
-rw-r--r--pyload/plugin/crypter/BitshareCom.py21
-rw-r--r--pyload/plugin/crypter/C1NeonCom.py16
-rw-r--r--pyload/plugin/crypter/ChipDe.py (renamed from module/plugins/crypter/ChipDe.py)0
-rw-r--r--pyload/plugin/crypter/CloudzillaTo.py36
-rw-r--r--pyload/plugin/crypter/CrockoCom.py20
-rw-r--r--pyload/plugin/crypter/CryptItCom.py16
-rw-r--r--pyload/plugin/crypter/CzshareCom.py (renamed from module/plugins/crypter/CzshareCom.py)0
-rw-r--r--pyload/plugin/crypter/DDLMusicOrg.py (renamed from module/plugins/crypter/DDLMusicOrg.py)0
-rw-r--r--pyload/plugin/crypter/DailymotionBatch.py (renamed from module/plugins/crypter/DailymotionBatch.py)0
-rw-r--r--pyload/plugin/crypter/DataHu.py40
-rw-r--r--pyload/plugin/crypter/DdlstorageCom.py17
-rw-r--r--pyload/plugin/crypter/DepositfilesCom.py20
-rw-r--r--pyload/plugin/crypter/Dereferer.py17
-rw-r--r--pyload/plugin/crypter/DevhostSt.py54
-rw-r--r--pyload/plugin/crypter/DlProtectCom.py65
-rw-r--r--pyload/plugin/crypter/DontKnowMe.py17
-rw-r--r--pyload/plugin/crypter/DuckCryptInfo.py (renamed from module/plugins/crypter/DuckCryptInfo.py)0
-rw-r--r--pyload/plugin/crypter/DuploadOrg.py16
-rw-r--r--pyload/plugin/crypter/EasybytezCom.py20
-rw-r--r--pyload/plugin/crypter/EmbeduploadCom.py (renamed from module/plugins/crypter/EmbeduploadCom.py)0
-rw-r--r--pyload/plugin/crypter/FilebeerInfo.py16
-rw-r--r--pyload/plugin/crypter/FilecloudIo.py21
-rw-r--r--pyload/plugin/crypter/FilecryptCc.py182
-rw-r--r--pyload/plugin/crypter/FilefactoryCom.py28
-rw-r--r--pyload/plugin/crypter/FilerNet.py24
-rw-r--r--pyload/plugin/crypter/FileserveCom.py (renamed from module/plugins/crypter/FileserveCom.py)0
-rw-r--r--pyload/plugin/crypter/FilesonicCom.py15
-rw-r--r--pyload/plugin/crypter/FilestubeCom.py21
-rw-r--r--pyload/plugin/crypter/FiletramCom.py22
-rw-r--r--pyload/plugin/crypter/FiredriveCom.py16
-rw-r--r--pyload/plugin/crypter/FourChanOrg.py (renamed from module/plugins/crypter/FourChanOrg.py)0
-rw-r--r--pyload/plugin/crypter/FreakhareCom.py38
-rw-r--r--pyload/plugin/crypter/FreetexthostCom.py27
-rw-r--r--pyload/plugin/crypter/FshareVn.py20
-rw-r--r--pyload/plugin/crypter/Go4UpCom.py46
-rw-r--r--pyload/plugin/crypter/GooGl.py (renamed from module/plugins/crypter/GooGl.py)0
-rw-r--r--pyload/plugin/crypter/HoerbuchIn.py (renamed from module/plugins/crypter/HoerbuchIn.py)0
-rw-r--r--pyload/plugin/crypter/HotfileCom.py16
-rw-r--r--pyload/plugin/crypter/ILoadTo.py16
-rw-r--r--pyload/plugin/crypter/ImgurComAlbum.py27
-rw-r--r--pyload/plugin/crypter/LetitbitNet.py (renamed from module/plugins/crypter/LetitbitNet.py)0
-rw-r--r--pyload/plugin/crypter/LinkCryptWs.py (renamed from module/plugins/crypter/LinkCryptWs.py)0
-rw-r--r--pyload/plugin/crypter/LinkSaveIn.py22
-rw-r--r--pyload/plugin/crypter/LinkdecrypterCom.py (renamed from module/plugins/crypter/LinkdecrypterCom.py)0
-rw-r--r--pyload/plugin/crypter/LixIn.py (renamed from module/plugins/crypter/LixIn.py)0
-rw-r--r--pyload/plugin/crypter/LofCc.py16
-rw-r--r--pyload/plugin/crypter/MBLinkInfo.py17
-rw-r--r--pyload/plugin/crypter/MediafireCom.py (renamed from module/plugins/crypter/MediafireCom.py)0
-rw-r--r--pyload/plugin/crypter/MegaCoNz.py32
-rw-r--r--pyload/plugin/crypter/MegaRapidCz.py20
-rw-r--r--pyload/plugin/crypter/MegauploadCom.py15
-rw-r--r--pyload/plugin/crypter/Movie2KTo.py16
-rw-r--r--pyload/plugin/crypter/MultiUpOrg.py38
-rw-r--r--pyload/plugin/crypter/MultiloadCz.py (renamed from module/plugins/crypter/MultiloadCz.py)0
-rw-r--r--pyload/plugin/crypter/MultiuploadCom.py15
-rw-r--r--pyload/plugin/crypter/NCryptIn.py (renamed from module/plugins/crypter/NCryptIn.py)0
-rw-r--r--pyload/plugin/crypter/NetfolderIn.py70
-rw-r--r--pyload/plugin/crypter/NosvideoCom.py21
-rw-r--r--pyload/plugin/crypter/OneKhDe.py (renamed from module/plugins/crypter/OneKhDe.py)0
-rw-r--r--pyload/plugin/crypter/OronCom.py16
-rw-r--r--pyload/plugin/crypter/PastebinCom.py21
-rw-r--r--pyload/plugin/crypter/QuickshareCz.py (renamed from module/plugins/crypter/QuickshareCz.py)0
-rw-r--r--pyload/plugin/crypter/RSLayerCom.py16
-rw-r--r--pyload/plugin/crypter/RelinkUs.py293
-rw-r--r--pyload/plugin/crypter/SafelinkingNet.py (renamed from module/plugins/crypter/SafelinkingNet.py)0
-rw-r--r--pyload/plugin/crypter/SecuredIn.py16
-rw-r--r--pyload/plugin/crypter/SexuriaCom.py (renamed from module/plugins/crypter/SexuriaCom.py)0
-rw-r--r--pyload/plugin/crypter/ShareLinksBiz.py (renamed from module/plugins/crypter/ShareLinksBiz.py)0
-rw-r--r--pyload/plugin/crypter/SharingmatrixCom.py15
-rw-r--r--pyload/plugin/crypter/SpeedLoadOrg.py16
-rw-r--r--pyload/plugin/crypter/StealthTo.py16
-rw-r--r--pyload/plugin/crypter/TnyCz.py27
-rw-r--r--pyload/plugin/crypter/TrailerzoneInfo.py16
-rw-r--r--pyload/plugin/crypter/TurbobitNet.py44
-rw-r--r--pyload/plugin/crypter/TusfilesNet.py43
-rw-r--r--pyload/plugin/crypter/UlozTo.py (renamed from module/plugins/crypter/UlozTo.py)0
-rw-r--r--pyload/plugin/crypter/UploadableCh.py24
-rw-r--r--pyload/plugin/crypter/UploadedTo.py34
-rw-r--r--pyload/plugin/crypter/WiiReloadedOrg.py16
-rw-r--r--pyload/plugin/crypter/WuploadCom.py15
-rw-r--r--pyload/plugin/crypter/XFileSharingPro.py52
-rw-r--r--pyload/plugin/crypter/XupPl.py (renamed from module/plugins/crypter/XupPl.py)0
-rw-r--r--pyload/plugin/crypter/YoutubeBatch.py (renamed from module/plugins/crypter/YoutubeBatch.py)0
-rw-r--r--pyload/plugin/crypter/__init__.py (renamed from module/plugins/crypter/__init__.py)0
-rw-r--r--pyload/plugin/extractor/SevenZip.py155
-rw-r--r--pyload/plugin/extractor/UnRar.py248
-rw-r--r--pyload/plugin/extractor/UnZip.py68
-rw-r--r--pyload/plugin/extractor/__init__.py (renamed from module/plugins/hooks/__init__.py)0
-rw-r--r--pyload/plugin/hook/AlldebridCom.py29
-rw-r--r--pyload/plugin/hook/BypassCaptcha.py135
-rw-r--r--pyload/plugin/hook/Captcha9Kw.py251
-rw-r--r--pyload/plugin/hook/CaptchaBrotherhood.py167
-rw-r--r--pyload/plugin/hook/DeathByCaptcha.py214
-rw-r--r--pyload/plugin/hook/DebridItaliaCom.py28
-rw-r--r--pyload/plugin/hook/EasybytezCom.py32
-rw-r--r--pyload/plugin/hook/ExpertDecoders.py96
-rw-r--r--pyload/plugin/hook/FastixRu.py31
-rw-r--r--pyload/plugin/hook/FreeWayMe.py27
-rw-r--r--pyload/plugin/hook/ImageTyperz.py153
-rw-r--r--pyload/plugin/hook/LinkdecrypterCom.py25
-rw-r--r--pyload/plugin/hook/LinksnappyCom.py29
-rw-r--r--pyload/plugin/hook/MegaDebridEu.py35
-rw-r--r--pyload/plugin/hook/MultihostersCom.py18
-rw-r--r--pyload/plugin/hook/MultishareCz.py31
-rw-r--r--pyload/plugin/hook/MyfastfileCom.py30
-rw-r--r--pyload/plugin/hook/NoPremiumPl.py31
-rw-r--r--pyload/plugin/hook/OverLoadMe.py31
-rw-r--r--pyload/plugin/hook/PremiumTo.py29
-rw-r--r--pyload/plugin/hook/PremiumizeMe.py40
-rw-r--r--pyload/plugin/hook/PutdriveCom.py18
-rw-r--r--pyload/plugin/hook/RPNetBiz.py38
-rw-r--r--pyload/plugin/hook/RapideoPl.py31
-rw-r--r--pyload/plugin/hook/RealdebridCom.py29
-rw-r--r--pyload/plugin/hook/RehostTo.py29
-rw-r--r--pyload/plugin/hook/SimplyPremiumCom.py31
-rw-r--r--pyload/plugin/hook/SimplydebridCom.py26
-rw-r--r--pyload/plugin/hook/SmoozedCom.py26
-rw-r--r--pyload/plugin/hook/UnrestrictLi.py30
-rw-r--r--pyload/plugin/hook/XFileSharingPro.py110
-rw-r--r--pyload/plugin/hook/ZeveraCom.py27
-rw-r--r--pyload/plugin/hook/__init__.py (renamed from module/plugins/hoster/__init__.py)0
-rw-r--r--pyload/plugin/hoster/AlldebridCom.py75
-rw-r--r--pyload/plugin/hoster/AndroidfilehostCom.py60
-rw-r--r--pyload/plugin/hoster/BasketbuildCom.py58
-rw-r--r--pyload/plugin/hoster/BayfilesCom.py15
-rw-r--r--pyload/plugin/hoster/BezvadataCz.py91
-rw-r--r--pyload/plugin/hoster/BillionuploadsCom.py19
-rw-r--r--pyload/plugin/hoster/BitshareCom.py155
-rw-r--r--pyload/plugin/hoster/BoltsharingCom.py15
-rw-r--r--pyload/plugin/hoster/CatShareNet.py59
-rw-r--r--pyload/plugin/hoster/CloudzerNet.py17
-rw-r--r--pyload/plugin/hoster/CloudzillaTo.py58
-rw-r--r--pyload/plugin/hoster/CramitIn.py20
-rw-r--r--pyload/plugin/hoster/CrockoCom.py63
-rw-r--r--pyload/plugin/hoster/CyberlockerCh.py15
-rw-r--r--pyload/plugin/hoster/CzshareCom.py158
-rw-r--r--pyload/plugin/hoster/DailymotionCom.py (renamed from module/plugins/hoster/DailymotionCom.py)0
-rw-r--r--pyload/plugin/hoster/DataHu.py31
-rw-r--r--pyload/plugin/hoster/DataportCz.py54
-rw-r--r--pyload/plugin/hoster/DateiTo.py79
-rw-r--r--pyload/plugin/hoster/DdlstorageCom.py16
-rw-r--r--pyload/plugin/hoster/DebridItaliaCom.py40
-rw-r--r--pyload/plugin/hoster/DepositfilesCom.py112
-rw-r--r--pyload/plugin/hoster/DevhostSt.py33
-rw-r--r--pyload/plugin/hoster/DlFreeFr.py137
-rw-r--r--pyload/plugin/hoster/DodanePl.py15
-rw-r--r--pyload/plugin/hoster/DuploadOrg.py15
-rw-r--r--pyload/plugin/hoster/EasybytezCom.py21
-rw-r--r--pyload/plugin/hoster/EdiskCz.py53
-rw-r--r--pyload/plugin/hoster/EgoFilesCom.py15
-rw-r--r--pyload/plugin/hoster/EnteruploadCom.py15
-rw-r--r--pyload/plugin/hoster/EpicShareNet.py15
-rw-r--r--pyload/plugin/hoster/EuroshareEu.py64
-rw-r--r--pyload/plugin/hoster/ExashareCom.py35
-rw-r--r--pyload/plugin/hoster/ExtabitCom.py75
-rw-r--r--pyload/plugin/hoster/FastixRu.py63
-rw-r--r--pyload/plugin/hoster/FastshareCz.py76
-rw-r--r--pyload/plugin/hoster/FileApeCom.py15
-rw-r--r--pyload/plugin/hoster/FileSharkPl.py130
-rw-r--r--pyload/plugin/hoster/FileStoreTo.py34
-rw-r--r--pyload/plugin/hoster/FilebeerInfo.py15
-rw-r--r--pyload/plugin/hoster/FilecloudIo.py123
-rw-r--r--pyload/plugin/hoster/FilefactoryCom.py (renamed from module/plugins/hoster/FilefactoryCom.py)0
-rw-r--r--pyload/plugin/hoster/FilejungleCom.py (renamed from module/plugins/hoster/FilejungleCom.py)0
-rw-r--r--pyload/plugin/hoster/FileomCom.py30
-rw-r--r--pyload/plugin/hoster/FilepostCom.py130
-rw-r--r--pyload/plugin/hoster/FilepupNet.py44
-rw-r--r--pyload/plugin/hoster/FilerNet.py71
-rw-r--r--pyload/plugin/hoster/FilerioCom.py20
-rw-r--r--pyload/plugin/hoster/FilesMailRu.py (renamed from module/plugins/hoster/FilesMailRu.py)0
-rw-r--r--pyload/plugin/hoster/FileserveCom.py216
-rw-r--r--pyload/plugin/hoster/FileshareInUa.py15
-rw-r--r--pyload/plugin/hoster/FilesonicCom.py16
-rw-r--r--pyload/plugin/hoster/FilezyNet.py15
-rw-r--r--pyload/plugin/hoster/FiredriveCom.py15
-rw-r--r--pyload/plugin/hoster/FlyFilesNet.py (renamed from module/plugins/hoster/FlyFilesNet.py)0
-rw-r--r--pyload/plugin/hoster/FourSharedCom.py59
-rw-r--r--pyload/plugin/hoster/FreakshareCom.py180
-rw-r--r--pyload/plugin/hoster/FreeWayMe.py50
-rw-r--r--pyload/plugin/hoster/FreevideoCz.py15
-rw-r--r--pyload/plugin/hoster/FshareVn.py (renamed from module/plugins/hoster/FshareVn.py)0
-rw-r--r--pyload/plugin/hoster/Ftp.py (renamed from module/plugins/hoster/Ftp.py)0
-rw-r--r--pyload/plugin/hoster/GamefrontCom.py (renamed from module/plugins/hoster/GamefrontCom.py)0
-rw-r--r--pyload/plugin/hoster/GigapetaCom.py61
-rw-r--r--pyload/plugin/hoster/GooIm.py34
-rw-r--r--pyload/plugin/hoster/GoogledriveCom.py62
-rw-r--r--pyload/plugin/hoster/HellshareCz.py32
-rw-r--r--pyload/plugin/hoster/HellspyCz.py15
-rw-r--r--pyload/plugin/hoster/HotfileCom.py18
-rw-r--r--pyload/plugin/hoster/HugefilesNet.py22
-rw-r--r--pyload/plugin/hoster/HundredEightyUploadCom.py15
-rw-r--r--pyload/plugin/hoster/IFileWs.py15
-rw-r--r--pyload/plugin/hoster/IcyFilesCom.py15
-rw-r--r--pyload/plugin/hoster/IfileIt.py15
-rw-r--r--pyload/plugin/hoster/IfolderRu.py73
-rw-r--r--pyload/plugin/hoster/JumbofilesCom.py33
-rw-r--r--pyload/plugin/hoster/JunocloudMe.py21
-rw-r--r--pyload/plugin/hoster/Keep2ShareCc.py109
-rw-r--r--pyload/plugin/hoster/KickloadCom.py15
-rw-r--r--pyload/plugin/hoster/KingfilesNet.py75
-rw-r--r--pyload/plugin/hoster/LemUploadsCom.py15
-rw-r--r--pyload/plugin/hoster/LetitbitNet.py155
-rw-r--r--pyload/plugin/hoster/LinksnappyCom.py55
-rw-r--r--pyload/plugin/hoster/LoadTo.py65
-rw-r--r--pyload/plugin/hoster/LomafileCom.py16
-rw-r--r--pyload/plugin/hoster/LuckyShareNet.py71
-rw-r--r--pyload/plugin/hoster/MediafireCom.py (renamed from module/plugins/hoster/MediafireCom.py)0
-rw-r--r--pyload/plugin/hoster/MegaCoNz.py217
-rw-r--r--pyload/plugin/hoster/MegaDebridEu.py86
-rw-r--r--pyload/plugin/hoster/MegaFilesSe.py15
-rw-r--r--pyload/plugin/hoster/MegaRapidCz.py65
-rw-r--r--pyload/plugin/hoster/MegacrypterCom.py (renamed from module/plugins/hoster/MegacrypterCom.py)0
-rw-r--r--pyload/plugin/hoster/MegareleaseOrg.py16
-rw-r--r--pyload/plugin/hoster/MegasharesCom.py110
-rw-r--r--pyload/plugin/hoster/MegauploadCom.py15
-rw-r--r--pyload/plugin/hoster/MegavideoCom.py16
-rw-r--r--pyload/plugin/hoster/MovReelCom.py18
-rw-r--r--pyload/plugin/hoster/MultihostersCom.py15
-rw-r--r--pyload/plugin/hoster/MultishareCz.py51
-rw-r--r--pyload/plugin/hoster/MyfastfileCom.py36
-rw-r--r--pyload/plugin/hoster/MystoreTo.py42
-rw-r--r--pyload/plugin/hoster/MyvideoDe.py (renamed from module/plugins/hoster/MyvideoDe.py)0
-rw-r--r--pyload/plugin/hoster/NahrajCz.py15
-rw-r--r--pyload/plugin/hoster/NarodRu.py63
-rw-r--r--pyload/plugin/hoster/NetloadIn.py (renamed from module/plugins/hoster/NetloadIn.py)0
-rw-r--r--pyload/plugin/hoster/NitroflareCom.py107
-rw-r--r--pyload/plugin/hoster/NoPremiumPl.py103
-rw-r--r--pyload/plugin/hoster/NosuploadCom.py39
-rw-r--r--pyload/plugin/hoster/NovafileCom.py26
-rw-r--r--pyload/plugin/hoster/NowDownloadSx.py61
-rw-r--r--pyload/plugin/hoster/NowVideoSx.py41
-rw-r--r--pyload/plugin/hoster/OboomCom.py (renamed from module/plugins/hoster/OboomCom.py)0
-rw-r--r--pyload/plugin/hoster/OneFichierCom.py58
-rw-r--r--pyload/plugin/hoster/OronCom.py16
-rw-r--r--pyload/plugin/hoster/OverLoadMe.py73
-rw-r--r--pyload/plugin/hoster/PandaplaNet.py15
-rw-r--r--pyload/plugin/hoster/PornhostCom.py (renamed from module/plugins/hoster/PornhostCom.py)0
-rw-r--r--pyload/plugin/hoster/PornhubCom.py (renamed from module/plugins/hoster/PornhubCom.py)0
-rw-r--r--pyload/plugin/hoster/PotloadCom.py15
-rw-r--r--pyload/plugin/hoster/PremiumTo.py52
-rw-r--r--pyload/plugin/hoster/PremiumizeMe.py57
-rw-r--r--pyload/plugin/hoster/PromptfileCom.py42
-rw-r--r--pyload/plugin/hoster/PrzeklejPl.py15
-rw-r--r--pyload/plugin/hoster/PutdriveCom.py15
-rw-r--r--pyload/plugin/hoster/QuickshareCz.py86
-rw-r--r--pyload/plugin/hoster/RPNetBiz.py77
-rw-r--r--pyload/plugin/hoster/RapideoPl.py103
-rw-r--r--pyload/plugin/hoster/RapidfileshareNet.py22
-rw-r--r--pyload/plugin/hoster/RapidgatorNet.py169
-rw-r--r--pyload/plugin/hoster/RapiduNet.py83
-rw-r--r--pyload/plugin/hoster/RarefileNet.py20
-rw-r--r--pyload/plugin/hoster/RealdebridCom.py76
-rw-r--r--pyload/plugin/hoster/RedtubeCom.py (renamed from module/plugins/hoster/RedtubeCom.py)0
-rw-r--r--pyload/plugin/hoster/RehostTo.py25
-rw-r--r--pyload/plugin/hoster/RemixshareCom.py57
-rw-r--r--pyload/plugin/hoster/RgHostNet.py23
-rw-r--r--pyload/plugin/hoster/SafesharingEu.py18
-rw-r--r--pyload/plugin/hoster/SecureUploadEu.py18
-rw-r--r--pyload/plugin/hoster/SendspaceCom.py58
-rw-r--r--pyload/plugin/hoster/Share4WebCom.py18
-rw-r--r--pyload/plugin/hoster/Share76Com.py15
-rw-r--r--pyload/plugin/hoster/ShareFilesCo.py15
-rw-r--r--pyload/plugin/hoster/SharebeesCom.py15
-rw-r--r--pyload/plugin/hoster/ShareonlineBiz.py184
-rw-r--r--pyload/plugin/hoster/ShareplaceCom.py (renamed from module/plugins/hoster/ShareplaceCom.py)0
-rw-r--r--pyload/plugin/hoster/SharingmatrixCom.py16
-rw-r--r--pyload/plugin/hoster/ShragleCom.py16
-rw-r--r--pyload/plugin/hoster/SimplyPremiumCom.py78
-rw-r--r--pyload/plugin/hoster/SimplydebridCom.py45
-rw-r--r--pyload/plugin/hoster/SmoozedCom.py63
-rw-r--r--pyload/plugin/hoster/SockshareCom.py17
-rw-r--r--pyload/plugin/hoster/SoundcloudCom.py (renamed from module/plugins/hoster/SoundcloudCom.py)0
-rw-r--r--pyload/plugin/hoster/SpeedLoadOrg.py15
-rw-r--r--pyload/plugin/hoster/SpeedfileCz.py15
-rw-r--r--pyload/plugin/hoster/SpeedyshareCom.py41
-rw-r--r--pyload/plugin/hoster/StorageTo.py15
-rw-r--r--pyload/plugin/hoster/StreamCz.py (renamed from module/plugins/hoster/StreamCz.py)0
-rw-r--r--pyload/plugin/hoster/StreamcloudEu.py28
-rw-r--r--pyload/plugin/hoster/TurbobitNet.py164
-rw-r--r--pyload/plugin/hoster/TurbouploadCom.py15
-rw-r--r--pyload/plugin/hoster/TusfilesNet.py37
-rw-r--r--pyload/plugin/hoster/TwoSharedCom.py29
-rw-r--r--pyload/plugin/hoster/UlozTo.py155
-rw-r--r--pyload/plugin/hoster/UloziskoSk.py68
-rw-r--r--pyload/plugin/hoster/UnibytesCom.py70
-rw-r--r--pyload/plugin/hoster/UnrestrictLi.py82
-rw-r--r--pyload/plugin/hoster/UpleaCom.py56
-rw-r--r--pyload/plugin/hoster/UploadStationCom.py16
-rw-r--r--pyload/plugin/hoster/UploadableCh.py76
-rw-r--r--pyload/plugin/hoster/UploadboxCom.py15
-rw-r--r--pyload/plugin/hoster/UploadedTo.py117
-rw-r--r--pyload/plugin/hoster/UploadhereCom.py15
-rw-r--r--pyload/plugin/hoster/UploadheroCom.py73
-rw-r--r--pyload/plugin/hoster/UploadingCom.py96
-rw-r--r--pyload/plugin/hoster/UploadkingCom.py15
-rw-r--r--pyload/plugin/hoster/UpstoreNet.py69
-rw-r--r--pyload/plugin/hoster/UptoboxCom.py29
-rw-r--r--pyload/plugin/hoster/VeehdCom.py (renamed from module/plugins/hoster/VeehdCom.py)0
-rw-r--r--pyload/plugin/hoster/VeohCom.py51
-rw-r--r--pyload/plugin/hoster/VidPlayNet.py21
-rw-r--r--pyload/plugin/hoster/VimeoCom.py71
-rw-r--r--pyload/plugin/hoster/Vipleech4UCom.py15
-rw-r--r--pyload/plugin/hoster/WarserverCz.py15
-rw-r--r--pyload/plugin/hoster/WebshareCz.py60
-rw-r--r--pyload/plugin/hoster/WrzucTo.py49
-rw-r--r--pyload/plugin/hoster/WuploadCom.py16
-rw-r--r--pyload/plugin/hoster/X7To.py15
-rw-r--r--pyload/plugin/hoster/XFileSharingPro.py59
-rw-r--r--pyload/plugin/hoster/XHamsterCom.py (renamed from module/plugins/hoster/XHamsterCom.py)0
-rw-r--r--pyload/plugin/hoster/XVideosCom.py (renamed from module/plugins/hoster/XVideosCom.py)0
-rw-r--r--pyload/plugin/hoster/XdadevelopersCom.py35
-rw-r--r--pyload/plugin/hoster/Xdcc.py (renamed from module/plugins/hoster/Xdcc.py)0
-rw-r--r--pyload/plugin/hoster/YibaishiwuCom.py56
-rw-r--r--pyload/plugin/hoster/YoupornCom.py (renamed from module/plugins/hoster/YoupornCom.py)0
-rw-r--r--pyload/plugin/hoster/YourfilesTo.py (renamed from module/plugins/hoster/YourfilesTo.py)0
-rw-r--r--pyload/plugin/hoster/YoutubeCom.py (renamed from module/plugins/hoster/YoutubeCom.py)0
-rw-r--r--pyload/plugin/hoster/ZDF.py (renamed from module/plugins/hoster/ZDF.py)0
-rw-r--r--pyload/plugin/hoster/ZShareNet.py16
-rw-r--r--pyload/plugin/hoster/ZeveraCom.py31
-rw-r--r--pyload/plugin/hoster/ZippyshareCom.py62
-rw-r--r--pyload/plugin/hoster/__init__.py (renamed from module/plugins/internal/__init__.py)0
-rw-r--r--pyload/plugin/internal/BasePlugin.py92
-rw-r--r--pyload/plugin/internal/DeadCrypter.py27
-rw-r--r--pyload/plugin/internal/DeadHoster.py27
-rw-r--r--pyload/plugin/internal/MultiHook.py308
-rw-r--r--pyload/plugin/internal/MultiHoster.py85
-rw-r--r--pyload/plugin/internal/SimpleCrypter.py157
-rw-r--r--pyload/plugin/internal/SimpleDereferer.py98
-rw-r--r--pyload/plugin/internal/SimpleHoster.py701
-rw-r--r--pyload/plugin/internal/UpdateManager.py306
-rw-r--r--pyload/plugin/internal/XFSAccount.py (renamed from module/plugins/internal/XFSAccount.py)0
-rw-r--r--pyload/plugin/internal/XFSCrypter.py45
-rw-r--r--pyload/plugin/internal/XFSHoster.py326
-rw-r--r--pyload/plugin/internal/__init__.py (renamed from module/plugins/ocr/__init__.py)0
-rw-r--r--pyload/plugin/ocr/GigasizeCom.py (renamed from module/plugins/ocr/GigasizeCom.py)0
-rw-r--r--pyload/plugin/ocr/LinksaveIn.py (renamed from module/plugins/ocr/LinksaveIn.py)0
-rw-r--r--pyload/plugin/ocr/NetloadIn.py (renamed from module/plugins/ocr/NetloadIn.py)0
-rw-r--r--pyload/plugin/ocr/ShareonlineBiz.py (renamed from module/plugins/ocr/ShareonlineBiz.py)0
-rw-r--r--pyload/plugin/ocr/__init__.py (renamed from module/remote/socketbackend/__init__.py)0
-rw-r--r--pyload/remote/ClickAndLoadBackend.py (renamed from module/remote/ClickAndLoadBackend.py)0
-rw-r--r--pyload/remote/SocketBackend.py (renamed from module/remote/SocketBackend.py)0
-rw-r--r--pyload/remote/ThriftBackend.py (renamed from module/remote/ThriftBackend.py)0
-rw-r--r--pyload/remote/__init__.py (renamed from module/remote/__init__.py)0
-rw-r--r--pyload/remote/socketbackend/__init__.py (renamed from module/remote/thriftbackend/__init__.py)0
-rw-r--r--pyload/remote/socketbackend/create_ttypes.py (renamed from module/remote/socketbackend/create_ttypes.py)0
-rw-r--r--pyload/remote/thriftbackend/Processor.py (renamed from module/remote/thriftbackend/Processor.py)0
-rw-r--r--pyload/remote/thriftbackend/Protocol.py (renamed from module/remote/thriftbackend/Protocol.py)0
-rw-r--r--pyload/remote/thriftbackend/Socket.py (renamed from module/remote/thriftbackend/Socket.py)0
-rw-r--r--pyload/remote/thriftbackend/ThriftClient.py (renamed from module/remote/thriftbackend/ThriftClient.py)0
-rw-r--r--pyload/remote/thriftbackend/ThriftTest.py (renamed from module/remote/thriftbackend/ThriftTest.py)0
-rw-r--r--pyload/remote/thriftbackend/Transport.py (renamed from module/remote/thriftbackend/Transport.py)0
-rw-r--r--pyload/remote/thriftbackend/__init__.py (renamed from module/remote/thriftbackend/thriftgen/__init__.py)0
-rw-r--r--pyload/remote/thriftbackend/pyload.thrift (renamed from module/remote/thriftbackend/pyload.thrift)0
-rw-r--r--pyload/remote/thriftbackend/thriftgen/__init__.py1
-rw-r--r--pyload/remote/thriftbackend/thriftgen/pyload/Pyload-remote (renamed from module/remote/thriftbackend/thriftgen/pyload/Pyload-remote)0
-rw-r--r--pyload/remote/thriftbackend/thriftgen/pyload/Pyload.py (renamed from module/remote/thriftbackend/thriftgen/pyload/Pyload.py)0
-rw-r--r--pyload/remote/thriftbackend/thriftgen/pyload/__init__.py (renamed from module/remote/thriftbackend/thriftgen/pyload/__init__.py)0
-rw-r--r--pyload/remote/thriftbackend/thriftgen/pyload/constants.py (renamed from module/remote/thriftbackend/thriftgen/pyload/constants.py)0
-rw-r--r--pyload/remote/thriftbackend/thriftgen/pyload/ttypes.py (renamed from module/remote/thriftbackend/thriftgen/pyload/ttypes.py)0
-rw-r--r--pyload/utils/__init__.py (renamed from module/utils/__init__.py)0
-rw-r--r--pyload/utils/packagetools.py (renamed from module/utils/packagetools.py)0
-rw-r--r--pyload/utils/printer.py (renamed from module/utils/printer.py)0
-rw-r--r--pyload/utils/pylgettext.py (renamed from module/utils/pylgettext.py)0
-rw-r--r--pyload/webui/__init__.py (renamed from module/webui/__init__.py)0
-rw-r--r--pyload/webui/app/__init__.py (renamed from module/webui/app/__init__.py)0
-rw-r--r--pyload/webui/app/api.py (renamed from module/webui/app/api.py)0
-rw-r--r--pyload/webui/app/cnl.py (renamed from module/webui/app/cnl.py)0
-rw-r--r--pyload/webui/app/json.py (renamed from module/webui/app/json.py)0
-rw-r--r--pyload/webui/app/pyload.py (renamed from module/webui/app/pyload.py)0
-rw-r--r--pyload/webui/app/utils.py (renamed from module/webui/app/utils.py)0
-rw-r--r--pyload/webui/filters.py (renamed from module/webui/filters.py)0
-rw-r--r--pyload/webui/middlewares.py (renamed from module/webui/middlewares.py)0
-rw-r--r--pyload/webui/servers/lighttpd_default.conf (renamed from module/webui/servers/lighttpd_default.conf)0
-rw-r--r--pyload/webui/servers/nginx_default.conf (renamed from module/webui/servers/nginx_default.conf)0
-rw-r--r--pyload/webui/themes/Dark/css/MooDialog.css (renamed from module/webui/themes/Dark/css/MooDialog.css)0
-rw-r--r--pyload/webui/themes/Dark/css/base.css (renamed from module/webui/themes/Dark/css/base.css)0
-rw-r--r--pyload/webui/themes/Dark/css/log.css (renamed from module/webui/themes/Dark/css/log.css)0
-rw-r--r--pyload/webui/themes/Dark/css/pathchooser.css (renamed from module/webui/themes/Dark/css/pathchooser.css)0
-rw-r--r--pyload/webui/themes/Dark/css/window.css (renamed from module/webui/themes/Dark/css/window.css)0
-rw-r--r--pyload/webui/themes/Dark/img/MooDialog/dialog-close.png (renamed from module/webui/themes/Dark/img/MooDialog/dialog-close.png)bin689 -> 689 bytes
-rw-r--r--pyload/webui/themes/Dark/img/MooDialog/dialog-error.png (renamed from module/webui/themes/Dark/img/MooDialog/dialog-error.png)bin1472 -> 1472 bytes
-rw-r--r--pyload/webui/themes/Dark/img/MooDialog/dialog-question.png (renamed from module/webui/themes/Dark/img/MooDialog/dialog-question.png)bin2073 -> 2073 bytes
-rw-r--r--pyload/webui/themes/Dark/img/MooDialog/dialog-warning.png (renamed from module/webui/themes/Dark/img/MooDialog/dialog-warning.png)bin1651 -> 1651 bytes
-rw-r--r--pyload/webui/themes/Dark/img/button.png (renamed from module/webui/themes/Dark/img/button.png)bin569 -> 569 bytes
-rw-r--r--pyload/webui/themes/Dark/img/dark-bg.jpg (renamed from module/webui/themes/Dark/img/dark-bg.jpg)bin40930 -> 40930 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/add_folder.png (renamed from module/webui/themes/Dark/img/default/add_folder.png)bin571 -> 571 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/ajax-loader.gif (renamed from module/webui/themes/Dark/img/default/ajax-loader.gif)bin404 -> 404 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/arrow_refresh.png (renamed from module/webui/themes/Dark/img/default/arrow_refresh.png)bin685 -> 685 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/arrow_right.png (renamed from module/webui/themes/Dark/img/default/arrow_right.png)bin349 -> 349 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/big_button.gif (renamed from module/webui/themes/Dark/img/default/big_button.gif)bin1905 -> 1905 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/big_button_over.gif (renamed from module/webui/themes/Dark/img/default/big_button_over.gif)bin728 -> 728 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/body.png (renamed from module/webui/themes/Dark/img/default/body.png)bin402 -> 402 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/closebtn.gif (renamed from module/webui/themes/Dark/img/default/closebtn.gif)bin254 -> 254 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/cog.png (renamed from module/webui/themes/Dark/img/default/cog.png)bin512 -> 512 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/control_add.png (renamed from module/webui/themes/Dark/img/default/control_add.png)bin446 -> 446 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/control_add_blue.png (renamed from module/webui/themes/Dark/img/default/control_add_blue.png)bin845 -> 845 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/control_cancel.png (renamed from module/webui/themes/Dark/img/default/control_cancel.png)bin3349 -> 3349 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/control_cancel_blue.png (renamed from module/webui/themes/Dark/img/default/control_cancel_blue.png)bin787 -> 787 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/control_pause.png (renamed from module/webui/themes/Dark/img/default/control_pause.png)bin598 -> 598 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/control_pause_blue.png (renamed from module/webui/themes/Dark/img/default/control_pause_blue.png)bin721 -> 721 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/control_play.png (renamed from module/webui/themes/Dark/img/default/control_play.png)bin592 -> 592 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/control_play_blue.png (renamed from module/webui/themes/Dark/img/default/control_play_blue.png)bin717 -> 717 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/control_stop.png (renamed from module/webui/themes/Dark/img/default/control_stop.png)bin403 -> 403 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/control_stop_blue.png (renamed from module/webui/themes/Dark/img/default/control_stop_blue.png)bin695 -> 695 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/delete.png (renamed from module/webui/themes/Dark/img/default/delete.png)bin715 -> 715 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/drag_corner.gif (renamed from module/webui/themes/Dark/img/default/drag_corner.gif)bin76 -> 76 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/error.png (renamed from module/webui/themes/Dark/img/default/error.png)bin701 -> 701 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/folder.png (renamed from module/webui/themes/Dark/img/default/folder.png)bin537 -> 537 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/full.png (renamed from module/webui/themes/Dark/img/default/full.png)bin3543 -> 3543 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/head-login.png (renamed from module/webui/themes/Dark/img/default/head-login.png)bin1288 -> 1288 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/head-menu-collector.png (renamed from module/webui/themes/Dark/img/default/head-menu-collector.png)bin1953 -> 1953 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/head-menu-config.png (renamed from module/webui/themes/Dark/img/default/head-menu-config.png)bin1802 -> 1802 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/head-menu-development.png (renamed from module/webui/themes/Dark/img/default/head-menu-development.png)bin876 -> 876 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/head-menu-download.png (renamed from module/webui/themes/Dark/img/default/head-menu-download.png)bin721 -> 721 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/head-menu-home.png (renamed from module/webui/themes/Dark/img/default/head-menu-home.png)bin920 -> 920 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/head-menu-index.png (renamed from module/webui/themes/Dark/img/default/head-menu-index.png)bin482 -> 482 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/head-menu-news.png (renamed from module/webui/themes/Dark/img/default/head-menu-news.png)bin628 -> 628 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/head-menu-queue.png (renamed from module/webui/themes/Dark/img/default/head-menu-queue.png)bin2629 -> 2629 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/head-menu-recent.png (renamed from module/webui/themes/Dark/img/default/head-menu-recent.png)bin932 -> 932 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/head-menu-wiki.png (renamed from module/webui/themes/Dark/img/default/head-menu-wiki.png)bin1204 -> 1204 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/head-search-noshadow.png (renamed from module/webui/themes/Dark/img/default/head-search-noshadow.png)bin1187 -> 1187 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/head_bg1.png (renamed from module/webui/themes/Dark/img/default/head_bg1.png)bin125 -> 125 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/images.png (renamed from module/webui/themes/Dark/img/default/images.png)bin661 -> 661 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/notice.png (renamed from module/webui/themes/Dark/img/default/notice.png)bin778 -> 778 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/package_go.png (renamed from module/webui/themes/Dark/img/default/package_go.png)bin898 -> 898 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/page-tools-backlinks.png (renamed from module/webui/themes/Dark/img/default/page-tools-backlinks.png)bin540 -> 540 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/page-tools-edit.png (renamed from module/webui/themes/Dark/img/default/page-tools-edit.png)bin574 -> 574 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/page-tools-revisions.png (renamed from module/webui/themes/Dark/img/default/page-tools-revisions.png)bin603 -> 603 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/parseUri.png (renamed from module/webui/themes/Dark/img/default/parseUri.png)bin666 -> 666 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/pencil.png (renamed from module/webui/themes/Dark/img/default/pencil.png)bin450 -> 450 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/reconnect.png (renamed from module/webui/themes/Dark/img/default/reconnect.png)bin755 -> 755 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/status_None.png (renamed from module/webui/themes/Dark/img/default/status_None.png)bin7613 -> 7613 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/status_downloading.png (renamed from module/webui/themes/Dark/img/default/status_downloading.png)bin943 -> 943 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/status_failed.png (renamed from module/webui/themes/Dark/img/default/status_failed.png)bin701 -> 701 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/status_finished.png (renamed from module/webui/themes/Dark/img/default/status_finished.png)bin781 -> 781 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/status_offline.png (renamed from module/webui/themes/Dark/img/default/status_offline.png)bin700 -> 700 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/status_proc.png (renamed from module/webui/themes/Dark/img/default/status_proc.png)bin512 -> 512 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/status_queue.png (renamed from module/webui/themes/Dark/img/default/status_queue.png)bin7613 -> 7613 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/status_waiting.png (renamed from module/webui/themes/Dark/img/default/status_waiting.png)bin889 -> 889 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/success.png (renamed from module/webui/themes/Dark/img/default/success.png)bin781 -> 781 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/tabs-border-bottom.png (renamed from module/webui/themes/Dark/img/default/tabs-border-bottom.png)bin163 -> 163 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/user-actions-logout.png (renamed from module/webui/themes/Dark/img/default/user-actions-logout.png)bin799 -> 799 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/user-actions-profile.png (renamed from module/webui/themes/Dark/img/default/user-actions-profile.png)bin628 -> 628 bytes
-rw-r--r--pyload/webui/themes/Dark/img/default/user-info.png (renamed from module/webui/themes/Dark/img/default/user-info.png)bin3963 -> 3963 bytes
-rw-r--r--pyload/webui/themes/Dark/img/pyload-logo.png (renamed from module/webui/themes/Dark/img/pyload-logo.png)bin6947 -> 6947 bytes
-rw-r--r--pyload/webui/themes/Dark/img/tab-background.png (renamed from module/webui/themes/Dark/img/tab-background.png)bin3044 -> 3044 bytes
-rw-r--r--pyload/webui/themes/Dark/js/render/admin.coffee (renamed from module/webui/themes/Dark/js/render/admin.coffee)0
-rw-r--r--pyload/webui/themes/Dark/js/render/admin.min.js (renamed from module/webui/themes/Dark/js/render/admin.min.js)0
-rw-r--r--pyload/webui/themes/Dark/js/render/base.coffee (renamed from module/webui/themes/Dark/js/render/base.coffee)0
-rw-r--r--pyload/webui/themes/Dark/js/render/base.min.js (renamed from module/webui/themes/Dark/js/render/base.min.js)0
-rw-r--r--pyload/webui/themes/Dark/js/render/package.js (renamed from module/webui/themes/Dark/js/render/package.js)0
-rw-r--r--pyload/webui/themes/Dark/js/render/settings.coffee (renamed from module/webui/themes/Dark/js/render/settings.coffee)0
-rw-r--r--pyload/webui/themes/Dark/js/render/settings.min.js (renamed from module/webui/themes/Dark/js/render/settings.min.js)0
-rw-r--r--pyload/webui/themes/Dark/js/static/MooDialog.js (renamed from module/webui/themes/Dark/js/static/MooDialog.js)0
-rw-r--r--pyload/webui/themes/Dark/js/static/MooDialog.min.js (renamed from module/webui/themes/Dark/js/static/MooDialog.min.js)0
-rw-r--r--pyload/webui/themes/Dark/js/static/MooDropMenu.js (renamed from module/webui/themes/Dark/js/static/MooDropMenu.js)0
-rw-r--r--pyload/webui/themes/Dark/js/static/MooDropMenu.min.js (renamed from module/webui/themes/Dark/js/static/MooDropMenu.min.js)0
-rw-r--r--pyload/webui/themes/Dark/js/static/mootools-core.js (renamed from module/webui/themes/Dark/js/static/mootools-core.js)0
-rw-r--r--pyload/webui/themes/Dark/js/static/mootools-core.min.js (renamed from module/webui/themes/Dark/js/static/mootools-core.min.js)0
-rw-r--r--pyload/webui/themes/Dark/js/static/mootools-more.js (renamed from module/webui/themes/Dark/js/static/mootools-more.js)0
-rw-r--r--pyload/webui/themes/Dark/js/static/mootools-more.min.js (renamed from module/webui/themes/Dark/js/static/mootools-more.min.js)0
-rw-r--r--pyload/webui/themes/Dark/js/static/purr.js (renamed from module/webui/themes/Dark/js/static/purr.js)0
-rw-r--r--pyload/webui/themes/Dark/js/static/purr.min.js (renamed from module/webui/themes/Dark/js/static/purr.min.js)0
-rw-r--r--pyload/webui/themes/Dark/js/static/tinytab.js (renamed from module/webui/themes/Dark/js/static/tinytab.js)0
-rw-r--r--pyload/webui/themes/Dark/js/static/tinytab.min.js (renamed from module/webui/themes/Dark/js/static/tinytab.min.js)0
-rw-r--r--pyload/webui/themes/Dark/tml/admin.html (renamed from module/webui/themes/Dark/tml/admin.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/base.html (renamed from module/webui/themes/Dark/tml/base.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/captcha.html (renamed from module/webui/themes/Dark/tml/captcha.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/downloads.html (renamed from module/webui/themes/Dark/tml/downloads.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/folder.html (renamed from module/webui/themes/Dark/tml/folder.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/home.html (renamed from module/webui/themes/Dark/tml/home.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/info.html (renamed from module/webui/themes/Dark/tml/info.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/login.html (renamed from module/webui/themes/Dark/tml/login.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/logout.html (renamed from module/webui/themes/Dark/tml/logout.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/logs.html (renamed from module/webui/themes/Dark/tml/logs.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/pathchooser.html (renamed from module/webui/themes/Dark/tml/pathchooser.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/queue.html (renamed from module/webui/themes/Dark/tml/queue.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/settings.html (renamed from module/webui/themes/Dark/tml/settings.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/settings_item.html (renamed from module/webui/themes/Dark/tml/settings_item.html)0
-rw-r--r--pyload/webui/themes/Dark/tml/window.html (renamed from module/webui/themes/Dark/tml/window.html)0
-rw-r--r--pyload/webui/themes/Default/css/MooDialog.css (renamed from module/webui/themes/Default/css/MooDialog.css)0
-rw-r--r--pyload/webui/themes/Default/css/base.css (renamed from module/webui/themes/Default/css/base.css)0
-rw-r--r--pyload/webui/themes/Default/css/log.css (renamed from module/webui/themes/Default/css/log.css)0
-rw-r--r--pyload/webui/themes/Default/css/pathchooser.css (renamed from module/webui/themes/Default/css/pathchooser.css)0
-rw-r--r--pyload/webui/themes/Default/css/window.css (renamed from module/webui/themes/Default/css/window.css)0
-rw-r--r--pyload/webui/themes/Default/img/MooDialog/dialog-close.png (renamed from module/webui/themes/Default/img/MooDialog/dialog-close.png)bin689 -> 689 bytes
-rw-r--r--pyload/webui/themes/Default/img/MooDialog/dialog-error.png (renamed from module/webui/themes/Default/img/MooDialog/dialog-error.png)bin1472 -> 1472 bytes
-rw-r--r--pyload/webui/themes/Default/img/MooDialog/dialog-question.png (renamed from module/webui/themes/Default/img/MooDialog/dialog-question.png)bin2073 -> 2073 bytes
-rw-r--r--pyload/webui/themes/Default/img/MooDialog/dialog-warning.png (renamed from module/webui/themes/Default/img/MooDialog/dialog-warning.png)bin1651 -> 1651 bytes
-rw-r--r--pyload/webui/themes/Default/img/add_folder.png (renamed from module/webui/themes/Default/img/add_folder.png)bin571 -> 571 bytes
-rw-r--r--pyload/webui/themes/Default/img/ajax-loader.gif (renamed from module/webui/themes/Default/img/ajax-loader.gif)bin404 -> 404 bytes
-rw-r--r--pyload/webui/themes/Default/img/arrow_refresh.png (renamed from module/webui/themes/Default/img/arrow_refresh.png)bin685 -> 685 bytes
-rw-r--r--pyload/webui/themes/Default/img/arrow_right.png (renamed from module/webui/themes/Default/img/arrow_right.png)bin349 -> 349 bytes
-rw-r--r--pyload/webui/themes/Default/img/big_button.gif (renamed from module/webui/themes/Default/img/big_button.gif)bin1905 -> 1905 bytes
-rw-r--r--pyload/webui/themes/Default/img/big_button_over.gif (renamed from module/webui/themes/Default/img/big_button_over.gif)bin728 -> 728 bytes
-rw-r--r--pyload/webui/themes/Default/img/body.png (renamed from module/webui/themes/Default/img/body.png)bin402 -> 402 bytes
-rw-r--r--pyload/webui/themes/Default/img/button.png (renamed from module/webui/themes/Default/img/button.png)bin452 -> 452 bytes
-rw-r--r--pyload/webui/themes/Default/img/closebtn.gif (renamed from module/webui/themes/Default/img/closebtn.gif)bin254 -> 254 bytes
-rw-r--r--pyload/webui/themes/Default/img/cog.png (renamed from module/webui/themes/Default/img/cog.png)bin512 -> 512 bytes
-rw-r--r--pyload/webui/themes/Default/img/control_add.png (renamed from module/webui/themes/Default/img/control_add.png)bin446 -> 446 bytes
-rw-r--r--pyload/webui/themes/Default/img/control_add_blue.png (renamed from module/webui/themes/Default/img/control_add_blue.png)bin845 -> 845 bytes
-rw-r--r--pyload/webui/themes/Default/img/control_cancel.png (renamed from module/webui/themes/Default/img/control_cancel.png)bin3349 -> 3349 bytes
-rw-r--r--pyload/webui/themes/Default/img/control_cancel_blue.png (renamed from module/webui/themes/Default/img/control_cancel_blue.png)bin787 -> 787 bytes
-rw-r--r--pyload/webui/themes/Default/img/control_pause.png (renamed from module/webui/themes/Default/img/control_pause.png)bin598 -> 598 bytes
-rw-r--r--pyload/webui/themes/Default/img/control_pause_blue.png (renamed from module/webui/themes/Default/img/control_pause_blue.png)bin721 -> 721 bytes
-rw-r--r--pyload/webui/themes/Default/img/control_play.png (renamed from module/webui/themes/Default/img/control_play.png)bin592 -> 592 bytes
-rw-r--r--pyload/webui/themes/Default/img/control_play_blue.png (renamed from module/webui/themes/Default/img/control_play_blue.png)bin717 -> 717 bytes
-rw-r--r--pyload/webui/themes/Default/img/control_stop.png (renamed from module/webui/themes/Default/img/control_stop.png)bin403 -> 403 bytes
-rw-r--r--pyload/webui/themes/Default/img/control_stop_blue.png (renamed from module/webui/themes/Default/img/control_stop_blue.png)bin695 -> 695 bytes
-rw-r--r--pyload/webui/themes/Default/img/delete.png (renamed from module/webui/themes/Default/img/delete.png)bin715 -> 715 bytes
-rw-r--r--pyload/webui/themes/Default/img/drag_corner.gif (renamed from module/webui/themes/Default/img/drag_corner.gif)bin76 -> 76 bytes
-rw-r--r--pyload/webui/themes/Default/img/error.png (renamed from module/webui/themes/Default/img/error.png)bin701 -> 701 bytes
-rw-r--r--pyload/webui/themes/Default/img/folder.png (renamed from module/webui/themes/Default/img/folder.png)bin537 -> 537 bytes
-rw-r--r--pyload/webui/themes/Default/img/full.png (renamed from module/webui/themes/Default/img/full.png)bin3543 -> 3543 bytes
-rw-r--r--pyload/webui/themes/Default/img/head-login.png (renamed from module/webui/themes/Default/img/head-login.png)bin1288 -> 1288 bytes
-rw-r--r--pyload/webui/themes/Default/img/head-menu-collector.png (renamed from module/webui/themes/Default/img/head-menu-collector.png)bin1953 -> 1953 bytes
-rw-r--r--pyload/webui/themes/Default/img/head-menu-config.png (renamed from module/webui/themes/Default/img/head-menu-config.png)bin1802 -> 1802 bytes
-rw-r--r--pyload/webui/themes/Default/img/head-menu-development.png (renamed from module/webui/themes/Default/img/head-menu-development.png)bin876 -> 876 bytes
-rw-r--r--pyload/webui/themes/Default/img/head-menu-download.png (renamed from module/webui/themes/Default/img/head-menu-download.png)bin721 -> 721 bytes
-rw-r--r--pyload/webui/themes/Default/img/head-menu-home.png (renamed from module/webui/themes/Default/img/head-menu-home.png)bin920 -> 920 bytes
-rw-r--r--pyload/webui/themes/Default/img/head-menu-index.png (renamed from module/webui/themes/Default/img/head-menu-index.png)bin482 -> 482 bytes
-rw-r--r--pyload/webui/themes/Default/img/head-menu-news.png (renamed from module/webui/themes/Default/img/head-menu-news.png)bin628 -> 628 bytes
-rw-r--r--pyload/webui/themes/Default/img/head-menu-queue.png (renamed from module/webui/themes/Default/img/head-menu-queue.png)bin2629 -> 2629 bytes
-rw-r--r--pyload/webui/themes/Default/img/head-menu-recent.png (renamed from module/webui/themes/Default/img/head-menu-recent.png)bin932 -> 932 bytes
-rw-r--r--pyload/webui/themes/Default/img/head-menu-wiki.png (renamed from module/webui/themes/Default/img/head-menu-wiki.png)bin1204 -> 1204 bytes
-rw-r--r--pyload/webui/themes/Default/img/head-search-noshadow.png (renamed from module/webui/themes/Default/img/head-search-noshadow.png)bin1187 -> 1187 bytes
-rw-r--r--pyload/webui/themes/Default/img/head_bg1.png (renamed from module/webui/themes/Default/img/head_bg1.png)bin125 -> 125 bytes
-rw-r--r--pyload/webui/themes/Default/img/images.png (renamed from module/webui/themes/Default/img/images.png)bin661 -> 661 bytes
-rw-r--r--pyload/webui/themes/Default/img/notice.png (renamed from module/webui/themes/Default/img/notice.png)bin778 -> 778 bytes
-rw-r--r--pyload/webui/themes/Default/img/package_go.png (renamed from module/webui/themes/Default/img/package_go.png)bin898 -> 898 bytes
-rw-r--r--pyload/webui/themes/Default/img/page-tools-backlinks.png (renamed from module/webui/themes/Default/img/page-tools-backlinks.png)bin540 -> 540 bytes
-rw-r--r--pyload/webui/themes/Default/img/page-tools-edit.png (renamed from module/webui/themes/Default/img/page-tools-edit.png)bin574 -> 574 bytes
-rw-r--r--pyload/webui/themes/Default/img/page-tools-revisions.png (renamed from module/webui/themes/Default/img/page-tools-revisions.png)bin603 -> 603 bytes
-rw-r--r--pyload/webui/themes/Default/img/parseUri.png (renamed from module/webui/themes/Default/img/parseUri.png)bin666 -> 666 bytes
-rw-r--r--pyload/webui/themes/Default/img/pencil.png (renamed from module/webui/themes/Default/img/pencil.png)bin450 -> 450 bytes
-rw-r--r--pyload/webui/themes/Default/img/pyload-logo.png (renamed from module/webui/themes/Default/img/pyload-logo.png)bin8457 -> 8457 bytes
-rw-r--r--pyload/webui/themes/Default/img/reconnect.png (renamed from module/webui/themes/Default/img/reconnect.png)bin755 -> 755 bytes
-rw-r--r--pyload/webui/themes/Default/img/status_None.png (renamed from module/webui/themes/Default/img/status_None.png)bin7613 -> 7613 bytes
-rw-r--r--pyload/webui/themes/Default/img/status_downloading.png (renamed from module/webui/themes/Default/img/status_downloading.png)bin943 -> 943 bytes
-rw-r--r--pyload/webui/themes/Default/img/status_failed.png (renamed from module/webui/themes/Default/img/status_failed.png)bin701 -> 701 bytes
-rw-r--r--pyload/webui/themes/Default/img/status_finished.png (renamed from module/webui/themes/Default/img/status_finished.png)bin781 -> 781 bytes
-rw-r--r--pyload/webui/themes/Default/img/status_offline.png (renamed from module/webui/themes/Default/img/status_offline.png)bin700 -> 700 bytes
-rw-r--r--pyload/webui/themes/Default/img/status_proc.png (renamed from module/webui/themes/Default/img/status_proc.png)bin512 -> 512 bytes
-rw-r--r--pyload/webui/themes/Default/img/status_queue.png (renamed from module/webui/themes/Default/img/status_queue.png)bin7613 -> 7613 bytes
-rw-r--r--pyload/webui/themes/Default/img/status_waiting.png (renamed from module/webui/themes/Default/img/status_waiting.png)bin889 -> 889 bytes
-rw-r--r--pyload/webui/themes/Default/img/success.png (renamed from module/webui/themes/Default/img/success.png)bin781 -> 781 bytes
-rw-r--r--pyload/webui/themes/Default/img/tab-background.png (renamed from module/webui/themes/Default/img/tab-background.png)bin179 -> 179 bytes
-rw-r--r--pyload/webui/themes/Default/img/tabs-border-bottom.png (renamed from module/webui/themes/Default/img/tabs-border-bottom.png)bin163 -> 163 bytes
-rw-r--r--pyload/webui/themes/Default/img/user-actions-logout.png (renamed from module/webui/themes/Default/img/user-actions-logout.png)bin799 -> 799 bytes
-rw-r--r--pyload/webui/themes/Default/img/user-actions-profile.png (renamed from module/webui/themes/Default/img/user-actions-profile.png)bin628 -> 628 bytes
-rw-r--r--pyload/webui/themes/Default/img/user-info.png (renamed from module/webui/themes/Default/img/user-info.png)bin3963 -> 3963 bytes
-rw-r--r--pyload/webui/themes/Default/js/render/admin.coffee (renamed from module/webui/themes/Default/js/render/admin.coffee)0
-rw-r--r--pyload/webui/themes/Default/js/render/admin.min.js (renamed from module/webui/themes/Default/js/render/admin.min.js)0
-rw-r--r--pyload/webui/themes/Default/js/render/base.coffee (renamed from module/webui/themes/Default/js/render/base.coffee)0
-rw-r--r--pyload/webui/themes/Default/js/render/base.min.js (renamed from module/webui/themes/Default/js/render/base.min.js)0
-rw-r--r--pyload/webui/themes/Default/js/render/package.js (renamed from module/webui/themes/Default/js/render/package.js)0
-rw-r--r--pyload/webui/themes/Default/js/render/settings.coffee (renamed from module/webui/themes/Default/js/render/settings.coffee)0
-rw-r--r--pyload/webui/themes/Default/js/render/settings.min.js (renamed from module/webui/themes/Default/js/render/settings.min.js)0
-rw-r--r--pyload/webui/themes/Default/js/static/MooDialog.js (renamed from module/webui/themes/Default/js/static/MooDialog.js)0
-rw-r--r--pyload/webui/themes/Default/js/static/MooDialog.min.js (renamed from module/webui/themes/Default/js/static/MooDialog.min.js)0
-rw-r--r--pyload/webui/themes/Default/js/static/MooDropMenu.js (renamed from module/webui/themes/Default/js/static/MooDropMenu.js)0
-rw-r--r--pyload/webui/themes/Default/js/static/MooDropMenu.min.js (renamed from module/webui/themes/Default/js/static/MooDropMenu.min.js)0
-rw-r--r--pyload/webui/themes/Default/js/static/mootools-core.js (renamed from module/webui/themes/Default/js/static/mootools-core.js)0
-rw-r--r--pyload/webui/themes/Default/js/static/mootools-core.min.js (renamed from module/webui/themes/Default/js/static/mootools-core.min.js)0
-rw-r--r--pyload/webui/themes/Default/js/static/mootools-more.js (renamed from module/webui/themes/Default/js/static/mootools-more.js)0
-rw-r--r--pyload/webui/themes/Default/js/static/mootools-more.min.js (renamed from module/webui/themes/Default/js/static/mootools-more.min.js)0
-rw-r--r--pyload/webui/themes/Default/js/static/purr.js (renamed from module/webui/themes/Default/js/static/purr.js)0
-rw-r--r--pyload/webui/themes/Default/js/static/purr.min.js (renamed from module/webui/themes/Default/js/static/purr.min.js)0
-rw-r--r--pyload/webui/themes/Default/js/static/tinytab.js (renamed from module/webui/themes/Default/js/static/tinytab.js)0
-rw-r--r--pyload/webui/themes/Default/js/static/tinytab.min.js (renamed from module/webui/themes/Default/js/static/tinytab.min.js)0
-rw-r--r--pyload/webui/themes/Default/tml/admin.html (renamed from module/webui/themes/Default/tml/admin.html)0
-rw-r--r--pyload/webui/themes/Default/tml/base.html (renamed from module/webui/themes/Default/tml/base.html)0
-rw-r--r--pyload/webui/themes/Default/tml/captcha.html (renamed from module/webui/themes/Default/tml/captcha.html)0
-rw-r--r--pyload/webui/themes/Default/tml/downloads.html (renamed from module/webui/themes/Default/tml/downloads.html)0
-rw-r--r--pyload/webui/themes/Default/tml/filemanager.html (renamed from module/webui/themes/Default/tml/filemanager.html)0
-rw-r--r--pyload/webui/themes/Default/tml/folder.html (renamed from module/webui/themes/Default/tml/folder.html)0
-rw-r--r--pyload/webui/themes/Default/tml/home.html (renamed from module/webui/themes/Default/tml/home.html)0
-rw-r--r--pyload/webui/themes/Default/tml/info.html (renamed from module/webui/themes/Default/tml/info.html)0
-rw-r--r--pyload/webui/themes/Default/tml/login.html (renamed from module/webui/themes/Default/tml/login.html)0
-rw-r--r--pyload/webui/themes/Default/tml/logout.html (renamed from module/webui/themes/Default/tml/logout.html)0
-rw-r--r--pyload/webui/themes/Default/tml/logs.html (renamed from module/webui/themes/Default/tml/logs.html)0
-rw-r--r--pyload/webui/themes/Default/tml/pathchooser.html (renamed from module/webui/themes/Default/tml/pathchooser.html)0
-rw-r--r--pyload/webui/themes/Default/tml/queue.html (renamed from module/webui/themes/Default/tml/queue.html)0
-rw-r--r--pyload/webui/themes/Default/tml/settings.html (renamed from module/webui/themes/Default/tml/settings.html)0
-rw-r--r--pyload/webui/themes/Default/tml/settings_item.html (renamed from module/webui/themes/Default/tml/settings_item.html)0
-rw-r--r--pyload/webui/themes/Default/tml/window.html (renamed from module/webui/themes/Default/tml/window.html)0
-rw-r--r--pyload/webui/themes/Flat/css/MooDialog.css (renamed from module/webui/themes/Flat/css/MooDialog.css)0
-rw-r--r--pyload/webui/themes/Flat/css/base.css (renamed from module/webui/themes/Flat/css/base.css)0
-rw-r--r--pyload/webui/themes/Flat/css/log.css (renamed from module/webui/themes/Flat/css/log.css)0
-rw-r--r--pyload/webui/themes/Flat/css/pathchooser.css (renamed from module/webui/themes/Flat/css/pathchooser.css)0
-rw-r--r--pyload/webui/themes/Flat/css/window.css (renamed from module/webui/themes/Flat/css/window.css)0
-rw-r--r--pyload/webui/themes/Flat/img/MooDialog/dialog-close.png (renamed from module/webui/themes/Flat/img/MooDialog/dialog-close.png)bin689 -> 689 bytes
-rw-r--r--pyload/webui/themes/Flat/img/MooDialog/dialog-error.png (renamed from module/webui/themes/Flat/img/MooDialog/dialog-error.png)bin1472 -> 1472 bytes
-rw-r--r--pyload/webui/themes/Flat/img/MooDialog/dialog-question.png (renamed from module/webui/themes/Flat/img/MooDialog/dialog-question.png)bin2073 -> 2073 bytes
-rw-r--r--pyload/webui/themes/Flat/img/MooDialog/dialog-warning.png (renamed from module/webui/themes/Flat/img/MooDialog/dialog-warning.png)bin1651 -> 1651 bytes
-rw-r--r--pyload/webui/themes/Flat/img/arrow_refresh.png (renamed from module/webui/themes/Flat/img/arrow_refresh.png)bin119032 -> 119032 bytes
-rw-r--r--pyload/webui/themes/Flat/img/arrow_right.png (renamed from module/webui/themes/Flat/img/arrow_right.png)bin136967 -> 136967 bytes
-rw-r--r--pyload/webui/themes/Flat/img/button.png (renamed from module/webui/themes/Flat/img/button.png)bin569 -> 569 bytes
-rw-r--r--pyload/webui/themes/Flat/img/cog.png (renamed from module/webui/themes/Flat/img/cog.png)bin137406 -> 137406 bytes
-rw-r--r--pyload/webui/themes/Flat/img/control_add.png (renamed from module/webui/themes/Flat/img/control_add.png)bin116941 -> 116941 bytes
-rw-r--r--pyload/webui/themes/Flat/img/control_add_blue.png (renamed from module/webui/themes/Flat/img/control_add_blue.png)bin116941 -> 116941 bytes
-rw-r--r--pyload/webui/themes/Flat/img/control_cancel.png (renamed from module/webui/themes/Flat/img/control_cancel.png)bin116939 -> 116939 bytes
-rw-r--r--pyload/webui/themes/Flat/img/control_cancel_blue.png (renamed from module/webui/themes/Flat/img/control_cancel_blue.png)bin116939 -> 116939 bytes
-rw-r--r--pyload/webui/themes/Flat/img/control_pause.png (renamed from module/webui/themes/Flat/img/control_pause.png)bin134855 -> 134855 bytes
-rw-r--r--pyload/webui/themes/Flat/img/control_pause_blue.png (renamed from module/webui/themes/Flat/img/control_pause_blue.png)bin134855 -> 134855 bytes
-rw-r--r--pyload/webui/themes/Flat/img/control_play.png (renamed from module/webui/themes/Flat/img/control_play.png)bin134904 -> 134904 bytes
-rw-r--r--pyload/webui/themes/Flat/img/control_play_blue.png (renamed from module/webui/themes/Flat/img/control_play_blue.png)bin134904 -> 134904 bytes
-rw-r--r--pyload/webui/themes/Flat/img/control_stop.png (renamed from module/webui/themes/Flat/img/control_stop.png)bin134835 -> 134835 bytes
-rw-r--r--pyload/webui/themes/Flat/img/control_stop_blue.png (renamed from module/webui/themes/Flat/img/control_stop_blue.png)bin134835 -> 134835 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/add_folder.png (renamed from module/webui/themes/Flat/img/default/add_folder.png)bin571 -> 571 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/ajax-loader.gif (renamed from module/webui/themes/Flat/img/default/ajax-loader.gif)bin404 -> 404 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/big_button.gif (renamed from module/webui/themes/Flat/img/default/big_button.gif)bin1905 -> 1905 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/big_button_over.gif (renamed from module/webui/themes/Flat/img/default/big_button_over.gif)bin728 -> 728 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/body.png (renamed from module/webui/themes/Flat/img/default/body.png)bin402 -> 402 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/closebtn.gif (renamed from module/webui/themes/Flat/img/default/closebtn.gif)bin254 -> 254 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/drag_corner.gif (renamed from module/webui/themes/Flat/img/default/drag_corner.gif)bin76 -> 76 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/full.png (renamed from module/webui/themes/Flat/img/default/full.png)bin3543 -> 3543 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/head-menu-recent.png (renamed from module/webui/themes/Flat/img/default/head-menu-recent.png)bin932 -> 932 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/head_bg1.png (renamed from module/webui/themes/Flat/img/default/head_bg1.png)bin125 -> 125 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/images.png (renamed from module/webui/themes/Flat/img/default/images.png)bin661 -> 661 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/parseUri.png (renamed from module/webui/themes/Flat/img/default/parseUri.png)bin666 -> 666 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/pyload-logo.png (renamed from module/webui/themes/Flat/img/default/pyload-logo.png)bin8457 -> 8457 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/tab-background.png (renamed from module/webui/themes/Flat/img/default/tab-background.png)bin179 -> 179 bytes
-rw-r--r--pyload/webui/themes/Flat/img/default/tabs-border-bottom.png (renamed from module/webui/themes/Flat/img/default/tabs-border-bottom.png)bin163 -> 163 bytes
-rw-r--r--pyload/webui/themes/Flat/img/delete.png (renamed from module/webui/themes/Flat/img/delete.png)bin117658 -> 117658 bytes
-rw-r--r--pyload/webui/themes/Flat/img/error.png (renamed from module/webui/themes/Flat/img/error.png)bin137673 -> 137673 bytes
-rw-r--r--pyload/webui/themes/Flat/img/folder.png (renamed from module/webui/themes/Flat/img/folder.png)bin134669 -> 134669 bytes
-rw-r--r--pyload/webui/themes/Flat/img/head-login.png (renamed from module/webui/themes/Flat/img/head-login.png)bin137406 -> 137406 bytes
-rw-r--r--pyload/webui/themes/Flat/img/head-menu-collector.png (renamed from module/webui/themes/Flat/img/head-menu-collector.png)bin134985 -> 134985 bytes
-rw-r--r--pyload/webui/themes/Flat/img/head-menu-config.png (renamed from module/webui/themes/Flat/img/head-menu-config.png)bin137664 -> 137664 bytes
-rw-r--r--pyload/webui/themes/Flat/img/head-menu-development.png (renamed from module/webui/themes/Flat/img/head-menu-development.png)bin135818 -> 135818 bytes
-rw-r--r--pyload/webui/themes/Flat/img/head-menu-download.png (renamed from module/webui/themes/Flat/img/head-menu-download.png)bin137664 -> 137664 bytes
-rw-r--r--pyload/webui/themes/Flat/img/head-menu-home.png (renamed from module/webui/themes/Flat/img/head-menu-home.png)bin139387 -> 139387 bytes
-rw-r--r--pyload/webui/themes/Flat/img/head-menu-index.png (renamed from module/webui/themes/Flat/img/head-menu-index.png)bin136511 -> 136511 bytes
-rw-r--r--pyload/webui/themes/Flat/img/head-menu-news.png (renamed from module/webui/themes/Flat/img/head-menu-news.png)bin136511 -> 136511 bytes
-rw-r--r--pyload/webui/themes/Flat/img/head-menu-queue.png (renamed from module/webui/themes/Flat/img/head-menu-queue.png)bin136269 -> 136269 bytes
-rw-r--r--pyload/webui/themes/Flat/img/head-menu-wiki.png (renamed from module/webui/themes/Flat/img/head-menu-wiki.png)bin137217 -> 137217 bytes
-rw-r--r--pyload/webui/themes/Flat/img/head-search-noshadow.png (renamed from module/webui/themes/Flat/img/head-search-noshadow.png)bin137217 -> 137217 bytes
-rw-r--r--pyload/webui/themes/Flat/img/notice.png (renamed from module/webui/themes/Flat/img/notice.png)bin3061 -> 3061 bytes
-rw-r--r--pyload/webui/themes/Flat/img/package_go.png (renamed from module/webui/themes/Flat/img/package_go.png)bin136299 -> 136299 bytes
-rw-r--r--pyload/webui/themes/Flat/img/page-tools-backlinks.png (renamed from module/webui/themes/Flat/img/page-tools-backlinks.png)bin138112 -> 138112 bytes
-rw-r--r--pyload/webui/themes/Flat/img/page-tools-edit.png (renamed from module/webui/themes/Flat/img/page-tools-edit.png)bin138112 -> 138112 bytes
-rw-r--r--pyload/webui/themes/Flat/img/page-tools-revisions.png (renamed from module/webui/themes/Flat/img/page-tools-revisions.png)bin138112 -> 138112 bytes
-rw-r--r--pyload/webui/themes/Flat/img/pencil.png (renamed from module/webui/themes/Flat/img/pencil.png)bin138112 -> 138112 bytes
-rw-r--r--pyload/webui/themes/Flat/img/reconnect.png (renamed from module/webui/themes/Flat/img/reconnect.png)bin3063 -> 3063 bytes
-rw-r--r--pyload/webui/themes/Flat/img/status_None.png (renamed from module/webui/themes/Flat/img/status_None.png)bin138112 -> 138112 bytes
-rw-r--r--pyload/webui/themes/Flat/img/status_downloading.png (renamed from module/webui/themes/Flat/img/status_downloading.png)bin3061 -> 3061 bytes
-rw-r--r--pyload/webui/themes/Flat/img/status_failed.png (renamed from module/webui/themes/Flat/img/status_failed.png)bin137673 -> 137673 bytes
-rw-r--r--pyload/webui/themes/Flat/img/status_finished.png (renamed from module/webui/themes/Flat/img/status_finished.png)bin117658 -> 117658 bytes
-rw-r--r--pyload/webui/themes/Flat/img/status_offline.png (renamed from module/webui/themes/Flat/img/status_offline.png)bin137673 -> 137673 bytes
-rw-r--r--pyload/webui/themes/Flat/img/status_proc.png (renamed from module/webui/themes/Flat/img/status_proc.png)bin137406 -> 137406 bytes
-rw-r--r--pyload/webui/themes/Flat/img/status_queue.png (renamed from module/webui/themes/Flat/img/status_queue.png)bin138112 -> 138112 bytes
-rw-r--r--pyload/webui/themes/Flat/img/status_waiting.png (renamed from module/webui/themes/Flat/img/status_waiting.png)bin138112 -> 138112 bytes
-rw-r--r--pyload/webui/themes/Flat/img/success.png (renamed from module/webui/themes/Flat/img/success.png)bin117658 -> 117658 bytes
-rw-r--r--pyload/webui/themes/Flat/img/user-actions-logout.png (renamed from module/webui/themes/Flat/img/user-actions-logout.png)bin138112 -> 138112 bytes
-rw-r--r--pyload/webui/themes/Flat/img/user-actions-profile.png (renamed from module/webui/themes/Flat/img/user-actions-profile.png)bin138112 -> 138112 bytes
-rw-r--r--pyload/webui/themes/Flat/img/user-info.png (renamed from module/webui/themes/Flat/img/user-info.png)bin3080 -> 3080 bytes
-rw-r--r--pyload/webui/themes/Flat/js/render/admin.coffee (renamed from module/webui/themes/Flat/js/render/admin.coffee)0
-rw-r--r--pyload/webui/themes/Flat/js/render/admin.min.js (renamed from module/webui/themes/Flat/js/render/admin.min.js)0
-rw-r--r--pyload/webui/themes/Flat/js/render/base.coffee (renamed from module/webui/themes/Flat/js/render/base.coffee)0
-rw-r--r--pyload/webui/themes/Flat/js/render/base.min.js (renamed from module/webui/themes/Flat/js/render/base.min.js)0
-rw-r--r--pyload/webui/themes/Flat/js/render/filemanager.js (renamed from module/webui/themes/Flat/js/render/filemanager.js)0
-rw-r--r--pyload/webui/themes/Flat/js/render/package.js (renamed from module/webui/themes/Flat/js/render/package.js)0
-rw-r--r--pyload/webui/themes/Flat/js/render/settings.coffee (renamed from module/webui/themes/Flat/js/render/settings.coffee)0
-rw-r--r--pyload/webui/themes/Flat/js/render/settings.min.js (renamed from module/webui/themes/Flat/js/render/settings.min.js)0
-rw-r--r--pyload/webui/themes/Flat/js/static/MooDialog.js (renamed from module/webui/themes/Flat/js/static/MooDialog.js)0
-rw-r--r--pyload/webui/themes/Flat/js/static/MooDialog.min.js (renamed from module/webui/themes/Flat/js/static/MooDialog.min.js)0
-rw-r--r--pyload/webui/themes/Flat/js/static/MooDropMenu.js (renamed from module/webui/themes/Flat/js/static/MooDropMenu.js)0
-rw-r--r--pyload/webui/themes/Flat/js/static/MooDropMenu.min.js (renamed from module/webui/themes/Flat/js/static/MooDropMenu.min.js)0
-rw-r--r--pyload/webui/themes/Flat/js/static/mootools-core.js (renamed from module/webui/themes/Flat/js/static/mootools-core.js)0
-rw-r--r--pyload/webui/themes/Flat/js/static/mootools-core.min.js (renamed from module/webui/themes/Flat/js/static/mootools-core.min.js)0
-rw-r--r--pyload/webui/themes/Flat/js/static/mootools-more.js (renamed from module/webui/themes/Flat/js/static/mootools-more.js)0
-rw-r--r--pyload/webui/themes/Flat/js/static/mootools-more.min.js (renamed from module/webui/themes/Flat/js/static/mootools-more.min.js)0
-rw-r--r--pyload/webui/themes/Flat/js/static/purr.js (renamed from module/webui/themes/Flat/js/static/purr.js)0
-rw-r--r--pyload/webui/themes/Flat/js/static/purr.min.js (renamed from module/webui/themes/Flat/js/static/purr.min.js)0
-rw-r--r--pyload/webui/themes/Flat/js/static/tinytab.js (renamed from module/webui/themes/Flat/js/static/tinytab.js)0
-rw-r--r--pyload/webui/themes/Flat/js/static/tinytab.min.js (renamed from module/webui/themes/Flat/js/static/tinytab.min.js)0
-rw-r--r--pyload/webui/themes/Flat/tml/admin.html (renamed from module/webui/themes/Flat/tml/admin.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/base.html (renamed from module/webui/themes/Flat/tml/base.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/captcha.html (renamed from module/webui/themes/Flat/tml/captcha.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/downloads.html (renamed from module/webui/themes/Flat/tml/downloads.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/filemanager.html (renamed from module/webui/themes/Flat/tml/filemanager.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/folder.html (renamed from module/webui/themes/Flat/tml/folder.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/home.html (renamed from module/webui/themes/Flat/tml/home.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/info.html (renamed from module/webui/themes/Flat/tml/info.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/login.html (renamed from module/webui/themes/Flat/tml/login.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/logout.html (renamed from module/webui/themes/Flat/tml/logout.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/logs.html (renamed from module/webui/themes/Flat/tml/logs.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/pathchooser.html (renamed from module/webui/themes/Flat/tml/pathchooser.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/queue.html (renamed from module/webui/themes/Flat/tml/queue.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/settings.html (renamed from module/webui/themes/Flat/tml/settings.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/settings_item.html (renamed from module/webui/themes/Flat/tml/settings_item.html)0
-rw-r--r--pyload/webui/themes/Flat/tml/window.html (renamed from module/webui/themes/Flat/tml/window.html)0
1190 files changed, 19400 insertions, 20474 deletions
diff --git a/.gitignore b/.gitignore
index 47e309ac3..ebd084ced 100644
--- a/.gitignore
+++ b/.gitignore
@@ -78,5 +78,5 @@ eggs
*.pydevproject
*.rej
_build/
-#module/
+module/
paver-minilib.zip
diff --git a/module/database/File.py b/module/database/File.py
deleted file mode 100644
index 2b7c6cad9..000000000
--- a/module/database/File.py
+++ /dev/null
@@ -1,875 +0,0 @@
-# -*- coding: utf-8 -*-
-# @author: RaNaN, mkaay
-
-from threading import RLock
-from time import time
-
-from pyload.utils import formatSize, lock
-from pyload.manager.Event import InsertEvent, ReloadAllEvent, RemoveEvent, UpdateEvent
-from pyload.datatype.Package import PyPackage
-from pyload.datatype.File import PyFile
-from pyload.database import style, DatabaseBackend
-
-try:
- from pysqlite2 import dbapi2 as sqlite3
-except Exception:
- import sqlite3
-
-
-class FileHandler(object):
- """Handles all request made to obtain information,
- modify status or other request for links or packages"""
-
- def __init__(self, core):
- """Constructor"""
- self.core = core
-
- # translations
- self.statusMsg = [_("finished"), _("offline"), _("online"), _("queued"), _("skipped"), _("waiting"), _("temp. offline"), _("starting"), _("failed"), _("aborted"), _("decrypting"), _("custom"), _("downloading"), _("processing"), _("unknown")]
-
- self.cache = {} #holds instances for files
- self.packageCache = {} # same for packages
- #@TODO: purge the cache
-
- self.jobCache = {}
-
- self.lock = RLock() #@TODO should be a Lock w/o R
- #self.lock._Verbose__verbose = True
-
- self.filecount = -1 # if an invalid value is set get current value from db
- self.queuecount = -1 #number of package to be loaded
- self.unchanged = False #determines if any changes was made since last call
-
- self.db = self.core.db
-
- def change(func):
- def new(*args):
- args[0].unchanged = False
- args[0].filecount = -1
- args[0].queuecount = -1
- args[0].jobCache = {}
- return func(*args)
- return new
-
- #--------------------------------------------------------------------------
- def save(self):
- """saves all data to backend"""
- self.db.commit()
-
- #--------------------------------------------------------------------------
- def syncSave(self):
- """saves all data to backend and waits until all data are written"""
- pyfiles = self.cache.values()
- for pyfile in pyfiles:
- pyfile.sync()
-
- pypacks = self.packageCache.values()
- for pypack in pypacks:
- pypack.sync()
-
- self.db.syncSave()
-
- @lock
- def getCompleteData(self, queue=1):
- """gets a complete data representation"""
-
- data = self.db.getAllLinks(queue)
- packs = self.db.getAllPackages(queue)
-
- data.update([(x.id, x.toDbDict()[x.id]) for x in self.cache.values()])
-
- for x in self.packageCache.itervalues():
- if x.queue != queue or x.id not in packs: continue
- packs[x.id].update(x.toDict()[x.id])
-
- for key, value in data.iteritems():
- if value["package"] in packs:
- packs[value["package"]]["links"][key] = value
-
- return packs
-
- @lock
- def getInfoData(self, queue=1):
- """gets a data representation without links"""
-
- packs = self.db.getAllPackages(queue)
- for x in self.packageCache.itervalues():
- if x.queue != queue or x.id not in packs: continue
- packs[x.id].update(x.toDict()[x.id])
-
- return packs
-
- @lock
- @change
- def addLinks(self, urls, package):
- """adds links"""
-
- self.core.addonManager.dispatchEvent("links-added", urls, package)
-
- data = self.core.pluginManager.parseUrls(urls)
-
- self.db.addLinks(data, package)
- self.core.threadManager.createInfoThread(data, package)
-
- #@TODO change from reloadAll event to package update event
- self.core.pullManager.addEvent(ReloadAllEvent("collector"))
-
- #--------------------------------------------------------------------------
- @lock
- @change
- def addPackage(self, name, folder, queue=0):
- """adds a package, default to link collector"""
- lastID = self.db.addPackage(name, folder, queue)
- p = self.db.getPackage(lastID)
- e = InsertEvent("pack", lastID, p.order, "collector" if not queue else "queue")
- self.core.pullManager.addEvent(e)
- return lastID
-
- #--------------------------------------------------------------------------
- @lock
- @change
- def deletePackage(self, id):
- """delete package and all contained links"""
-
- p = self.getPackage(id)
- if not p:
- if id in self.packageCache: del self.packageCache[id]
- return
-
- oldorder = p.order
- queue = p.queue
-
- e = RemoveEvent("pack", id, "collector" if not p.queue else "queue")
-
- pyfiles = self.cache.values()
-
- for pyfile in pyfiles:
- if pyfile.packageid == id:
- pyfile.abortDownload()
- pyfile.release()
-
- self.db.deletePackage(p)
- self.core.pullManager.addEvent(e)
- self.core.addonManager.dispatchEvent("package-deleted", id)
-
- if id in self.packageCache:
- del self.packageCache[id]
-
- packs = self.packageCache.values()
- for pack in packs:
- if pack.queue == queue and pack.order > oldorder:
- pack.order -= 1
- pack.notifyChange()
-
- #--------------------------------------------------------------------------
- @lock
- @change
- def deleteLink(self, id):
- """deletes links"""
-
- f = self.getFile(id)
- if not f:
- return None
-
- pid = f.packageid
- e = RemoveEvent("file", id, "collector" if not f.package().queue else "queue")
-
- oldorder = f.order
-
- if id in self.core.threadManager.processingIds():
- self.cache[id].abortDownload()
-
- if id in self.cache:
- del self.cache[id]
-
- self.db.deleteLink(f)
-
- self.core.pullManager.addEvent(e)
-
- p = self.getPackage(pid)
- if not len(p.getChildren()):
- p.delete()
-
- pyfiles = self.cache.values()
- for pyfile in pyfiles:
- if pyfile.packageid == pid and pyfile.order > oldorder:
- pyfile.order -= 1
- pyfile.notifyChange()
-
- #--------------------------------------------------------------------------
- def releaseLink(self, id):
- """removes pyfile from cache"""
- if id in self.cache:
- del self.cache[id]
-
- #--------------------------------------------------------------------------
- def releasePackage(self, id):
- """removes package from cache"""
- if id in self.packageCache:
- del self.packageCache[id]
-
- #--------------------------------------------------------------------------
- def updateLink(self, pyfile):
- """updates link"""
- self.db.updateLink(pyfile)
-
- e = UpdateEvent("file", pyfile.id, "collector" if not pyfile.package().queue else "queue")
- self.core.pullManager.addEvent(e)
-
- #--------------------------------------------------------------------------
- def updatePackage(self, pypack):
- """updates a package"""
- self.db.updatePackage(pypack)
-
- e = UpdateEvent("pack", pypack.id, "collector" if not pypack.queue else "queue")
- self.core.pullManager.addEvent(e)
-
- #--------------------------------------------------------------------------
- def getPackage(self, id):
- """return package instance"""
-
- if id in self.packageCache:
- return self.packageCache[id]
- else:
- return self.db.getPackage(id)
-
- #--------------------------------------------------------------------------
- def getPackageData(self, id):
- """returns dict with package information"""
- pack = self.getPackage(id)
-
- if not pack:
- return None
-
- pack = pack.toDict()[id]
-
- data = self.db.getPackageData(id)
-
- tmplist = []
-
- cache = self.cache.values()
- for x in cache:
- if int(x.toDbDict()[x.id]["package"]) == int(id):
- tmplist.append((x.id, x.toDbDict()[x.id]))
- data.update(tmplist)
-
- pack["links"] = data
-
- return pack
-
- #--------------------------------------------------------------------------
- def getFileData(self, id):
- """returns dict with file information"""
- if id in self.cache:
- return self.cache[id].toDbDict()
-
- return self.db.getLinkData(id)
-
- #--------------------------------------------------------------------------
- def getFile(self, id):
- """returns pyfile instance"""
- if id in self.cache:
- return self.cache[id]
- else:
- return self.db.getFile(id)
-
- #--------------------------------------------------------------------------
- @lock
- def getJob(self, occ):
- """get suitable job"""
-
- #@TODO clean mess
- #@TODO improve selection of valid jobs
-
- if occ in self.jobCache:
- if self.jobCache[occ]:
- id = self.jobCache[occ].pop()
- if id == "empty":
- pyfile = None
- self.jobCache[occ].append("empty")
- else:
- pyfile = self.getFile(id)
- else:
- jobs = self.db.getJob(occ)
- jobs.reverse()
- if not jobs:
- self.jobCache[occ].append("empty")
- pyfile = None
- else:
- self.jobCache[occ].extend(jobs)
- pyfile = self.getFile(self.jobCache[occ].pop())
-
- else:
- self.jobCache = {} #better not caching to much
- jobs = self.db.getJob(occ)
- jobs.reverse()
- self.jobCache[occ] = jobs
-
- if not jobs:
- self.jobCache[occ].append("empty")
- pyfile = None
- else:
- pyfile = self.getFile(self.jobCache[occ].pop())
-
- #@TODO: maybe the new job has to be approved...
-
-
- #pyfile = self.getFile(self.jobCache[occ].pop())
- return pyfile
-
- @lock
- def getDecryptJob(self):
- """return job for decrypting"""
- if "decrypt" in self.jobCache:
- return None
-
- plugins = self.core.pluginManager.crypterPlugins.keys() + self.core.pluginManager.containerPlugins.keys()
- plugins = str(tuple(plugins))
-
- jobs = self.db.getPluginJob(plugins)
- if jobs:
- return self.getFile(jobs[0])
- else:
- self.jobCache["decrypt"] = "empty"
- return None
-
- def getFileCount(self):
- """returns number of files"""
-
- if self.filecount == -1:
- self.filecount = self.db.filecount(1)
-
- return self.filecount
-
- def getQueueCount(self, force=False):
- """number of files that have to be processed"""
- if self.queuecount == -1 or force:
- self.queuecount = self.db.queuecount(1)
-
- return self.queuecount
-
- def checkAllLinksFinished(self):
- """checks if all files are finished and dispatch event"""
-
- if not self.getQueueCount(True):
- self.core.addonManager.dispatchEvent("all_downloads-finished")
- self.core.log.debug("All downloads finished")
- return True
-
- return False
-
- def checkAllLinksProcessed(self, fid):
- """checks if all files was processed and pyload would idle now, needs fid which will be ignored when counting"""
-
- # reset count so statistic will update (this is called when dl was processed)
- self.resetCount()
-
- if not self.db.processcount(1, fid):
- self.core.addonManager.dispatchEvent("all_downloads-processed")
- self.core.log.debug("All downloads processed")
- return True
-
- return False
-
- def resetCount(self):
- self.queuecount = -1
-
- @lock
- @change
- def restartPackage(self, id):
- """restart package"""
- pyfiles = self.cache.values()
- for pyfile in pyfiles:
- if pyfile.packageid == id:
- self.restartFile(pyfile.id)
-
- self.db.restartPackage(id)
-
- if id in self.packageCache:
- self.packageCache[id].setFinished = False
-
- e = UpdateEvent("pack", id, "collector" if not self.getPackage(id).queue else "queue")
- self.core.pullManager.addEvent(e)
-
- @lock
- @change
- def restartFile(self, id):
- """ restart file"""
- if id in self.cache:
- self.cache[id].status = 3
- self.cache[id].name = self.cache[id].url
- self.cache[id].error = ""
- self.cache[id].abortDownload()
-
-
- self.db.restartFile(id)
-
- e = UpdateEvent("file", id, "collector" if not self.getFile(id).package().queue else "queue")
- self.core.pullManager.addEvent(e)
-
- @lock
- @change
- def setPackageLocation(self, id, queue):
- """push package to queue"""
-
- p = self.db.getPackage(id)
- oldorder = p.order
-
- e = RemoveEvent("pack", id, "collector" if not p.queue else "queue")
- self.core.pullManager.addEvent(e)
-
- self.db.clearPackageOrder(p)
-
- p = self.db.getPackage(id)
-
- p.queue = queue
- self.db.updatePackage(p)
-
- self.db.reorderPackage(p, -1, True)
-
- packs = self.packageCache.values()
- for pack in packs:
- if pack.queue != queue and pack.order > oldorder:
- pack.order -= 1
- pack.notifyChange()
-
- self.db.commit()
- self.releasePackage(id)
- p = self.getPackage(id)
-
- e = InsertEvent("pack", id, p.order, "collector" if not p.queue else "queue")
- self.core.pullManager.addEvent(e)
-
- @lock
- @change
- def reorderPackage(self, id, position):
- p = self.getPackage(id)
-
- e = RemoveEvent("pack", id, "collector" if not p.queue else "queue")
- self.core.pullManager.addEvent(e)
- self.db.reorderPackage(p, position)
-
- packs = self.packageCache.values()
- for pack in packs:
- if pack.queue != p.queue or pack.order < 0 or pack == p: continue
- if p.order > position:
- if pack.order >= position and pack.order < p.order:
- pack.order += 1
- pack.notifyChange()
- elif p.order < position:
- if pack.order <= position and pack.order > p.order:
- pack.order -= 1
- pack.notifyChange()
-
- p.order = position
- self.db.commit()
-
- e = InsertEvent("pack", id, position, "collector" if not p.queue else "queue")
- self.core.pullManager.addEvent(e)
-
- @lock
- @change
- def reorderFile(self, id, position):
- f = self.getFileData(id)
- f = f[id]
-
- e = RemoveEvent("file", id, "collector" if not self.getPackage(f["package"]).queue else "queue")
- self.core.pullManager.addEvent(e)
-
- self.db.reorderLink(f, position)
-
- pyfiles = self.cache.values()
- for pyfile in pyfiles:
- if pyfile.packageid != f["package"] or pyfile.order < 0: continue
- if f["order"] > position:
- if pyfile.order >= position and pyfile.order < f["order"]:
- pyfile.order += 1
- pyfile.notifyChange()
- elif f["order"] < position:
- if pyfile.order <= position and pyfile.order > f["order"]:
- pyfile.order -= 1
- pyfile.notifyChange()
-
- if id in self.cache:
- self.cache[id].order = position
-
- self.db.commit()
-
- e = InsertEvent("file", id, position, "collector" if not self.getPackage(f["package"]).queue else "queue")
- self.core.pullManager.addEvent(e)
-
- @change
- def updateFileInfo(self, data, pid):
- """ updates file info (name, size, status, url)"""
- ids = self.db.updateLinkInfo(data)
- e = UpdateEvent("pack", pid, "collector" if not self.getPackage(pid).queue else "queue")
- self.core.pullManager.addEvent(e)
-
- def checkPackageFinished(self, pyfile):
- """ checks if package is finished and calls AddonManager """
-
- ids = self.db.getUnfinished(pyfile.packageid)
- if not ids or (pyfile.id in ids and len(ids) == 1):
- if not pyfile.package().setFinished:
- self.core.log.info(_("Package finished: %s") % pyfile.package().name)
- self.core.addonManager.packageFinished(pyfile.package())
- pyfile.package().setFinished = True
-
-
- def reCheckPackage(self, pid):
- """ recheck links in package """
- data = self.db.getPackageData(pid)
-
- urls = []
-
- for pyfile in data.itervalues():
- if pyfile["status"] not in (0, 12, 13):
- urls.append((pyfile["url"], pyfile["plugin"]))
-
- self.core.threadManager.createInfoThread(urls, pid)
-
- @lock
- @change
- def deleteFinishedLinks(self):
- """ deletes finished links and packages, return deleted packages """
-
- old_packs = self.getInfoData(0)
- old_packs.update(self.getInfoData(1))
-
- self.db.deleteFinished()
-
- new_packs = self.db.getAllPackages(0)
- new_packs.update(self.db.getAllPackages(1))
- #get new packages only from db
-
- deleted = []
- for id in old_packs.iterkeys():
- if id not in new_packs:
- deleted.append(id)
- self.deletePackage(int(id))
-
- return deleted
-
- @lock
- @change
- def restartFailed(self):
- """ restart all failed links """
- self.db.restartFailed()
-
-class FileMethods(object):
- @style.queue
- def filecount(self, queue):
- """returns number of files in queue"""
- self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=?", (queue,))
- return self.c.fetchone()[0]
-
- @style.queue
- def queuecount(self, queue):
- """ number of files in queue not finished yet"""
- self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? AND l.status NOT IN (0, 4)", (queue,))
- return self.c.fetchone()[0]
-
- @style.queue
- def processcount(self, queue, fid):
- """ number of files which have to be proccessed """
- self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? AND l.status IN (2, 3, 5, 7, 12) AND l.id != ?", (queue, str(fid)))
- return self.c.fetchone()[0]
-
- @style.inner
- def _nextPackageOrder(self, queue=0):
- self.c.execute('SELECT MAX(packageorder) FROM packages WHERE queue=?', (queue,))
- max = self.c.fetchone()[0]
- if max is not None:
- return max + 1
- else:
- return 0
-
- @style.inner
- def _nextFileOrder(self, package):
- self.c.execute('SELECT MAX(linkorder) FROM links WHERE package=?', (package,))
- max = self.c.fetchone()[0]
- if max is not None:
- return max + 1
- else:
- return 0
-
- @style.queue
- def addLink(self, url, name, plugin, package):
- order = self._nextFileOrder(package)
- self.c.execute('INSERT INTO links(url, name, plugin, package, linkorder) VALUES(?,?,?,?,?)', (url, name, (plugintype, pluginname), package, order))
- return self.c.lastrowid
-
- @style.queue
- def addLinks(self, links, package):
- """ links is a list of tupels (url, plugin)"""
- order = self._nextFileOrder(package)
- orders = [order + x for x in range(len(links))]
- links = [(x[0], x[0], (x[1], x[2]), package, o) for x, o in zip(links, orders)]
- self.c.executemany('INSERT INTO links(url, name, plugin, package, linkorder) VALUES(?,?,?,?,?)', links)
-
- @style.queue
- def addPackage(self, name, folder, queue):
- order = self._nextPackageOrder(queue)
- self.c.execute('INSERT INTO packages(name, folder, queue, packageorder) VALUES(?,?,?,?)', (name, folder, queue, order))
- return self.c.lastrowid
-
- @style.queue
- def deletePackage(self, p):
-
- self.c.execute('DELETE FROM links WHERE package=?', (str(p.id),))
- self.c.execute('DELETE FROM packages WHERE id=?', (str(p.id),))
- self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder > ? AND queue=?', (p.order, p.queue))
-
- @style.queue
- def deleteLink(self, f):
-
- self.c.execute('DELETE FROM links WHERE id=?', (str(f.id),))
- self.c.execute('UPDATE links SET linkorder=linkorder-1 WHERE linkorder > ? AND package=?', (f.order, str(f.packageid)))
-
-
- @style.queue
- def getAllLinks(self, q):
- """return information about all links in queue q
-
- q0 queue
- q1 collector
-
- format:
-
- {
- id: {'name': name, ... 'package': id }, ...
- }
-
- """
- self.c.execute('SELECT l.id, l.url, l.name, l.size, l.status, l.error, l.plugin, l.package, l.linkorder FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? ORDER BY l.linkorder', (q,))
- data = {}
- for r in self.c:
- data[r[0]] = {
- 'id': r[0],
- 'url': r[1],
- 'name': r[2],
- 'size': r[3],
- 'format_size': formatSize(r[3]),
- 'status': r[4],
- 'statusmsg': self.manager.statusMsg[r[4]],
- 'error': r[5],
- 'plugin': r[6],
- 'package': r[7],
- 'order': r[8],
- }
-
- return data
-
- @style.queue
- def getAllPackages(self, q):
- """return information about packages in queue q
- (only useful in get all data)
-
- q0 queue
- q1 collector
-
- format:
-
- {
- id: {'name': name ... 'links': {}}, ...
- }
- """
- self.c.execute('SELECT p.id, p.name, p.folder, p.site, p.password, p.queue, p.packageorder, s.sizetotal, s.sizedone, s.linksdone, s.linkstotal \
- FROM packages p JOIN pstats s ON p.id = s.id \
- WHERE p.queue=? ORDER BY p.packageorder', str(q))
-
- data = {}
- for r in self.c:
- data[r[0]] = {
- 'id': r[0],
- 'name': r[1],
- 'folder': r[2],
- 'site': r[3],
- 'password': r[4],
- 'queue': r[5],
- 'order': r[6],
- 'sizetotal': int(r[7]),
- 'sizedone': r[8] if r[8] else 0, #these can be None
- 'linksdone': r[9] if r[9] else 0,
- 'linkstotal': r[10],
- 'links': {}
- }
-
- return data
-
- @style.queue
- def getLinkData(self, id):
- """get link information as dict"""
- self.c.execute('SELECT id, url, name, size, status, error, plugin, package, linkorder FROM links WHERE id=?', (str(id),))
- data = {}
- r = self.c.fetchone()
- if not r:
- return None
- data[r[0]] = {
- 'id': r[0],
- 'url': r[1],
- 'name': r[2],
- 'size': r[3],
- 'format_size': formatSize(r[3]),
- 'status': r[4],
- 'statusmsg': self.manager.statusMsg[r[4]],
- 'error': r[5],
- 'plugin': r[6],
- 'package': r[7],
- 'order': r[8],
- }
-
- return data
-
- @style.queue
- def getPackageData(self, id):
- """get data about links for a package"""
- self.c.execute('SELECT id, url, name, size, status, error, plugin, package, linkorder FROM links WHERE package=? ORDER BY linkorder', (str(id),))
-
- data = {}
- for r in self.c:
- data[r[0]] = {
- 'id': r[0],
- 'url': r[1],
- 'name': r[2],
- 'size': r[3],
- 'format_size': formatSize(r[3]),
- 'status': r[4],
- 'statusmsg': self.manager.statusMsg[r[4]],
- 'error': r[5],
- 'plugin': r[6],
- 'package': r[7],
- 'order': r[8],
- }
-
- return data
-
-
- @style.async
- def updateLink(self, f):
- self.c.execute('UPDATE links SET url=?, name=?, size=?, status=?, error=?, package=? WHERE id=?', (f.url, f.name, f.size, f.status, f.error, str(f.packageid), str(f.id)))
-
- @style.queue
- def updatePackage(self, p):
- self.c.execute('UPDATE packages SET name=?, folder=?, site=?, password=?, queue=? WHERE id=?', (p.name, p.folder, p.site, p.password, p.queue, str(p.id)))
-
- @style.queue
- def updateLinkInfo(self, data):
- """ data is list of tupels (name, size, status, url) """
- self.c.executemany('UPDATE links SET name=?, size=?, status=? WHERE url=? AND status IN (1, 2, 3, 14)', data)
- ids = []
- self.c.execute('SELECT id FROM links WHERE url IN (\'%s\')' % "','".join([x[3] for x in data]))
- for r in self.c:
- ids.append(int(r[0]))
- return ids
-
- @style.queue
- def reorderPackage(self, p, position, noMove=False):
- if position == -1:
- position = self._nextPackageOrder(p.queue)
- if not noMove:
- if p.order > position:
- self.c.execute('UPDATE packages SET packageorder=packageorder+1 WHERE packageorder >= ? AND packageorder < ? AND queue=? AND packageorder >= 0', (position, p.order, p.queue))
- elif p.order < position:
- self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder <= ? AND packageorder > ? AND queue=? AND packageorder >= 0', (position, p.order, p.queue))
-
- self.c.execute('UPDATE packages SET packageorder=? WHERE id=?', (position, str(p.id)))
-
- @style.queue
- def reorderLink(self, f, position):
- """ reorder link with f as dict for pyfile """
- if f["order"] > position:
- self.c.execute('UPDATE links SET linkorder=linkorder+1 WHERE linkorder >= ? AND linkorder < ? AND package=?', (position, f["order"], f["package"]))
- elif f["order"] < position:
- self.c.execute('UPDATE links SET linkorder=linkorder-1 WHERE linkorder <= ? AND linkorder > ? AND package=?', (position, f["order"], f["package"]))
-
- self.c.execute('UPDATE links SET linkorder=? WHERE id=?', (position, f["id"]))
-
- @style.queue
- def clearPackageOrder(self, p):
- self.c.execute('UPDATE packages SET packageorder=? WHERE id=?', (-1, str(p.id)))
- self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder > ? AND queue=? AND id != ?', (p.order, p.queue, str(p.id)))
-
- @style.async
- def restartFile(self, id):
- self.c.execute('UPDATE links SET status=3, error="" WHERE id=?', (str(id),))
-
- @style.async
- def restartPackage(self, id):
- self.c.execute('UPDATE links SET status=3 WHERE package=?', (str(id),))
-
- @style.queue
- def getPackage(self, id):
- """return package instance from id"""
- self.c.execute("SELECT name, folder, site, password, queue, packageorder FROM packages WHERE id=?", (str(id),))
- r = self.c.fetchone()
- if not r: return None
- return PyPackage(self.manager, id, * r)
-
- #--------------------------------------------------------------------------
- @style.queue
- def getFile(self, id):
- """return link instance from id"""
- self.c.execute("SELECT url, name, size, status, error, plugin, package, linkorder FROM links WHERE id=?", (str(id),))
- r = self.c.fetchone()
- if not r: return None
- return PyFile(self.manager, id, * r)
-
-
- @style.queue
- def getJob(self, occ):
- """return pyfile ids, which are suitable for download and dont use a occupied plugin"""
-
- #@TODO improve this hardcoded method
- pre = "('DLC', 'LinkList', 'SerienjunkiesOrg', 'CCF', 'RSDF')" #plugins which are processed in collector
-
- cmd = "("
- for i, item in enumerate(occ):
- if i: cmd += ", "
- cmd += "'%s'" % item
-
- cmd += ")"
-
- cmd = "SELECT l.id FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE ((p.queue=1 AND l.plugin NOT IN %s) OR l.plugin IN %s) AND l.status IN (2, 3, 14) ORDER BY p.packageorder ASC, l.linkorder ASC LIMIT 5" % (cmd, pre)
-
- self.c.execute(cmd) # very bad!
-
- return [x[0] for x in self.c]
-
- @style.queue
- def getPluginJob(self, plugins):
- """returns pyfile ids with suited plugins"""
- cmd = "SELECT l.id FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE l.plugin IN %s AND l.status IN (2, 3, 14) ORDER BY p.packageorder ASC, l.linkorder ASC LIMIT 5" % plugins
-
- self.c.execute(cmd) # very bad!
-
- return [x[0] for x in self.c]
-
- @style.queue
- def getUnfinished(self, pid):
- """return list of max length 3 ids with pyfiles in package not finished or processed"""
-
- self.c.execute("SELECT id FROM links WHERE package=? AND status NOT IN (0, 4, 13) LIMIT 3", (str(pid),))
- return [r[0] for r in self.c]
-
- @style.queue
- def deleteFinished(self):
- self.c.execute("DELETE FROM links WHERE status IN (0, 4)")
- self.c.execute("DELETE FROM packages WHERE NOT EXISTS(SELECT 1 FROM links WHERE packages.id=links.package)")
-
- @style.queue
- def restartFailed(self):
- self.c.execute("UPDATE links SET status=3, error='' WHERE status IN (6, 8, 9)")
-
- @style.queue
- def findDuplicates(self, id, folder, filename):
- """ checks if filename exists with different id and same package """
- self.c.execute("SELECT l.plugin FROM links as l INNER JOIN packages as p ON l.package=p.id AND p.folder=? WHERE l.id!=? AND l.status=0 AND l.name=?", (folder, id, filename))
- return self.c.fetchone()
-
- @style.queue
- def purgeLinks(self):
- self.c.execute("DELETE FROM links;")
- self.c.execute("DELETE FROM packages;")
-
-DatabaseBackend.registerSub(FileMethods)
diff --git a/module/plugins/Addon.py b/module/plugins/Addon.py
deleted file mode 100644
index ca36fe4ae..000000000
--- a/module/plugins/Addon.py
+++ /dev/null
@@ -1,185 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from traceback import print_exc
-
-from pyload.plugin.Plugin import Base
-from pyload.utils import has_method
-
-
-class Expose(object):
- """ used for decoration to declare rpc services """
-
- def __new__(cls, f, *args, **kwargs):
- addonManager.addRPC(f.__module__, f.func_name, f.func_doc)
- return f
-
-
-def threaded(fn):
-
- def run(*args,**kwargs):
- addonManager.startThread(fn, *args, **kwargs)
-
- return run
-
-
-class Addon(Base):
- """
- Base class for addon plugins.
- """
- __name__ = "Addon"
- __type__ = "addon"
- __version__ = "0.03"
-
- __config__ = [] #: [("name", "type", "desc", "default")]
-
- __description__ = """Base addon/hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("mkaay", "mkaay@mkaay.de"),
- ("RaNaN", "RaNaN@pyload.org")]
-
-
- #: automatically register event listeners for functions, attribute will be deleted dont use it yourself
- event_map = {}
-
- # Deprecated alternative to event_map
- #: List of events the plugin can handle, name the functions exactly like eventname.
- event_list = [] #@NOTE: dont make duplicate entries in event_map
-
-
- def __init__(self, core, manager):
- Base.__init__(self, core)
-
- #: Provide information in dict here, usable by API `getInfo`
- self.info = {}
-
- #: Callback of periodical job task, used by AddonManager
- self.cb = None
- self.interval = 60
-
- #: `AddonManager`
- self.manager = manager
-
- #register events
- if self.event_map:
- for event, funcs in self.event_map.iteritems():
- if type(funcs) in (list, tuple):
- for f in funcs:
- self.manager.addEvent(event, getattr(self,f))
- else:
- self.manager.addEvent(event, getattr(self,funcs))
-
- #delete for various reasons
- self.event_map = None
-
- if self.event_list:
- for f in self.event_list:
- self.manager.addEvent(f, getattr(self,f))
-
- self.event_list = None
-
- self.setup()
-
- # self.initPeriodical()
-
-
- def initPeriodical(self, delay=0, threaded=False):
- self.cb = self.core.scheduler.addJob(delay, self._periodical, args=[threaded], threaded=threaded)
-
-
- def _periodical(self, threaded):
- if self.interval < 0:
- self.cb = None
- return
-
- try:
- self.periodical()
-
- except Exception, e:
- self.logError(_("Error executing addon: %s") % e)
- if self.core.debug:
- print_exc()
-
- self.cb = self.core.scheduler.addJob(self.interval, self._periodical, threaded=threaded)
-
-
- def __repr__(self):
- return "<Addon %s>" % self.__name__
-
-
- def setup(self):
- """ more init stuff if needed """
- pass
-
-
- def deactivate(self):
- """ called when addon was deactivated """
- if has_method(self.__class__, "unload"):
- self.unload()
-
- def unload(self): # Deprecated, use method deactivate() instead
- pass
-
-
- def isActivated(self):
- """ checks if addon is activated"""
- return self.core.config.getPlugin(self.__name__, "activated")
-
-
- # Event methods - overwrite these if needed
- def activate(self):
- """ called when addon was activated """
- if has_method(self.__class__, "coreReady"):
- self.coreReady()
-
- def coreReady(self): # Deprecated, use method activate() instead
- pass
-
-
- def exit(self):
- """ called by core.shutdown just before pyLoad exit """
- if has_method(self.__class__, "coreExiting"):
- self.coreExiting()
-
- def coreExiting(self): # Deprecated, use method exit() instead
- pass
-
-
- def downloadPreparing(self, pyfile):
- pass
-
-
- def downloadFinished(self, pyfile):
- pass
-
-
- def downloadFailed(self, pyfile):
- pass
-
-
- def packageFinished(self, pypack):
- pass
-
-
- def beforeReconnecting(self, ip):
- pass
-
-
- def afterReconnecting(self, ip):
- pass
-
-
- def periodical(self):
- pass
-
-
- def captchaTask(self, task):
- """ new captcha task for the plugin, it MUST set the handler and timeout or will be ignored """
- pass
-
-
- def captchaCorrect(self, task):
- pass
-
-
- def captchaInvalid(self, task):
- pass
diff --git a/module/plugins/Captcha.py b/module/plugins/Captcha.py
deleted file mode 100644
index ace488994..000000000
--- a/module/plugins/Captcha.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.Plugin import Plugin
-
-
-class Captcha(Plugin):
- __name__ = "Captcha"
- __type__ = "captcha"
- __version__ = "0.14"
-
- __description__ = """Base captcha service plugin"""
- __license__ = "GPLv3"
- __authors__ = [("pyLoad Team", "admin@pyload.org")]
-
-
- KEY_PATTERN = None
-
- key = None #: last key detected
-
-
- def __init__(self, plugin):
- self.plugin = plugin
-
-
- def detect_key(self, html=None):
- if not html:
- if hasattr(self.plugin, "html") and self.plugin.html:
- html = self.plugin.html
- else:
- errmsg = _("%s html not found") % self.__name__
- self.plugin.error(errmsg)
- raise TypeError(errmsg)
-
- m = re.search(self.KEY_PATTERN, html)
- if m:
- self.key = m.group("KEY")
- self.plugin.logDebug("%s key: %s" % (self.__name__, self.key))
- return self.key
- else:
- self.plugin.logDebug("%s key not found" % self.__name__)
- return None
-
-
- def challenge(self, key=None):
- raise NotImplementedError
-
-
- def result(self, server, challenge):
- raise NotImplementedError
diff --git a/module/plugins/OCR.py b/module/plugins/OCR.py
deleted file mode 100644
index f309394f5..000000000
--- a/module/plugins/OCR.py
+++ /dev/null
@@ -1,318 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-try:
- from PIL import Image, GifImagePlugin, JpegImagePlugin, PngImagePlugin, TiffImagePlugin
-
-except ImportError:
- import Image, GifImagePlugin, JpegImagePlugin, PngImagePlugin, TiffImagePlugin
-
-import logging
-import os
-import subprocess
-#import tempfile
-
-from module.utils import save_join
-
-
-class OCR(object):
- __name__ = "OCR"
- __type__ = "ocr"
- __version__ = "0.11"
-
- __description__ = """OCR base plugin"""
- __license__ = "GPLv3"
- __authors__ = [("pyLoad Team", "admin@pyload.org")]
-
-
- def __init__(self):
- self.logger = logging.getLogger("log")
-
-
- def load_image(self, image):
- self.image = Image.open(image)
- self.pixels = self.image.load()
- self.result_captcha = ''
-
-
- def unload(self):
- """delete all tmp images"""
- pass
-
-
- def threshold(self, value):
- self.image = self.image.point(lambda a: a * value + 10)
-
-
- def run(self, command):
- """Run a command"""
-
- popen = subprocess.Popen(command, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- popen.wait()
- output = popen.stdout.read() + " | " + popen.stderr.read()
- popen.stdout.close()
- popen.stderr.close()
- self.logger.debug("Tesseract ReturnCode %s Output: %s" % (popen.returncode, output))
-
-
- def run_tesser(self, subset=False, digits=True, lowercase=True, uppercase=True):
- #tmpTif = tempfile.NamedTemporaryFile(suffix=".tif")
- try:
- tmpTif = open(save_join("tmp", "tmpTif_%s.tif" % self.__name__), "wb")
- tmpTif.close()
-
- #tmpTxt = tempfile.NamedTemporaryFile(suffix=".txt")
- tmpTxt = open(save_join("tmp", "tmpTxt_%s.txt" % self.__name__), "wb")
- tmpTxt.close()
-
- except IOError, e:
- self.logError(e)
- return
-
- self.logger.debug("save tiff")
- self.image.save(tmpTif.name, 'TIFF')
-
- if os.name == "nt":
- tessparams = [os.path.join(pypath, "tesseract", "tesseract.exe")]
- else:
- tessparams = ["tesseract"]
-
- tessparams.extend([os.path.abspath(tmpTif.name), os.path.abspath(tmpTxt.name).replace(".txt", "")] )
-
- if subset and (digits or lowercase or uppercase):
- #tmpSub = tempfile.NamedTemporaryFile(suffix=".subset")
- with open(save_join("tmp", "tmpSub_%s.subset" % self.__name__), "wb") as tmpSub:
- tmpSub.write("tessedit_char_whitelist ")
-
- if digits:
- tmpSub.write("0123456789")
- if lowercase:
- tmpSub.write("abcdefghijklmnopqrstuvwxyz")
- if uppercase:
- tmpSub.write("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
-
- tmpSub.write("\n")
- tessparams.append("nobatch")
- tessparams.append(os.path.abspath(tmpSub.name))
-
- self.logger.debug("run tesseract")
- self.run(tessparams)
- self.logger.debug("read txt")
-
- try:
- with open(tmpTxt.name, 'r') as f:
- self.result_captcha = f.read().replace("\n", "")
- except Exception:
- self.result_captcha = ""
-
- self.logger.debug(self.result_captcha)
- try:
- os.remove(tmpTif.name)
- os.remove(tmpTxt.name)
- if subset and (digits or lowercase or uppercase):
- os.remove(tmpSub.name)
- except Exception:
- pass
-
-
- def get_captcha(self, name):
- raise NotImplementedError
-
-
- def to_greyscale(self):
- if self.image.mode != 'L':
- self.image = self.image.convert('L')
-
- self.pixels = self.image.load()
-
-
- def eval_black_white(self, limit):
- self.pixels = self.image.load()
- w, h = self.image.size
- for x in xrange(w):
- for y in xrange(h):
- if self.pixels[x, y] > limit:
- self.pixels[x, y] = 255
- else:
- self.pixels[x, y] = 0
-
-
- def clean(self, allowed):
- pixels = self.pixels
-
- w, h = self.image.size
-
- for x in xrange(w):
- for y in xrange(h):
- if pixels[x, y] == 255:
- continue
- # No point in processing white pixels since we only want to remove black pixel
- count = 0
-
- try:
- if pixels[x - 1, y - 1] != 255:
- count += 1
- if pixels[x - 1, y] != 255:
- count += 1
- if pixels[x - 1, y + 1] != 255:
- count += 1
- if pixels[x, y + 1] != 255:
- count += 1
- if pixels[x + 1, y + 1] != 255:
- count += 1
- if pixels[x + 1, y] != 255:
- count += 1
- if pixels[x + 1, y - 1] != 255:
- count += 1
- if pixels[x, y - 1] != 255:
- count += 1
- except Exception:
- pass
-
- # not enough neighbors are dark pixels so mark this pixel
- # to be changed to white
- if count < allowed:
- pixels[x, y] = 1
-
- # second pass: this time set all 1's to 255 (white)
- for x in xrange(w):
- for y in xrange(h):
- if pixels[x, y] == 1:
- pixels[x, y] = 255
-
- self.pixels = pixels
-
-
- def derotate_by_average(self):
- """rotate by checking each angle and guess most suitable"""
-
- w, h = self.image.size
- pixels = self.pixels
-
- for x in xrange(w):
- for y in xrange(h):
- if pixels[x, y] == 0:
- pixels[x, y] = 155
-
- highest = {}
- counts = {}
-
- for angle in xrange(-45, 45):
-
- tmpimage = self.image.rotate(angle)
-
- pixels = tmpimage.load()
-
- w, h = self.image.size
-
- for x in xrange(w):
- for y in xrange(h):
- if pixels[x, y] == 0:
- pixels[x, y] = 255
-
- count = {}
-
- for x in xrange(w):
- count[x] = 0
- for y in xrange(h):
- if pixels[x, y] == 155:
- count[x] += 1
-
- sum = 0
- cnt = 0
-
- for x in count.values():
- if x != 0:
- sum += x
- cnt += 1
-
- avg = sum / cnt
- counts[angle] = cnt
- highest[angle] = 0
- for x in count.values():
- if x > highest[angle]:
- highest[angle] = x
-
- highest[angle] = highest[angle] - avg
-
- hkey = 0
- hvalue = 0
-
- for key, value in highest.iteritems():
- if value > hvalue:
- hkey = key
- hvalue = value
-
- self.image = self.image.rotate(hkey)
- pixels = self.image.load()
-
- for x in xrange(w):
- for y in xrange(h):
- if pixels[x, y] == 0:
- pixels[x, y] = 255
-
- if pixels[x, y] == 155:
- pixels[x, y] = 0
-
- self.pixels = pixels
-
-
- def split_captcha_letters(self):
- captcha = self.image
- started = False
- letters = []
- width, height = captcha.size
- bottomY, topY = 0, height
- pixels = captcha.load()
-
- for x in xrange(width):
- black_pixel_in_col = False
- for y in xrange(height):
- if pixels[x, y] != 255:
- if not started:
- started = True
- firstX = x
- lastX = x
-
- if y > bottomY:
- bottomY = y
- if y < topY:
- topY = y
- if x > lastX:
- lastX = x
-
- black_pixel_in_col = True
-
- if black_pixel_in_col is False and started is True:
- rect = (firstX, topY, lastX, bottomY)
- new_captcha = captcha.crop(rect)
-
- w, h = new_captcha.size
- if w > 5 and h > 5:
- letters.append(new_captcha)
-
- started = False
- bottomY, topY = 0, height
-
- return letters
-
-
- def correct(self, values, var=None):
- if var:
- result = var
- else:
- result = self.result_captcha
-
- for key, item in values.iteritems():
-
- if key.__class__ == str:
- result = result.replace(key, item)
- else:
- for expr in key:
- result = result.replace(expr, item)
-
- if var:
- return result
- else:
- self.result_captcha = result
diff --git a/module/plugins/accounts/BackinNet.py b/module/plugins/accounts/BackinNet.py
deleted file mode 100644
index 46c8d7ac5..000000000
--- a/module/plugins/accounts/BackinNet.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.XFSAccount import XFSAccount
-
-
-class BackinNet(XFSAccount):
- __name__ = "BackinNet"
- __type__ = "account"
- __version__ = "0.01"
-
- __description__ = """Backin.net account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- HOSTER_DOMAIN = "backin.net"
diff --git a/module/plugins/accounts/CloudzillaTo.py b/module/plugins/accounts/CloudzillaTo.py
deleted file mode 100644
index d22d5e4b3..000000000
--- a/module/plugins/accounts/CloudzillaTo.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.Account import Account
-
-
-class CloudzillaTo(Account):
- __name__ = "CloudzillaTo"
- __type__ = "account"
- __version__ = "0.02"
-
- __description__ = """Cloudzilla.to account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- PREMIUM_PATTERN = r'<h2>account type</h2>\s*Premium Account'
-
-
- def loadAccountInfo(self, user, req):
- html = req.load("http://www.cloudzilla.to/")
-
- premium = True if re.search(self.PREMIUM_PATTERN, html) else False
-
- return {'validuntil': -1, 'trafficleft': -1, 'premium': premium}
-
-
- def login(self, user, data, req):
- html = req.load("http://www.cloudzilla.to/",
- post={'lusername': user,
- 'lpassword': data['password'],
- 'w' : "dologin"},
- decode=True)
-
- if "ERROR" in html:
- self.wrongPassword()
diff --git a/module/plugins/accounts/DropboxCom.py b/module/plugins/accounts/DropboxCom.py
deleted file mode 100644
index bcaa24b8e..000000000
--- a/module/plugins/accounts/DropboxCom.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class DropboxCom(SimpleHoster):
- __name__ = "DropboxCom"
- __type__ = "hoster"
- __version__ = "0.04"
-
- __pattern__ = r'https?://(?:www\.)?dropbox\.com/.+'
-
- __description__ = """Dropbox.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
-
-
- NAME_PATTERN = r'<title>Dropbox - (?P<N>.+?)<'
- SIZE_PATTERN = r'&nbsp;&middot;&nbsp; (?P<S>[\d.,]+) (?P<U>[\w^_]+)'
-
- OFFLINE_PATTERN = r'<title>Dropbox - (404|Shared link error)<'
-
- COOKIES = [("dropbox.com", "lang", "en")]
-
-
- def setup(self):
- self.multiDL = True
- self.chunkLimit = 1
- self.resumeDownload = True
-
-
- def handleFree(self, pyfile):
- self.download(pyfile.url, get={'dl': "1"})
-
-
-getInfo = create_getInfo(DropboxCom)
diff --git a/module/plugins/accounts/ExashareCom.py b/module/plugins/accounts/ExashareCom.py
deleted file mode 100644
index 431798522..000000000
--- a/module/plugins/accounts/ExashareCom.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.XFSAccount import XFSAccount
-
-
-class ExashareCom(XFSAccount):
- __name__ = "ExashareCom"
- __type__ = "account"
- __version__ = "0.01"
-
- __description__ = """Exashare.com account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- HOSTER_DOMAIN = "exashare.com"
diff --git a/module/plugins/accounts/JunkyvideoCom.py b/module/plugins/accounts/JunkyvideoCom.py
deleted file mode 100644
index 8275ff176..000000000
--- a/module/plugins/accounts/JunkyvideoCom.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.XFSAccount import XFSAccount
-
-
-class JunkyvideoCom(XFSAccount):
- __name__ = "JunkyvideoCom"
- __type__ = "account"
- __version__ = "0.01"
-
- __description__ = """Junkyvideo.com account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- HOSTER_DOMAIN = "junkyvideo.com"
diff --git a/module/plugins/accounts/MultihostersCom.py b/module/plugins/accounts/MultihostersCom.py
deleted file mode 100644
index e98f17b2d..000000000
--- a/module/plugins/accounts/MultihostersCom.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.accounts.ZeveraCom import ZeveraCom
-
-
-class MultihostersCom(ZeveraCom):
- __name__ = "MultihostersCom"
- __type__ = "account"
- __version__ = "0.03"
-
- __description__ = """Multihosters.com account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("tjeh", "tjeh@gmx.net")]
-
-
- HOSTER_DOMAIN = "multihosters.com"
diff --git a/module/plugins/accounts/NoPremiumPl.py b/module/plugins/accounts/NoPremiumPl.py
deleted file mode 100644
index a36b114eb..000000000
--- a/module/plugins/accounts/NoPremiumPl.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from datetime import datetime
-import hashlib
-
-from module.plugins.Account import Account
-from time import mktime
-from module.common.json_layer import json_loads as loads
-
-
-class NoPremiumPl(Account):
- __name__ = "NoPremiumPl"
- __version__ = "0.01"
- __type__ = "account"
- __description__ = "NoPremium.pl account plugin"
- __license__ = "GPLv3"
- __authors__ = [("goddie", "dev@nopremium.pl")]
-
- _api_url = "http://crypt.nopremium.pl"
-
- _api_query = {
- "site": "nopremium",
- "username": "",
- "password": "",
- "output": "json",
- "loc": "1",
- "info": "1"
- }
-
- _req = None
- _usr = None
- _pwd = None
-
- def loadAccountInfo(self, name, req):
- self._req = req
- try:
- result = loads(self.runAuthQuery())
- except Exception:
- # todo: return or let it be thrown?
- return
-
- premium = False
- valid_untill = -1
-
- if "expire" in result.keys() and result["expire"]:
- premium = True
- valid_untill = mktime(datetime.fromtimestamp(int(result["expire"])).timetuple())
- traffic_left = result["balance"] * 1024
-
- return ({
- "validuntil": valid_untill,
- "trafficleft": traffic_left,
- "premium": premium
- })
-
- def login(self, user, data, req):
- self._usr = user
- self._pwd = hashlib.sha1(hashlib.md5(data["password"]).hexdigest()).hexdigest()
- self._req = req
-
- try:
- response = loads(self.runAuthQuery())
- except Exception:
- self.wrongPassword()
-
- if "errno" in response.keys():
- self.wrongPassword()
- data['usr'] = self._usr
- data['pwd'] = self._pwd
-
- def createAuthQuery(self):
- query = self._api_query
- query["username"] = self._usr
- query["password"] = self._pwd
-
- return query
-
- def runAuthQuery(self):
- data = self._req.load(self._api_url, post=self.createAuthQuery())
-
- return data \ No newline at end of file
diff --git a/module/plugins/accounts/PutdriveCom.py b/module/plugins/accounts/PutdriveCom.py
deleted file mode 100644
index 4f2fadbcc..000000000
--- a/module/plugins/accounts/PutdriveCom.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.accounts.ZeveraCom import ZeveraCom
-
-
-class PutdriveCom(ZeveraCom):
- __name__ = "PutdriveCom"
- __type__ = "account"
- __version__ = "0.02"
-
- __description__ = """Putdrive.com account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- HOSTER_DOMAIN = "putdrive.com"
diff --git a/module/plugins/accounts/RapideoPl.py b/module/plugins/accounts/RapideoPl.py
deleted file mode 100644
index 426c680a6..000000000
--- a/module/plugins/accounts/RapideoPl.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from datetime import datetime
-import hashlib
-
-from module.plugins.Account import Account
-from time import mktime
-from module.common.json_layer import json_loads as loads
-
-
-class RapideoPl(Account):
- __name__ = "RapideoPl"
- __version__ = "0.01"
- __type__ = "account"
- __description__ = "Rapideo.pl account plugin"
- __license__ = "GPLv3"
- __authors__ = [("goddie", "dev@rapideo.pl")]
-
- _api_url = "http://enc.rapideo.pl"
-
- _api_query = {
- "site": "newrd",
- "username": "",
- "password": "",
- "output": "json",
- "loc": "1",
- "info": "1"
- }
-
- _req = None
- _usr = None
- _pwd = None
-
- def loadAccountInfo(self, name, req):
- self._req = req
- try:
- result = loads(self.runAuthQuery())
- except Exception:
- # todo: return or let it be thrown?
- return
-
- premium = False
- valid_untill = -1
- if "expire" in result.keys() and result["expire"]:
- premium = True
- valid_untill = mktime(datetime.fromtimestamp(int(result["expire"])).timetuple())
-
- traffic_left = result["balance"]
-
- return ({
- "validuntil": valid_untill,
- "trafficleft": traffic_left,
- "premium": premium
- })
-
- def login(self, user, data, req):
- self._usr = user
- self._pwd = hashlib.md5(data["password"]).hexdigest()
- self._req = req
- try:
- response = loads(self.runAuthQuery())
- except Exception:
- self.wrongPassword()
-
- if "errno" in response.keys():
- self.wrongPassword()
- data['usr'] = self._usr
- data['pwd'] = self._pwd
-
- def createAuthQuery(self):
- query = self._api_query
- query["username"] = self._usr
- query["password"] = self._pwd
-
- return query
-
- def runAuthQuery(self):
- data = self._req.load(self._api_url, post=self.createAuthQuery())
-
- return data \ No newline at end of file
diff --git a/module/plugins/accounts/RapiduNet.py b/module/plugins/accounts/RapiduNet.py
deleted file mode 100644
index 8da698c57..000000000
--- a/module/plugins/accounts/RapiduNet.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from time import time
-
-from module.plugins.Account import Account
-from module.common.json_layer import json_loads
-
-
-class RapiduNet(Account):
- __name__ = "RapiduNet"
- __type__ = "account"
- __version__ = "0.05"
-
- __description__ = """Rapidu.net account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("prOq", None),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- PREMIUM_PATTERN = r'>Account: <b>Premium'
-
- VALID_UNTIL_PATTERN = r'>Account: <b>\w+ \((\d+)'
-
- TRAFFIC_LEFT_PATTERN = r'class="tipsyS"><b>(.+?)<'
-
-
- def loadAccountInfo(self, user, req):
- validuntil = None
- trafficleft = -1
- premium = False
-
- html = req.load("https://rapidu.net/", decode=True)
-
- if re.search(self.PREMIUM_PATTERN, html):
- premium = True
-
- m = re.search(self.VALID_UNTIL_PATTERN, html)
- if m:
- validuntil = time() + (86400 * int(m.group(1)))
-
- m = re.search(self.TRAFFIC_LEFT_PATTERN, html)
- if m:
- trafficleft = self.parseTraffic(m.group(1))
-
- return {'validuntil': validuntil, 'trafficleft': trafficleft, 'premium': premium}
-
-
- def login(self, user, data, req):
- req.load("https://rapidu.net/ajax.php",
- get={'a': "getChangeLang"},
- post={'_go' : "",
- 'lang': "en"})
-
- json = json_loads(req.load("https://rapidu.net/ajax.php",
- get={'a': "getUserLogin"},
- post={'_go' : "",
- 'login' : user,
- 'pass' : data['password'],
- 'remember': "1"}))
-
- self.logDebug(json)
-
- if not json['message'] == "success":
- self.wrongPassword()
diff --git a/module/plugins/accounts/SmoozedCom.py b/module/plugins/accounts/SmoozedCom.py
deleted file mode 100644
index e6c25752b..000000000
--- a/module/plugins/accounts/SmoozedCom.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import hashlib
-
-from beaker.crypto.pbkdf2 import PBKDF2
-from time import time
-
-from module.common.json_layer import json_loads
-from module.plugins.Account import Account
-
-
-class SmoozedCom(Account):
- __name__ = "SmoozedCom"
- __type__ = "account"
- __version__ = "0.03"
-
- __description__ = """Smoozed.com account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("", "")]
-
-
- def loadAccountInfo(self, user, req):
- # Get user data from premiumize.me
- status = self.getAccountStatus(user, req)
-
- self.logDebug(status)
-
- if status['state'] != 'ok':
- info = {'validuntil' : None,
- 'trafficleft': None,
- 'premium' : False}
- else:
- # Parse account info
- info = {'validuntil' : float(status["data"]["user"]["user_premium"]),
- 'trafficleft': max(0, status["data"]["traffic"][1] - status["data"]["traffic"][0]),
- 'session' : status["data"]["session_key"],
- 'hosters' : [hoster["name"] for hoster in status["data"]["hoster"]]}
-
- if info['validuntil'] < time():
- info['premium'] = False
- else:
- info['premium'] = True
-
- return info
-
-
- def login(self, user, data, req):
- # Get user data from premiumize.me
- status = self.getAccountStatus(user, req)
-
- # Check if user and password are valid
- if status['state'] != 'ok':
- self.wrongPassword()
-
-
- def getAccountStatus(self, user, req):
- password = self.getAccountData(user)['password']
- salt = hashlib.sha256(password).hexdigest()
- encrypted = PBKDF2(password, salt, iterations=1000).hexread(32)
-
- return json_loads(req.load("http://www2.smoozed.com/api/login",
- get={'auth': user, 'password': encrypted}))
diff --git a/module/plugins/accounts/UploadableCh.py b/module/plugins/accounts/UploadableCh.py
deleted file mode 100644
index 86ae5dd17..000000000
--- a/module/plugins/accounts/UploadableCh.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.Account import Account
-
-
-class UploadableCh(Account):
- __name__ = "UploadableCh"
- __type__ = "account"
- __version__ = "0.03"
-
- __description__ = """Uploadable.ch account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Sasch", "gsasch@gmail.com")]
-
-
- def loadAccountInfo(self, user, req):
- html = req.load("http://www.uploadable.ch/login.php")
-
- premium = '<a href="/logout.php"' in html
- trafficleft = -1 if premium else None
-
- return {'validuntil': None, 'trafficleft': trafficleft, 'premium': premium} #@TODO: validuntil
-
-
- def login(self, user, data, req):
- html = req.load("http://www.uploadable.ch/login.php",
- post={'userName' : user,
- 'userPassword' : data["password"],
- 'autoLogin' : "1",
- 'action__login': "normalLogin"},
- decode=True)
-
- if "Login failed" in html:
- self.wrongPassword()
diff --git a/module/plugins/accounts/WebshareCz.py b/module/plugins/accounts/WebshareCz.py
deleted file mode 100644
index f8e3eeb73..000000000
--- a/module/plugins/accounts/WebshareCz.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from hashlib import md5, sha1
-from passlib.hash import md5_crypt
-from time import mktime, strptime, time
-
-from module.plugins.Account import Account
-
-
-class WebshareCz(Account):
- __name__ = "WebshareCz"
- __type__ = "account"
- __version__ = "0.07"
-
- __description__ = """Webshare.cz account plugin"""
- __license__ = "GPLv3"
- __authors__ = [("rush", "radek.senfeld@gmail.com")]
-
-
- VALID_UNTIL_PATTERN = r'<vip_until>(.+)</vip_until>'
-
- TRAFFIC_LEFT_PATTERN = r'<bytes>(.+)</bytes>'
-
-
- def loadAccountInfo(self, user, req):
- html = req.load("https://webshare.cz/api/user_data/",
- post={'wst': self.infos['wst']},
- decode=True)
-
- self.logDebug("Response: " + html)
-
- expiredate = re.search(self.VALID_UNTIL_PATTERN, html).group(1)
- self.logDebug("Expire date: " + expiredate)
-
- validuntil = mktime(strptime(expiredate, "%Y-%m-%d %H:%M:%S"))
- trafficleft = self.parseTraffic(re.search(self.TRAFFIC_LEFT_PATTERN, html).group(1))
- premium = validuntil > time()
-
- return {'validuntil': validuntil, 'trafficleft': -1, 'premium': premium}
-
-
- def login(self, user, data, req):
- salt = req.load("https://webshare.cz/api/salt/",
- post={'username_or_email': user,
- 'wst' : ""},
- decode=True)
-
- if "<status>OK</status>" not in salt:
- self.wrongPassword()
-
- salt = re.search('<salt>(.+)</salt>', salt).group(1)
- password = sha1(md5_crypt.encrypt(data["password"], salt=salt)).hexdigest()
- digest = md5(user + ":Webshare:" + password).hexdigest()
-
- login = req.load("https://webshare.cz/api/login/",
- post={'digest' : digest,
- 'keep_logged_in' : 1,
- 'password' : password,
- 'username_or_email': user,
- 'wst' : ""},
- decode=True)
-
- if "<status>OK</status>" not in login:
- self.wrongPassword()
-
- self.infos['wst'] = re.search('<token>(.+)</token>', login).group(1)
diff --git a/module/plugins/addon/ClickAndLoad.py b/module/plugins/addon/ClickAndLoad.py
deleted file mode 100644
index 5fe6e4bec..000000000
--- a/module/plugins/addon/ClickAndLoad.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from socket import socket, error
-from threading import Thread
-
-from pyload.plugin.Addon import Addon
-
-
-def forward(source, destination):
- string = ' '
- while string:
- string = source.recv(1024)
- if string:
- destination.sendall(string)
- else:
- #source.shutdown(socket.SHUT_RD)
- destination.shutdown(socket.SHUT_WR)
-
-
-class ClickAndLoad(Addon):
- __name__ = "ClickAndLoad"
- __type__ = "addon"
- __version__ = "0.23"
-
- __config__ = [("activated", "bool", "Activated" , True ),
- ("port" , "int" , "Port" , 9666 ),
- ("extern" , "bool", "Allow external link adding", False)]
-
- __description__ = """Click'N'Load hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.de"),
- ("mkaay", "mkaay@mkaay.de"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- def setup(self):
- self.interval = 300
-
-
- def activate(self):
- self.initPeriodical()
-
-
- def periodical(self):
- webip = "0.0.0.0" if self.getConfig("extern") else "127.0.0.1"
- webport = self.config['webinterface']['port']
- cnlport = self.getConfig("port"))
-
- try:
- s = socket()
- s.bind((webip, cnlport))
- s.listen(5)
-
- client = s.accept()[0]
- server = socket()
-
- server.connect(("127.0.0.1", webport))
-
- except error, e:
- if hasattr(e, "errno"):
- errno = e.errno
- else:
- errno = e.args[0]
-
- if errno == 98:
- self.logWarning(_("Port %d already in use") % cnlport)
- else:
- self.logDebug(e)
-
- else:
- self.core.scheduler.removeJob(self.cb)
- t = Thread(target=forward, args=[client, server])
- t.setDaemon(True)
- t.start()
diff --git a/module/plugins/addon/ExtractArchive.py b/module/plugins/addon/ExtractArchive.py
deleted file mode 100644
index 3ea8839dc..000000000
--- a/module/plugins/addon/ExtractArchive.py
+++ /dev/null
@@ -1,509 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import os
-import sys
-
-from copy import copy
-from traceback import print_exc
-
-# monkey patch bug in python 2.6 and lower
-# http://bugs.python.org/issue6122 , http://bugs.python.org/issue1236 , http://bugs.python.org/issue1731717
-if sys.version_info < (2, 7) and os.name != "nt":
- import errno
-
- from subprocess import Popen
-
- def _eintr_retry_call(func, *args):
- while True:
- try:
- return func(*args)
-
- except OSError, e:
- if e.errno == errno.EINTR:
- continue
- raise
-
-
- # unsued timeout option for older python version
- def wait(self, timeout=0):
- """Wait for child process to terminate. Returns returncode
- attribute."""
- if self.returncode is None:
- try:
- pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0)
- except OSError, e:
- if e.errno != errno.ECHILD:
- raise
- # This happens if SIGCLD is set to be ignored or waiting
- # for child processes has otherwise been disabled for our
- # process. This child is dead, we can't get the status.
- sts = 0
- self._handle_exitstatus(sts)
- return self.returncode
-
- Popen.wait = wait
-
-if os.name != "nt":
- from grp import getgrnam
- from pwd import getpwnam
-
-from module.plugins.Hook import Hook, threaded, Expose
-from module.plugins.internal.Extractor import ArchiveError, CRCError, PasswordError
-from module.plugins.internal.SimpleHoster import replace_patterns
-from module.utils import fs_encode, save_join, uniqify
-
-
-class ArchiveQueue(object):
-
- def __init__(self, plugin, storage):
- self.plugin = plugin
- self.storage = storage
-
-
- def get(self):
- try:
- return [int(pid) for pid in self.plugin.getStorage("ExtractArchive:%s" % self.storage, "").decode('base64').split()]
- except Exception:
- return []
-
-
- def set(self, value):
- if isinstance(value, list):
- item = str(value)[1:-1].replace(' ', '').replace(',', ' ')
- else:
- item = str(value).strip()
- return self.plugin.setStorage("ExtractArchive:%s" % self.storage, item.encode('base64')[:-1])
-
-
- def delete(self):
- return self.plugin.delStorage("ExtractArchive:%s" % self.storage)
-
-
- def add(self, item):
- queue = self.get()
- if item not in queue:
- return self.set(queue + [item])
- else:
- return True
-
-
- def remove(self, item):
- queue = self.get()
- try:
- queue.remove(item)
- except ValueError:
- pass
- if queue == []:
- return self.delete()
- return self.set(queue)
-
-
-
-class ExtractArchive(Hook):
- __name__ = "ExtractArchive"
- __type__ = "hook"
- __version__ = "1.29"
-
- __config__ = [("activated" , "bool" , "Activated" , True ),
- ("fullpath" , "bool" , "Extract with full paths" , True ),
- ("overwrite" , "bool" , "Overwrite files" , False ),
- ("keepbroken" , "bool" , "Try to extract broken archives" , False ),
- ("repair" , "bool" , "Repair broken archives" , True ),
- ("usepasswordfile" , "bool" , "Use password file" , True ),
- ("passwordfile" , "file" , "Password file" , "archive_password.txt" ),
- ("delete" , "bool" , "Delete archive when successfully extracted", False ),
- ("subfolder" , "bool" , "Create subfolder for each package" , False ),
- ("destination" , "folder", "Extract files to folder" , "" ),
- ("extensions" , "str" , "Extract the following extensions" , "7z,bz2,bzip2,gz,gzip,lha,lzh,lzma,rar,tar,taz,tbz,tbz2,tgz,xar,xz,z,zip"),
- ("excludefiles" , "str" , "Don't extract the following files" , "*.nfo,*.DS_Store,index.dat,thumb.db" ),
- ("recursive" , "bool" , "Extract archives in archives" , True ),
- ("waitall" , "bool" , "Wait for all downloads to be finished" , False ),
- ("renice" , "int" , "CPU priority" , 0 )]
-
- __description__ = """Extract different kind of archives"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com"),
- ("Immenz" , "immenz@gmx.net" )]
-
-
- event_list = ["allDownloadsProcessed"]
-
- NAME_REPLACEMENTS = [(r'\.part\d+\.rar$', ".part.rar")]
-
-
- #@TODO: Remove in 0.4.10
- def initPeriodical(self):
- pass
-
-
- def setup(self):
- self.queue = ArchiveQueue(self, "Queue")
- self.failed = ArchiveQueue(self, "Failed")
-
- self.interval = 60
- self.extracting = False
- self.extractors = []
- self.passwords = []
-
-
- def coreReady(self):
- # self.extracting = False
-
- for p in ("UnRar", "SevenZip", "UnZip"):
- try:
- module = self.core.pluginManager.loadModule("internal", p)
- klass = getattr(module, p)
- if klass.isUsable():
- self.extractors.append(klass)
-
- except OSError, e:
- if e.errno == 2:
- self.logInfo(_("No %s installed") % p)
- else:
- self.logWarning(_("Could not activate: %s") % p, e)
- if self.core.debug:
- print_exc()
-
- except Exception, e:
- self.logWarning(_("Could not activate: %s") % p, e)
- if self.core.debug:
- print_exc()
-
- if self.extractors:
- self.logInfo(_("Activated") + " " + "|".join("%s %s" % (Extractor.__name__,Extractor.VERSION) for Extractor in self.extractors))
-
- if self.getConfig("waitall"):
- self.extractPackage(*self.queue.get()) #: Resume unfinished extractions
- else:
- super(ExtractArchive, self).initPeriodical()
-
- else:
- self.logInfo(_("No Extract plugins activated"))
-
-
- def periodical(self):
- if not self.extracting:
- self.extractPackage(*self.queue.get())
-
-
- @Expose
- def extractPackage(self, *ids):
- """ Extract packages with given id"""
- self.manager.startThread(self.extract, ids)
-
-
- def packageFinished(self, pypack):
- self.queue.add(pypack.id)
-
-
- @threaded
- def allDownloadsProcessed(self, thread):
- if self.extract(self.queue.get(), thread): #@NOTE: check only if all gone fine, no failed reporting for now
- self.manager.dispatchEvent("all_archives_extracted")
-
- self.manager.dispatchEvent("all_archives_processed")
-
-
- def extract(self, ids, thread=None):
- if not ids:
- return False
-
- self.extracting = True
-
- processed = []
- extracted = []
- failed = []
-
- toList = lambda string: string.replace(' ', '').replace(',', '|').replace(';', '|').split('|')
-
- destination = self.getConfig("destination")
- subfolder = self.getConfig("subfolder")
- fullpath = self.getConfig("fullpath")
- overwrite = self.getConfig("overwrite")
- renice = self.getConfig("renice")
- recursive = self.getConfig("recursive")
- delete = self.getConfig("delete")
- keepbroken = self.getConfig("keepbroken")
-
- extensions = [x.lstrip('.').lower() for x in toList(self.getConfig("extensions"))]
- excludefiles = toList(self.getConfig("excludefiles"))
-
- if extensions:
- self.logDebug("Use for extensions: %s" % "|.".join(extensions))
-
- # reload from txt file
- self.reloadPasswords()
-
- # dl folder
- dl = self.config['general']['download_folder']
-
- #iterate packages -> extractors -> targets
- for pid in ids:
- pypack = self.core.files.getPackage(pid)
-
- if not pypack:
- continue
-
- self.logInfo(_("Check package: %s") % pypack.name)
-
- # determine output folder
- out = save_join(dl, pypack.folder, destination, "") #: force trailing slash
-
- if subfolder:
- out = save_join(out, pypack.folder)
-
- if not os.path.exists(out):
- os.makedirs(out)
-
- matched = False
- success = True
- files_ids = [(save_join(dl, pypack.folder, pylink['name']), pylink['id'], out) for pylink in pypack.getChildren().itervalues()]
-
- # check as long there are unseen files
- while files_ids:
- new_files_ids = []
-
- if extensions:
- files_ids = [(fname, fid, fout) for fname, fid, fout in files_ids \
- if filter(lambda ext: fname.lower().endswith(ext), extensions)]
-
- for Extractor in self.extractors:
- targets = Extractor.getTargets(files_ids)
- if targets:
- self.logDebug("Targets for %s: %s" % (Extractor.__name__, targets))
- matched = True
-
- for fname, fid, fout in targets:
- name = os.path.basename(fname)
-
- if not os.path.exists(fname):
- self.logDebug(name, "File not found")
- continue
-
- self.logInfo(name, _("Extract to: %s") % fout)
- try:
- archive = Extractor(self,
- fname,
- fout,
- fullpath,
- overwrite,
- excludefiles,
- renice,
- delete,
- keepbroken,
- fid)
- archive.init()
-
- new_files = self._extract(archive, fid, pypack.password, thread)
-
- except Exception, e:
- self.logError(name, e)
- success = False
- continue
-
- files_ids.remove((fname, fid, fout)) # don't let other extractors spam log
- self.logDebug("Extracted files: %s" % new_files)
- self.setPermissions(new_files)
-
- for filename in new_files:
- file = fs_encode(save_join(os.path.dirname(archive.filename), filename))
- if not os.path.exists(file):
- self.logDebug("New file %s does not exists" % filename)
- continue
-
- if recursive and os.path.isfile(file):
- new_files_ids.append((filename, fid, os.path.dirname(filename))) # append as new target
-
- files_ids = new_files_ids # also check extracted files
-
- if matched:
- if success:
- extracted.append(pid)
- self.manager.dispatchEvent("package_extracted", pypack)
- else:
- failed.append(pid)
- self.manager.dispatchEvent("package_extract_failed", pypack)
-
- self.failed.add(pid)
- else:
- self.logInfo(_("No files found to extract"))
-
- if not matched or not success and subfolder:
- try:
- os.rmdir(out)
-
- except OSError:
- pass
-
- self.queue.remove(pid)
-
- self.extracting = False
- return True if not failed else False
-
-
- def _extract(self, archive, fid, password, thread):
- pyfile = self.core.files.getFile(fid)
- name = os.path.basename(archive.filename)
-
- thread.addActive(pyfile)
- pyfile.setStatus("processing")
-
- encrypted = False
- try:
- try:
- archive.check()
-
- except CRCError, e:
- self.logDebug(name, e)
- self.logInfo(name, _("Header protected"))
-
- if self.getConfig("repair"):
- self.logWarning(name, _("Repairing..."))
-
- pyfile.setCustomStatus(_("repairing"))
- pyfile.setProgress(0)
-
- repaired = archive.repair()
-
- pyfile.setProgress(100)
-
- if not repaired and not self.getConfig("keepbroken"):
- raise CRCError("Archive damaged")
-
- except PasswordError:
- self.logInfo(name, _("Password protected"))
- encrypted = True
-
- except ArchiveError, e:
- raise ArchiveError(e)
-
- self.logDebug("Password: %s" % (password or "No provided"))
-
- pyfile.setCustomStatus(_("extracting"))
- pyfile.setProgress(0)
-
- if not encrypted or not self.getConfig("usepasswordfile"):
- archive.extract(password)
- else:
- for pw in filter(None, uniqify([password] + self.getPasswords(False))):
- try:
- self.logDebug("Try password: %s" % pw)
-
- ispw = archive.isPassword(pw)
- if ispw or ispw is None:
- archive.extract(pw)
- self.addPassword(pw)
- break
-
- except PasswordError:
- self.logDebug("Password was wrong")
- else:
- raise PasswordError
-
- pyfile.setProgress(100)
- pyfile.setCustomStatus(_("finalizing"))
-
- if self.core.debug:
- self.logDebug("Would delete: %s" % ", ".join(archive.getDeleteFiles()))
-
- if self.getConfig("delete"):
- files = archive.getDeleteFiles()
- self.logInfo(_("Deleting %s files") % len(files))
- for f in files:
- file = fs_encode(f)
- if os.path.exists(file):
- os.remove(file)
- else:
- self.logDebug("%s does not exists" % f)
-
- self.logInfo(name, _("Extracting finished"))
-
- extracted_files = archive.files or archive.list()
- self.manager.dispatchEvent("archive_extracted", pyfile, archive.out, archive.filename, extracted_files)
-
- return extracted_files
-
- except PasswordError:
- self.logError(name, _("Wrong password" if password else "No password found"))
-
- except CRCError, e:
- self.logError(name, _("CRC mismatch"), e)
-
- except ArchiveError, e:
- self.logError(name, _("Archive error"), e)
-
- except Exception, e:
- self.logError(name, _("Unknown error"), e)
- if self.core.debug:
- print_exc()
-
- finally:
- pyfile.finishIfDone()
-
- self.manager.dispatchEvent("archive_extract_failed", pyfile)
-
- raise Exception(_("Extract failed"))
-
-
- @Expose
- def getPasswords(self, reload=True):
- """ List of saved passwords """
- if reload:
- self.reloadPasswords()
-
- return self.passwords
-
-
- def reloadPasswords(self):
- try:
- passwords = []
-
- file = fs_encode(self.getConfig("passwordfile"))
- with open(file) as f:
- for pw in f.read().splitlines():
- passwords.append(pw)
-
- except IOError, e:
- self.logError(e)
-
- else:
- self.passwords = passwords
-
-
- @Expose
- def addPassword(self, password):
- """ Adds a password to saved list"""
- try:
- self.passwords = uniqify([password] + self.passwords)
-
- file = fs_encode(self.getConfig("passwordfile"))
- with open(file, "wb") as f:
- for pw in self.passwords:
- f.write(pw + '\n')
-
- except IOError, e:
- self.logError(e)
-
-
- def setPermissions(self, files):
- for f in files:
- if not os.path.exists(f):
- continue
-
- try:
- if self.config['permission']['change_file']:
- if os.path.isfile(f):
- os.chmod(f, int(self.config['permission']['file'], 8))
-
- elif os.path.isdir(f):
- os.chmod(f, int(self.config['permission']['folder'], 8))
-
- if self.config['permission']['change_dl'] and os.name != "nt":
- uid = getpwnam(self.config['permission']['user'])[2]
- gid = getgrnam(self.config['permission']['group'])[2]
- os.chown(f, uid, gid)
-
- except Exception, e:
- self.logWarning(_("Setting User and Group failed"), e)
diff --git a/module/plugins/addon/MergeFiles.py b/module/plugins/addon/MergeFiles.py
deleted file mode 100644
index 42ac3ff4d..000000000
--- a/module/plugins/addon/MergeFiles.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import os
-import re
-
-from traceback import print_exc
-
-from pyload.plugin.Addon import Addon, threaded
-from module.utils import safe_join
-
-
-class MergeFiles(Addon):
- __name__ = "MergeFiles"
- __type__ = "addon"
- __version__ = "0.14"
-
- __config__ = [("activated", "bool", "Activated", True)]
-
- __description__ = """Merges parts splitted with hjsplit"""
- __license__ = "GPLv3"
- __authors__ = [("and9000", "me@has-no-mail.com")]
-
-
- BUFFER_SIZE = 4096
-
-
- def setup(self):
- pass
-
-
- @threaded
- def packageFinished(self, pack):
- files = {}
- fid_dict = {}
- for fid, data in pack.getChildren().iteritems():
- if re.search("\.\d{3}$", data['name']):
- if data['name'][:-4] not in files:
- files[data['name'][:-4]] = []
- files[data['name'][:-4]].append(data['name'])
- files[data['name'][:-4]].sort()
- fid_dict[data['name']] = fid
-
- download_folder = self.config['general']['download_folder']
-
- if self.config['general']['folder_per_package']:
- download_folder = safe_join(download_folder, pack.folder)
-
- for name, file_list in files.iteritems():
- self.logInfo(_("Starting merging of"), name)
-
- final_file = open(safe_join(download_folder, name), "wb")
- for splitted_file in file_list:
- self.logDebug("Merging part", splitted_file)
-
- pyfile = self.core.files.getFile(fid_dict[splitted_file])
-
- pyfile.setStatus("processing")
-
- try:
- with open(save_join(download_folder, splitted_file), "rb") as s_file:
- size_written = 0
- s_file_size = int(os.path.getsize(os.path.join(download_folder, splitted_file)))
-
- while True:
- f_buffer = s_file.read(self.BUFFER_SIZE)
- if f_buffer:
- final_file.write(f_buffer)
- size_written += self.BUFFER_SIZE
- pyfile.setProgress((size_written * 100) / s_file_size)
- else:
- break
-
- self.logDebug("Finished merging part", splitted_file)
-
- except Exception, e:
- print_exc()
-
- finally:
- pyfile.setProgress(100)
- pyfile.setStatus("finished")
- pyfile.release()
-
- self.logInfo(_("Finished merging of"), name)
diff --git a/module/plugins/addon/SkipRev.py b/module/plugins/addon/SkipRev.py
deleted file mode 100644
index 0bbdec3b2..000000000
--- a/module/plugins/addon/SkipRev.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from types import MethodType
-from urllib import unquote
-from urlparse import urlparse
-
-from module.PyFile import PyFile
-from module.plugins.Hook import Hook
-from module.plugins.Plugin import SkipDownload
-
-
-def _setup(self):
- self.pyfile.plugin._setup()
- if self.pyfile.hasStatus("skipped"):
- raise SkipDownload(self.pyfile.statusname or self.pyfile.pluginname)
-
-
-class SkipRev(Hook):
- __name__ = "SkipRev"
- __type__ = "hook"
- __version__ = "0.25"
-
- __config__ = [("tokeep", "int", "Number of rev files to keep for package (-1 to auto)", -1)]
-
- __description__ = """Skip files ending with extension rev"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- #@TODO: Remove in 0.4.10
- def initPeriodical(self):
- pass
-
-
- def _pyname(self, pyfile):
- if hasattr(pyfile.pluginmodule, "getInfo"):
- return getattr(pyfile.pluginmodule, "getInfo")([pyfile.url]).next()[0]
- else:
- self.logWarning("Unable to grab file name")
- return urlparse(unquote(pyfile.url)).path.split('/')[-1]
-
-
- def _pyfile(self, link):
- return PyFile(self.core.files,
- link.fid,
- link.url,
- link.name,
- link.size,
- link.status,
- link.error,
- link.plugin,
- link.packageID,
- link.order)
-
-
- def downloadPreparing(self, pyfile):
- if pyfile.statusname is "unskipped" or not self._pyname(pyfile).endswith(".rev"):
- return
-
- tokeep = self.getConfig("tokeep")
-
- if tokeep:
- status_list = (1, 4, 8, 9, 14) if tokeep < 0 else (1, 3, 4, 8, 9, 14)
-
- queued = [True for link in self.core.api.getPackageData(pyfile.package().id).links \
- if link.name.endswith(".rev") and link.status not in status_list].count(True)
-
- if not queued or queued < tokeep: #: keep one rev at least in auto mode
- return
-
- pyfile.setCustomStatus("SkipRev", "skipped")
- pyfile.plugin._setup = pyfile.plugin.setup
- pyfile.plugin.setup = MethodType(_setup, pyfile.plugin) #: work-around: inject status checker inside the preprocessing routine of the plugin
-
-
- def downloadFailed(self, pyfile):
- #: Check if pyfile is still "failed",
- # maybe might has been restarted in meantime
- if pyfile.status != 8:
- return
-
- tokeep = self.getConfig("tokeep")
-
- if not tokeep:
- return
-
- for link in self.core.api.getPackageData(pyfile.package().id).links:
- if link.status is 4 and link.name.endswith(".rev"):
- pylink = self._pyfile(link)
-
- if tokeep > -1 or pyfile.name.endswith(".rev"):
- pylink.setStatus("queued")
- else:
- pylink.setCustomStatus("unskipped", "queued")
-
- self.core.files.save()
- pylink.release()
- return
diff --git a/module/plugins/addon/UnSkipOnFail.py b/module/plugins/addon/UnSkipOnFail.py
deleted file mode 100644
index 1becb937a..000000000
--- a/module/plugins/addon/UnSkipOnFail.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.PyFile import PyFile
-from module.plugins.Hook import Hook
-
-
-class UnSkipOnFail(Hook):
- __name__ = "UnSkipOnFail"
- __type__ = "hook"
- __version__ = "0.05"
-
- __config__ = [("activated", "bool", "Activated", True)]
-
- __description__ = """Queue skipped duplicates when download fails"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- #@TODO: Remove in 0.4.10
- def initPeriodical(self):
- pass
-
-
- def downloadFailed(self, pyfile):
- #: Check if pyfile is still "failed",
- # maybe might has been restarted in meantime
- if pyfile.status != 8:
- return
-
- msg = _("Looking for skipped duplicates of: %s (pid:%s)")
- self.logInfo(msg % (pyfile.name, pyfile.package().id))
-
- dup = self.findDuplicate(pyfile)
- if dup:
- self.logInfo(_("Queue found duplicate: %s (pid:%s)") % (dup.name, dup.packageID))
-
- #: Change status of "link" to "new_status".
- # "link" has to be a valid FileData object,
- # "new_status" has to be a valid status name
- # (i.e. "queued" for this Plugin)
- # It creates a temporary PyFile object using
- # "link" data, changes its status, and tells
- # the core.files-manager to save its data.
- pylink = _pyfile(link)
-
- pylink.setCustomStatus("UnSkipOnFail", "queued")
-
- self.core.files.save()
- pylink.release()
-
- else:
- self.logInfo(_("No duplicates found"))
-
-
- def findDuplicate(self, pyfile):
- """ Search all packages for duplicate links to "pyfile".
- Duplicates are links that would overwrite "pyfile".
- To test on duplicity the package-folder and link-name
- of twolinks are compared (link.name).
- So this method returns a list of all links with equal
- package-folders and filenames as "pyfile", but except
- the data for "pyfile" iotselöf.
- It does MOT check the link's status.
- """
- queue = self.core.api.getQueue() #: get packages (w/o files, as most file data is useless here)
-
- for package in queue:
- #: check if package-folder equals pyfile's package folder
- if package.folder != pyfile.package().folder:
- continue
-
- #: now get packaged data w/ files/links
- pdata = self.core.api.getPackageData(package.pid)
- for link in pdata.links:
- #: check if link is "skipped"
- if link.status != 4:
- continue
-
- #: check if link name collides with pdata's name
- #: AND at last check if it is not pyfile itself
- if link.name == pyfile.name and link.fid != pyfile.id:
- return link
-
-
- def _pyfile(self, link):
- return PyFile(self.core.files,
- link.fid,
- link.url,
- link.name,
- link.size,
- link.status,
- link.error,
- link.plugin,
- link.packageID,
- link.order)
diff --git a/module/plugins/addon/UpdateManager.py b/module/plugins/addon/UpdateManager.py
deleted file mode 100644
index efccc73fb..000000000
--- a/module/plugins/addon/UpdateManager.py
+++ /dev/null
@@ -1,306 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import re
-import sys
-
-from operator import itemgetter
-from os import path, remove, stat
-
-from pyload.network.RequestFactory import getURL
-from pyload.plugin.Addon import Expose, Addon, threaded
-from pyload.utils import safe_join
-
-
-class UpdateManager(Addon):
- __name__ = "UpdateManager"
- __type__ = "addon"
- __version__ = "0.43"
-
- __config__ = [("activated" , "bool" , "Activated" , True ),
- ("mode" , "pyLoad + plugins;plugins only", "Check updates for" , "pyLoad + plugins"),
- ("interval" , "int" , "Check interval in hours" , 8 ),
- ("autorestart" , "bool" , "Automatically restart pyLoad when required" , True ),
- ("reloadplugins", "bool" , "Monitor plugins for code changes in debug mode", True ),
- ("nodebugupdate", "bool" , "Don't check for updates in debug mode" , False )]
-
- __description__ = """Check for updates"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- # event_list = ["pluginConfigChanged"]
-
- SERVER_URL = "http://updatemanager.pyload.org"
- VERSION = re.compile(r'__version__.*=.*("|\')([\d.]+)')
- MIN_INTERVAL = 3 * 60 * 60 #: 3h minimum check interval (value is in seconds)
-
-
- def pluginConfigChanged(self, plugin, name, value):
- if name == "interval":
- interval = value * 60 * 60
- if self.MIN_INTERVAL <= interval != self.interval:
- self.core.scheduler.removeJob(self.cb)
- self.interval = interval
- self.initPeriodical()
- else:
- self.logDebug("Invalid interval value, kept current")
-
- elif name == "reloadplugins":
- if self.cb2:
- self.core.scheduler.removeJob(self.cb2)
- if value is True and self.core.debug:
- self.periodical2()
-
-
- def activate(self):
- self.pluginConfigChanged(self.__name__, "interval", self.getConfig("interval"))
- x = lambda: self.pluginConfigChanged(self.__name__, "reloadplugins", self.getConfig("reloadplugins"))
- self.core.scheduler.addJob(10, x, threaded=False)
-
-
- def deactivate(self):
- self.pluginConfigChanged(self.__name__, "reloadplugins", False)
-
-
- def setup(self):
- self.cb2 = None
- self.interval = 0
- self.updating = False
- self.info = {'pyload': False, 'version': None, 'plugins': False}
- self.mtimes = {} #: store modification time for each plugin
-
-
- def periodical2(self):
- if not self.updating:
- self.autoreloadPlugins()
-
- self.cb2 = self.core.scheduler.addJob(4, self.periodical2, threaded=False)
-
-
- @Expose
- def autoreloadPlugins(self):
- """ reload and reindex all modified plugins """
- modules = filter(
- lambda m: m and (m.__name__.startswith("pyload.plugin.") or
- m.__name__.startswith("userplugins.")) and
- m.__name__.count(".") >= 2, sys.modules.itervalues()
- )
-
- reloads = []
-
- for m in modules:
- root, type, name = m.__name__.rsplit(".", 2)
- id = (type, name)
- if type in self.core.pluginManager.plugins:
- f = m.__file__.replace(".pyc", ".py")
- if not path.isfile(f):
- continue
-
- mtime = stat(f).st_mtime
-
- if id not in self.mtimes:
- self.mtimes[id] = mtime
- elif self.mtimes[id] < mtime:
- reloads.append(id)
- self.mtimes[id] = mtime
-
- return True if self.core.pluginManager.reloadPlugins(reloads) else False
-
-
- def periodical(self):
- if self.info['pyload'] or self.getConfig("nodebugupdate") and self.core.debug:
- return
-
- self.updateThread()
-
-
- def server_request(self):
- try:
- return getURL(self.SERVER_URL, get={'v': self.core.api.getServerVersion()}).splitlines()
- except Exception:
- self.logWarning(_("Unable to contact server to get updates"))
-
-
- @threaded
- def updateThread(self):
- self.updating = True
-
- status = self.update(onlyplugin=self.getConfig("mode") == "plugins only")
-
- if status is 2 and self.getConfig("autorestart"):
- self.core.api.restart()
- else:
- self.updating = False
-
-
- @Expose
- def updatePlugins(self):
- """ simple wrapper for calling plugin update quickly """
- return self.update(onlyplugin=True)
-
-
- @Expose
- def update(self, onlyplugin=False):
- """ check for updates """
- data = self.server_request()
-
- if not data:
- exitcode = 0
-
- elif data[0] == "None":
- self.logInfo(_("No new pyLoad version available"))
- updates = data[1:]
- exitcode = self._updatePlugins(updates)
-
- elif onlyplugin:
- exitcode = 0
-
- else:
- newversion = data[0]
- self.logInfo(_("*** New pyLoad Version %s available ***") % newversion)
- self.logInfo(_("*** Get it here: https://github.com/pyload/pyload/releases ***"))
- exitcode = 3
- self.info['pyload'] = True
- self.info['version'] = newversion
-
- return exitcode #: 0 = No plugins updated; 1 = Plugins updated; 2 = Plugins updated, but restart required; 3 = No plugins updated, new pyLoad version available
-
-
- def _updatePlugins(self, updates):
- """ check for plugin updates """
-
- if self.info['plugins']:
- return False #: plugins were already updated
-
- exitcode = 0
- updated = []
-
- url = updates[0]
- schema = updates[1].split('|')
-
- if "BLACKLIST" in updates:
- blacklist = updates[updates.index('BLACKLIST') + 1:]
- updates = updates[2:updates.index('BLACKLIST')]
- else:
- blacklist = None
- updates = updates[2:]
-
- upgradable = [dict(zip(schema, x.split('|'))) for x in updates]
- blacklisted = [(x.split('|')[0], x.split('|')[1].rsplit('.', 1)[0]) for x in blacklist] if blacklist else []
-
- if blacklist:
- # Protect UpdateManager from self-removing
- try:
- blacklisted.remove(("hook", "UpdateManager"))
- except Exception:
- pass
-
- for t, n in blacklisted:
- for idx, plugin in enumerate(upgradable):
- if n == plugin['name'] and t == plugin['type']:
- upgradable.pop(idx)
- break
-
- for t, n in self.removePlugins(sorted(blacklisted)):
- self.logInfo(_("Removed blacklisted plugin [%(type)s] %(name)s") % {
- 'type': t,
- 'name': n,
- })
-
- for plugin in sorted(upgradable, key=itemgetter("type", "name")):
- filename = plugin['name']
- type = plugin['type']
- version = plugin['version']
-
- if filename.endswith(".pyc"):
- name = filename[:filename.find("_")]
- else:
- name = filename.replace(".py", "")
-
- plugins = getattr(self.core.pluginManager, "%sPlugins" % type)
-
- oldver = float(plugins[name]['version']) if name in plugins else None
- newver = float(version)
-
- if not oldver:
- msg = "New plugin: [%(type)s] %(name)s (v%(newver).2f)"
- elif newver > oldver:
- msg = "New version of plugin: [%(type)s] %(name)s (v%(oldver).2f -> v%(newver).2f)"
- else:
- continue
-
- self.logInfo(_(msg) % {'type' : type,
- 'name' : name,
- 'oldver': oldver,
- 'newver': newver})
- try:
- content = getURL(url % plugin)
- m = self.VERSION.search(content)
-
- if m and m.group(2) == version:
- with open(safe_join("userplugins", prefix, filename), "wb") as f:
- f.write(content)
-
- updated.append((prefix, name))
- else:
- raise Exception, _("Version mismatch")
-
- except Exception, e:
- self.logError(_("Error updating plugin: %s") % filename, str(e))
-
- if updated:
- reloaded = self.core.pluginManager.reloadPlugins(updated)
- if reloaded:
- self.logInfo(_("Plugins updated and reloaded"))
- exitcode = 1
- else:
- self.logInfo(_("*** Plugins have been updated, but need a pyLoad restart to be reloaded ***"))
- self.info['plugins'] = True
- exitcode = 2
- else:
- self.logInfo(_("No plugin updates available"))
-
- return exitcode #: 0 = No plugins updated; 1 = Plugins updated; 2 = Plugins updated, but restart required
-
-
- @Expose
- def removePlugins(self, type_plugins):
- """ delete plugins from disk """
-
- if not type_plugins:
- return
-
- self.logDebug("Requested deletion of plugins: %s" % type_plugins)
-
- removed = []
-
- for type, name in type_plugins:
- err = False
- file = name + ".py"
-
- for root in ("userplugins", path.join(pypath, "pyload", "plugins")):
-
- filename = safe_join(root, type, file)
- try:
- remove(filename)
- except Exception, e:
- self.logDebug("Error deleting: %s" % path.basename(filename), e)
- err = True
-
- filename += "c"
- if path.isfile(filename):
- try:
- if type == "addon":
- self.manager.deactivateAddon(name)
- remove(filename)
- except Exception, e:
- self.logDebug("Error deleting: %s" % path.basename(filename), e)
- err = True
-
- if not err:
- id = (type, name)
- removed.append(id)
-
- return removed #: return a list of the plugins successfully removed
diff --git a/module/plugins/captcha/AdYouLike.py b/module/plugins/captcha/AdYouLike.py
deleted file mode 100644
index bfb8b5ccb..000000000
--- a/module/plugins/captcha/AdYouLike.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.Captcha import Captcha
-from pyload.utils import json_loads
-
-
-class AdYouLike(Captcha):
- __name__ = "AdYouLike"
- __type__ = "captcha"
- __version__ = "0.02"
-
- __description__ = """AdYouLike captcha service plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- AYL_PATTERN = r'Adyoulike\.create\s*\((.+?)\)'
- CALLBACK_PATTERN = r'(Adyoulike\.g\._jsonp_\d+)'
-
-
- def detect_key(self, html=None):
- if not html:
- if hasattr(self.plugin, "html") and self.plugin.html:
- html = self.plugin.html
- else:
- errmsg = _("AdYouLike html not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- m = re.search(self.AYL_PATTERN, html)
- n = re.search(self.CALLBACK_PATTERN, html)
- if m and n:
- self.key = (m.group(1).strip(), n.group(1).strip())
- self.plugin.logDebug("AdYouLike ayl|callback: %s | %s" % self.key)
- return self.key #: key is the tuple(ayl, callback)
- else:
- self.plugin.logDebug("AdYouLike ayl or callback not found")
- return None
-
-
- def challenge(self, key=None):
- if not key:
- if self.detect_key():
- key = self.key
- else:
- errmsg = _("AdYouLike key not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- ayl, callback = key
-
- # {"adyoulike":{"key":"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"},
- # "all":{"element_id":"ayl_private_cap_92300","lang":"fr","env":"prod"}}
- ayl = json_loads(ayl)
-
- html = self.plugin.req.load("http://api-ayl.appspot.com/challenge",
- get={'key' : ayl['adyoulike']['key'],
- 'env' : ayl['all']['env'],
- 'callback': callback})
- try:
- challenge = json_loads(re.search(callback + r'\s*\((.+?)\)', html).group(1))
- except Exception:
- errmsg = _("AdYouLike challenge pattern not found")
- self.plugin.error(errmsg)
- raise ValueError(errmsg)
-
- self.plugin.logDebug("AdYouLike challenge: %s" % challenge)
-
- return self.result(ayl, challenge)
-
-
- def result(self, server, challenge):
- # Adyoulike.g._jsonp_5579316662423138
- # ({"translations":{"fr":{"instructions_visual":"Recopiez « Soonnight » ci-dessous :"}},
- # "site_under":true,"clickable":true,"pixels":{"VIDEO_050":[],"DISPLAY":[],"VIDEO_000":[],"VIDEO_100":[],
- # "VIDEO_025":[],"VIDEO_075":[]},"medium_type":"image/adyoulike",
- # "iframes":{"big":"<iframe src=\"http://www.soonnight.com/campagn.html\" scrolling=\"no\"
- # height=\"250\" width=\"300\" frameborder=\"0\"></iframe>"},"shares":{},"id":256,
- # "token":"e6QuI4aRSnbIZJg02IsV6cp4JQ9~MjA1","formats":{"small":{"y":300,"x":0,"w":300,"h":60},
- # "big":{"y":0,"x":0,"w":300,"h":250},"hover":{"y":440,"x":0,"w":300,"h":60}},
- # "tid":"SqwuAdxT1EZoi4B5q0T63LN2AkiCJBg5"})
-
- if isinstance(server, basestring):
- server = json_loads(server)
-
- if isinstance(challenge, basestring):
- challenge = json_loads(challenge)
-
- try:
- instructions_visual = challenge['translations'][server['all']['lang']]['instructions_visual']
- result = re.search(u'«(.+?)»', instructions_visual).group(1).strip()
- except Exception:
- errmsg = _("AdYouLike result not found")
- self.plugin.error(errmsg)
- raise ValueError(errmsg)
-
- result = {'_ayl_captcha_engine' : "adyoulike",
- '_ayl_env' : server['all']['env'],
- '_ayl_tid' : challenge['tid'],
- '_ayl_token_challenge': challenge['token'],
- '_ayl_response' : response}
-
- self.plugin.logDebug("AdYouLike result: %s" % result)
-
- return result
diff --git a/module/plugins/captcha/AdsCaptcha.py b/module/plugins/captcha/AdsCaptcha.py
deleted file mode 100644
index 5c01a422e..000000000
--- a/module/plugins/captcha/AdsCaptcha.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from random import random
-
-from pyload.plugin.Captcha import Captcha
-
-
-class AdsCaptcha(Captcha):
- __name__ = "AdsCaptcha"
- __type__ = "captcha"
- __version__ = "0.06"
-
- __description__ = """AdsCaptcha captcha service plugin"""
- __license__ = "GPLv3"
- __authors__ = [("pyLoad Team", "admin@pyload.org")]
-
-
- CAPTCHAID_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*CaptchaId=(\d+)'
- PUBLICKEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*PublicKey=([\w-]+)'
-
-
- def detect_key(self, html=None):
- if not html:
- if hasattr(self.plugin, "html") and self.plugin.html:
- html = self.plugin.html
- else:
- errmsg = _("AdsCaptcha html not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- m = re.search(self.PUBLICKEY_PATTERN, html)
- n = re.search(self.CAPTCHAID_PATTERN, html)
- if m and n:
- self.key = (m.group(1).strip(), n.group(1).strip()) #: key is the tuple(PublicKey, CaptchaId)
- self.plugin.logDebug("AdsCaptcha key|id: %s | %s" % self.key)
- return self.key
- else:
- self.plugin.logDebug("AdsCaptcha key or id not found")
- return None
-
-
- def challenge(self, key=None):
- if not key:
- if self.detect_key():
- key = self.key
- else:
- errmsg = _("AdsCaptcha key not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- PublicKey, CaptchaId = key
-
- html = self.plugin.req.load("http://api.adscaptcha.com/Get.aspx", get={'CaptchaId': CaptchaId, 'PublicKey': PublicKey})
- try:
- challenge = re.search("challenge: '(.+?)',", html).group(1)
- server = re.search("server: '(.+?)',", html).group(1)
- except Exception:
- errmsg = _("AdsCaptcha challenge pattern not found")
- self.plugin.error(errmsg)
- raise ValueError(errmsg)
-
- self.plugin.logDebug("AdsCaptcha challenge: %s" % challenge)
-
- return challenge, self.result(server, challenge)
-
-
- def result(self, server, challenge):
- result = self.plugin.decryptCaptcha("%sChallenge.aspx" % server,
- get={'cid': challenge, 'dummy': random()},
- cookies=True,
- imgtype="jpg")
-
- self.plugin.logDebug("AdsCaptcha result: %s" % result)
-
- return result
diff --git a/module/plugins/captcha/ReCaptcha.py b/module/plugins/captcha/ReCaptcha.py
deleted file mode 100644
index 4b900c57b..000000000
--- a/module/plugins/captcha/ReCaptcha.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.Captcha import Captcha
-
-
-class ReCaptcha(Captcha):
- __name__ = "ReCaptcha"
- __type__ = "captcha"
- __version__ = "0.08"
-
- __description__ = """ReCaptcha captcha service plugin"""
- __license__ = "GPLv3"
- __authors__ = [("pyLoad Team", "admin@pyload.org")]
-
-
- KEY_PATTERN = r'recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=([\w-]+)'
- KEY_AJAX_PATTERN = r'Recaptcha\.create\s*\(\s*["\']([\w-]+)'
-
-
- def detect_key(self, html=None):
- if not html:
- if hasattr(self.plugin, "html") and self.plugin.html:
- html = self.plugin.html
- else:
- errmsg = _("ReCaptcha html not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- m = re.search(self.KEY_PATTERN, html) or re.search(self.KEY_AJAX_PATTERN, html)
- if m:
- self.key = m.group(1).strip()
- self.plugin.logDebug("ReCaptcha key: %s" % self.key)
- return self.key
- else:
- self.plugin.logDebug("ReCaptcha key not found")
- return None
-
-
- def challenge(self, key=None):
- if not key:
- if self.detect_key():
- key = self.key
- else:
- errmsg = _("ReCaptcha key not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- html = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge", get={'k': key})
- try:
- challenge = re.search("challenge : '(.+?)',", html).group(1)
- server = re.search("server : '(.+?)',", html).group(1)
- except Exception:
- errmsg = _("ReCaptcha challenge pattern not found")
- self.plugin.error(errmsg)
- raise ValueError(errmsg)
-
- self.plugin.logDebug("ReCaptcha challenge: %s" % challenge)
-
- return challenge, self.result(server, challenge)
-
-
- def result(self, server, challenge):
- result = self.plugin.decryptCaptcha("%simage" % server,
- get={'c': challenge},
- cookies=True,
- forceUser=True,
- imgtype="jpg")
-
- self.plugin.logDebug("ReCaptcha result: %s" % result)
-
- return result
diff --git a/module/plugins/captcha/SolveMedia.py b/module/plugins/captcha/SolveMedia.py
deleted file mode 100644
index 6e2a6c362..000000000
--- a/module/plugins/captcha/SolveMedia.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.Captcha import Captcha
-
-
-class SolveMedia(Captcha):
- __name__ = "SolveMedia"
- __type__ = "captcha"
- __version__ = "0.06"
-
- __description__ = """SolveMedia captcha service plugin"""
- __license__ = "GPLv3"
- __authors__ = [("pyLoad Team", "admin@pyload.org")]
-
-
- KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(?:no)?script\?k=(.+?)["\']'
-
-
- def challenge(self, key=None):
- if not key:
- if self.detect_key():
- key = self.key
- else:
- errmsg = _("SolveMedia key not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.noscript", get={'k': key})
- try:
- challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="([^"]+)">',
- html).group(1)
- server = "http://api.solvemedia.com/papi/media"
- except Exception:
- errmsg = _("SolveMedia challenge pattern not found")
- self.plugin.error(errmsg)
- raise ValueError(errmsg)
-
- self.plugin.logDebug("SolveMedia challenge: %s" % challenge)
-
- return challenge, self.result(server, challenge)
-
-
- def result(self, server, challenge):
- result = self.plugin.decryptCaptcha(server, get={'c': challenge}, imgtype="gif")
-
- self.plugin.logDebug("SolveMedia result: %s" % result)
-
- return result
diff --git a/module/plugins/container/CCF.py b/module/plugins/container/CCF.py
deleted file mode 100644
index 452b9bb65..000000000
--- a/module/plugins/container/CCF.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import re
-
-from urllib2 import build_opener
-
-from MultipartPostHandler import MultipartPostHandler
-
-from module.plugins.Container import Container
-from module.utils import fs_encode, save_join
-
-
-class CCF(Container):
- __name__ = "CCF"
- __type__ = "container"
- __version__ = "0.23"
-
- __pattern__ = r'.+\.ccf$'
-
- __description__ = """CCF container decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Willnix", "Willnix@pyload.org"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- def decrypt(self, pyfile):
- file = fs_encode(pyfile.url.strip())
- opener = build_opener(MultipartPostHandler)
-
- dlc_content = opener.open('http://service.jdownloader.net/dlcrypt/getDLC.php',
- {'src' : "ccf",
- 'filename': "test.ccf",
- 'upload' : open(file, "rb")}).read()
-
- download_folder = self.config['general']['download_folder']
- dlc_file = save_join(download_folder, "tmp_%s.dlc" % pyfile.name)
-
- try:
- dlc = re.search(r'<dlc>(.+)</dlc>', dlc_content, re.S).group(1).decode('base64')
-
- except AttributeError:
- self.fail(_("Container is corrupted"))
-
- with open(dlc_file, "w") as tempdlc:
- tempdlc.write(dlc)
-
- self.urls = [dlc_file]
diff --git a/module/plugins/container/DLC.py b/module/plugins/container/DLC.py
deleted file mode 100644
index b01e3098c..000000000
--- a/module/plugins/container/DLC.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import re
-import xml.dom.minidom
-
-from Crypto.Cipher import AES
-
-from module.plugins.Container import Container
-from module.utils import decode, fs_encode
-
-
-class DLC(Container):
- __name__ = "DLC"
- __type__ = "container"
- __version__ = "0.24"
-
- __pattern__ = r'.+\.dlc$'
-
- __description__ = """DLC container decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("spoob", "spoob@pyload.org"),
- ("mkaay", "mkaay@mkaay.de"),
- ("Schnusch", "Schnusch@users.noreply.github.com"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- KEY = "cb99b5cbc24db398"
- IV = "9bc24cb995cb8db3"
- API_URL = "http://service.jdownloader.org/dlcrypt/service.php?srcType=dlc&destType=pylo&data=%s"
-
-
- def decrypt(self, pyfile):
- file = fs_encode(pyfile.url.strip())
- with open(file) as dlc:
- data = dlc.read().strip()
-
- data += '=' * (-len(data) % 4)
-
- dlc_key = data[-88:]
- dlc_data = data[:-88].decode('base64')
- dlc_content = self.load(self.API_URL % dlc_key)
-
- try:
- rc = re.search(r'<rc>(.+)</rc>', dlc_content, re.S).group(1).decode('base64')
-
- except AttributeError:
- self.fail(_("Container is corrupted"))
-
- cipher = AES.new(self.KEY, AES.MODE_CBC, self.IV).decrypt(rc)
-
- self.data = AES.new(cipher, AES.MODE_CBC, cipher).decrypt(dlc_data).decode('base64')
- self.packages = [(entry[0] if entry[0] else pyfile.name, entry[1], entry[0] if entry[0] else pyfile.name) \
- for entry in self.getPackages()]
-
-
- def getPackages(self):
- root = xml.dom.minidom.parseString(self.data).documentElement
- content = root.getElementsByTagName("content")[0]
- return self.parsePackages(content)
-
-
- def parsePackages(self, startNode):
- return [(decode(node.getAttribute("name")).decode('base64'), self.parseLinks(node)) \
- for node in startNode.getElementsByTagName("package")]
-
-
- def parseLinks(self, startNode):
- return [node.getElementsByTagName("url")[0].firstChild.data.decode('base64') \
- for node in startNode.getElementsByTagName("file")]
diff --git a/module/plugins/container/LinkList.py b/module/plugins/container/LinkList.py
deleted file mode 100644
index ccb9b2fa3..000000000
--- a/module/plugins/container/LinkList.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import codecs
-
-from module.plugins.Container import Container
-from module.utils import fs_encode
-
-
-class LinkList(Container):
- __name__ = "LinkList"
- __type__ = "container"
- __version__ = "0.14"
-
- __pattern__ = r'.+\.txt$'
- __config__ = [("flush" , "bool" , "Flush list after adding", False ),
- ("encoding", "string", "File encoding" , "utf-8")]
-
- __description__ = """Read link lists in txt format"""
- __license__ = "GPLv3"
- __authors__ = [("spoob", "spoob@pyload.org"),
- ("jeix", "jeix@hasnomail.com")]
-
-
- def decrypt(self, pyfile):
- try:
- encoding = codecs.lookup(self.getConfig("encoding")).name
-
- except Exception:
- encoding = "utf-8"
-
- file = fs_encode(pyfile.url.strip())
- txt = codecs.open(file, 'r', encoding)
- curPack = "Parsed links from %s" % pyfile.name
- packages = {curPack:[],}
-
- for link in txt.readlines():
- link = link.strip()
-
- if not link:
- continue
-
- if link.startswith(";"):
- continue
-
- if link.startswith("[") and link.endswith("]"):
- # new package
- curPack = link[1:-1]
- packages[curPack] = []
- continue
-
- packages[curPack].append(link)
-
- txt.close()
-
- # empty packages fix
- for key, value in packages.iteritems():
- if not value:
- packages.pop(key, None)
-
- if self.getConfig("flush"):
- try:
- txt = open(file, 'wb')
- txt.close()
-
- except IOError:
- self.logWarning(_("Failed to flush list"))
-
- for name, links in packages.iteritems():
- self.packages.append((name, links, name))
diff --git a/module/plugins/container/RSDF.py b/module/plugins/container/RSDF.py
deleted file mode 100644
index 8f9bfc0d5..000000000
--- a/module/plugins/container/RSDF.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import binascii
-import re
-
-from Crypto.Cipher import AES
-
-from module.plugins.Container import Container
-from module.utils import fs_encode
-
-
-class RSDF(Container):
- __name__ = "RSDF"
- __type__ = "container"
- __version__ = "0.27"
-
- __pattern__ = r'.+\.rsdf$'
-
- __description__ = """RSDF container decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("spoob", "spoob@pyload.org"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- KEY = "8C35192D964DC3182C6F84F3252239EB4A320D2500000000"
- IV = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
-
-
- def decrypt(self, pyfile):
- KEY = binascii.unhexlify(self.KEY)
- IV = AES.new(Key, AES.MODE_ECB).encrypt(binascii.unhexlify(self.IV))
-
- cipher = AES.new(KEY, AES.MODE_CFB, IV)
-
- try:
- file = fs_encode(pyfile.url.strip())
- with open(file, 'r') as rsdf:
- data = rsdf.read()
-
- except IOError, e:
- self.fail(e)
-
- if re.search(r"<title>404 - Not Found</title>", data):
- return
-
- for link in binascii.unhexlify(''.join(data.split())).splitlines():
- if link:
- link = cipher.decrypt(link.decode('base64')).replace('CCF: ', '')
- self.urls.append(link)
diff --git a/module/plugins/crypter/BitshareCom.py b/module/plugins/crypter/BitshareCom.py
deleted file mode 100644
index 2960243fc..000000000
--- a/module/plugins/crypter/BitshareCom.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter
-
-
-class BitshareCom(SimpleCrypter):
- __name__ = "BitshareCom"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?bitshare\.com/\?d=\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Bitshare.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- LINK_PATTERN = r'<a href="(http://bitshare\.com/files/.+)">.+</a></td>'
- NAME_PATTERN = r'View public folder "(?P<N>.+)"</h1>'
-
-
-getInfo = create_getInfo(BitshareComFolder)
diff --git a/module/plugins/crypter/C1NeonCom.py b/module/plugins/crypter/C1NeonCom.py
deleted file mode 100644
index eaccb471f..000000000
--- a/module/plugins/crypter/C1NeonCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class C1NeonCom(DeadCrypter):
- __name__ = "C1NeonCom"
- __type__ = "crypter"
- __version__ = "0.05"
-
- __pattern__ = r'http://(?:www\.)?c1neon\.com/.+'
- __config__ = []
-
- __description__ = """C1neon.com decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("godofdream", "soilfiction@gmail.com")]
-
-
-getInfo = create_getInfo(C1NeonCom)
diff --git a/module/plugins/crypter/CloudzillaToFolder.py b/module/plugins/crypter/CloudzillaToFolder.py
deleted file mode 100644
index 76019d928..000000000
--- a/module/plugins/crypter/CloudzillaToFolder.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urlparse import urljoin
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
-
-
-class CloudzillaToFolder(SimpleHoster):
- __name__ = "CloudzillaToFolder"
- __type__ = "crypter"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?cloudzilla\.to/share/folder/(?P<ID>[\w^_]+)'
-
- __description__ = """Cloudzilla.to folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- INFO_PATTERN = r'<span class="name" title="(?P<N>.+?)"'
- OFFLINE_PATTERN = r'>File not found...<'
-
- LINK_PATTERN = r'<a href="(.+?)" class="item_href">'
-
- PASSWORD_PATTERN = r'<div id="pwd_protected">'
-
-
- def checkErrors(self):
- m = re.search(self.PASSWORD_PATTERN, self.html)
- if m:
- self.html = self.load(self.pyfile.url, get={'key': self.getPassword()})
-
- if re.search(self.PASSWORD_PATTERN, self.html):
- self.retry(reason="Wrong password")
-
-
-getInfo = create_getInfo(CloudzillaToFolder)
diff --git a/module/plugins/crypter/CrockoCom.py b/module/plugins/crypter/CrockoCom.py
deleted file mode 100644
index 9fad661d2..000000000
--- a/module/plugins/crypter/CrockoCom.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter
-
-
-class CrockoCom(SimpleCrypter):
- __name__ = "CrockoCom"
- __type__ = "crypter"
- __version__ = "0.01"
-
- __pattern__ = r'http://(?:www\.)?crocko\.com/f/.+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Crocko.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- LINK_PATTERN = r'<td class="last"><a href="([^"]+)">download</a>'
-
-
-getInfo = create_getInfo(CrockoComFolder)
diff --git a/module/plugins/crypter/CryptItCom.py b/module/plugins/crypter/CryptItCom.py
deleted file mode 100644
index cb3347f55..000000000
--- a/module/plugins/crypter/CryptItCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class CryptItCom(DeadCrypter):
- __name__ = "CryptItCom"
- __type__ = "crypter"
- __version__ = "0.11"
-
- __pattern__ = r'http://(?:www\.)?crypt-it\.com/(s|e|d|c)/\w+'
- __config__ = []
-
- __description__ = """Crypt-it.com decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("jeix", "jeix@hasnomail.de")]
-
-
-getInfo = create_getInfo(CryptItCom)
diff --git a/module/plugins/crypter/DataHu.py b/module/plugins/crypter/DataHu.py
deleted file mode 100644
index e8b3acbb7..000000000
--- a/module/plugins/crypter/DataHu.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter
-
-
-class DataHu(SimpleCrypter):
- __name__ = "DataHu"
- __type__ = "crypter"
- __version__ = "0.06"
-
- __pattern__ = r'http://(?:www\.)?data\.hu/dir/\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Data.hu folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("crash", ""),
- ("stickell", "l.stickell@yahoo.it")]
-
-
- LINK_PATTERN = r'<a href=\'(http://data\.hu/get/.+)\' target=\'_blank\'>\1</a>'
- NAME_PATTERN = ur'<title>(?P<N>.+) Let\xf6lt\xe9se</title>'
-
-
- def prepare(self):
- super(DataHu, self).prepare()
-
- if u'K\xe9rlek add meg a jelsz\xf3t' in self.html: # Password protected
- password = self.getPassword()
- if not password:
- self.fail(_("Password required"))
-
- self.logDebug("The folder is password protected', 'Using password: " + password)
-
- self.html = self.load(self.pyfile.url, post={'mappa_pass': password}, decode=True)
-
- if u'Hib\xe1s jelsz\xf3' in self.html: # Wrong password
- self.fail(_("Wrong password"))
-
-
-getInfo = create_getInfo(DataHuFolder)
diff --git a/module/plugins/crypter/DdlstorageCom.py b/module/plugins/crypter/DdlstorageCom.py
deleted file mode 100644
index 1d87e975b..000000000
--- a/module/plugins/crypter/DdlstorageCom.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class DdlstorageCom(DeadCrypter):
- __name__ = "DdlstorageCom"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'https?://(?:www\.)?ddlstorage\.com/folder/\w+'
- __config__ = []
-
- __description__ = """DDLStorage.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("godofdream", "soilfiction@gmail.com"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
-getInfo = create_getInfo(DdlstorageCom)
diff --git a/module/plugins/crypter/DepositfilesCom.py b/module/plugins/crypter/DepositfilesCom.py
deleted file mode 100644
index ba578a4ed..000000000
--- a/module/plugins/crypter/DepositfilesCom.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter
-
-
-class DepositfilesCom(SimpleCrypter):
- __name__ = "DepositfilesCom"
- __type__ = "crypter"
- __version__ = "0.01"
-
- __pattern__ = r'http://(?:www\.)?depositfiles\.com/folders/\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Depositfiles.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- LINK_PATTERN = r'<div class="progressName"[^>]*>\s*<a href="([^"]+)" title="[^"]*" target="_blank">'
-
-
-getInfo = create_getInfo(DepositfilesComFolder)
diff --git a/module/plugins/crypter/Dereferer.py b/module/plugins/crypter/Dereferer.py
deleted file mode 100644
index d52bb1094..000000000
--- a/module/plugins/crypter/Dereferer.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.Crypter import Crypter
-
-
-class Dereferer(SimpleDereferer):
- __name__ = "Dereferer"
- __type__ = "crypter"
- __version__ = "0.11"
-
- __pattern__ = r'https?://([^/]+)/.*?(?P<LINK>(ht|f)tps?(://|%3A%2F%2F).+)'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Crypter for dereferers"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/module/plugins/crypter/DevhostStFolder.py b/module/plugins/crypter/DevhostStFolder.py
deleted file mode 100644
index 2fbc90ba8..000000000
--- a/module/plugins/crypter/DevhostStFolder.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# http://d-h.st/users/shine/?fld_id=37263#files
-
-import re
-
-from urlparse import urljoin
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter
-
-
-class DevhostStFolder(SimpleCrypter):
- __name__ = "DevhostStFolder"
- __type__ = "crypter"
- __version__ = "0.04"
-
- __pattern__ = r'http://(?:www\.)?d-h\.st/users/(?P<USER>\w+)(/\?fld_id=(?P<ID>\d+))?'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """d-h.st folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- LINK_PATTERN = r'(?:/> |;">)<a href="(.+?)"(?!>Back to \w+<)'
- OFFLINE_PATTERN = r'"/cHP">test\.png<'
-
-
- def getFileInfo(self):
- if re.search(self.OFFLINE_PATTERN, self.html):
- self.offline()
-
- try:
- id = re.match(self.__pattern__, self.pyfile.url).group('ID')
- if id == "0":
- raise
-
- p = r'href="(.+?)">Back to \w+<'
- m = re.search(p, self.html)
- html = self.load(urljoin("http://d-h.st", m.group(1)),
- cookies=False)
-
- p = '\?fld_id=%s.*?">(.+?)<' % id
- m = re.search(p, html)
- name = folder = m.group(1)
-
- except Exception, e:
- self.logDebug(e)
- name = folder = re.match(self.__pattern__, self.pyfile.url).group('USER')
-
- return {'name': name, 'folder': folder}
-
-
-getInfo = create_getInfo(DevhostStFolder)
diff --git a/module/plugins/crypter/DlProtectCom.py b/module/plugins/crypter/DlProtectCom.py
deleted file mode 100644
index 1cfe7639a..000000000
--- a/module/plugins/crypter/DlProtectCom.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from base64 import urlsafe_b64encode
-from time import time
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter
-
-
-class DlProtectCom(SimpleCrypter):
- __name__ = "DlProtectCom"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'https?://(?:www\.)?dl-protect\.com/((en|fr)/)?\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Dl-protect.com decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- COOKIES = [("dl-protect.com", "l", "en")]
-
- OFFLINE_PATTERN = r'Unfortunately, the link you are looking for is not found'
-
-
- def getLinks(self):
- # Direct link with redirect
- if not re.match(r"https?://(?:www\.)?dl-protect\.com/.+", self.req.http.lastEffectiveURL):
- return [self.req.http.lastEffectiveURL]
-
- post_req = {'key' : re.search(r'name="key" value="(.+?)"', self.html).group(1),
- 'submitform': ""}
-
- if "Please click on continue to see the content" in self.html:
- post_req['submitform'] = "Continue"
- self.wait(2)
-
- else:
- mstime = int(round(time() * 1000))
- b64time = "_" + urlsafe_b64encode(str(mstime)).replace("=", "%3D")
-
- post_req.update({'i' : b64time,
- 'submitform': "Decrypt+link"})
-
- if "Password :" in self.html:
- post_req['pwd'] = self.getPassword()
-
- if "Security Code" in self.html:
- captcha_id = re.search(r'/captcha\.php\?uid=(.+?)"', self.html).group(1)
- captcha_url = "http://www.dl-protect.com/captcha.php?uid=" + captcha_id
- captcha_code = self.decryptCaptcha(captcha_url, imgtype="gif")
-
- post_req['secure'] = captcha_code
-
- self.html = self.load(self.pyfile.url, post=post_req)
-
- for errmsg in ("The password is incorrect", "The security code is incorrect"):
- if errmsg in self.html:
- self.fail(_(errmsg[1:]))
-
- return re.findall(r'<a href="([^/].+?)" target="_blank">', self.html)
-
-
-getInfo = create_getInfo(DlProtectCom)
diff --git a/module/plugins/crypter/DontKnowMe.py b/module/plugins/crypter/DontKnowMe.py
deleted file mode 100644
index 7a4b85b2d..000000000
--- a/module/plugins/crypter/DontKnowMe.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.Crypter import Crypter
-
-
-class DontKnowMe(SimpleDereferer):
- __name__ = "DontKnowMe"
- __type__ = "crypter"
- __version__ = "0.11"
-
- __pattern__ = r'http://(?:www\.)?dontknow\.me/at/\?(?P<LINK>.+)'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """DontKnow.me decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("selaux", "")]
diff --git a/module/plugins/crypter/DuploadOrg.py b/module/plugins/crypter/DuploadOrg.py
deleted file mode 100644
index 70745b550..000000000
--- a/module/plugins/crypter/DuploadOrg.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class DuploadOrg(DeadCrypter):
- __name__ = "DuploadOrg"
- __type__ = "crypter"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?dupload\.org/folder/\d+'
- __config__ = []
-
- __description__ = """Dupload.org folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
-getInfo = create_getInfo(DuploadOrg)
diff --git a/module/plugins/crypter/EasybytezCom.py b/module/plugins/crypter/EasybytezCom.py
deleted file mode 100644
index d9685e2f1..000000000
--- a/module/plugins/crypter/EasybytezCom.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.XFSCrypter import XFSCrypter
-
-
-class EasybytezCom(XFSCrypter):
- __name__ = "EasybytezCom"
- __type__ = "crypter"
- __version__ = "0.10"
-
- __pattern__ = r'http://(?:www\.)?easybytez\.com/users/\d+/\d+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Easybytez.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- LOGIN_ACCOUNT = True
-
-
-getInfo = create_getInfo(EasybytezComFolder)
diff --git a/module/plugins/crypter/FilebeerInfo.py b/module/plugins/crypter/FilebeerInfo.py
deleted file mode 100644
index 4e8ab1259..000000000
--- a/module/plugins/crypter/FilebeerInfo.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class FilebeerInfo(DeadCrypter):
- __name__ = "FilebeerInfo"
- __type__ = "crypter"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?filebeer\.info/\d*~f\w+'
- __config__ = []
-
- __description__ = """Filebeer.info folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(FilebeerInfo)
diff --git a/module/plugins/crypter/FilecloudIo.py b/module/plugins/crypter/FilecloudIo.py
deleted file mode 100644
index d0ca619de..000000000
--- a/module/plugins/crypter/FilecloudIo.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter
-
-
-class FilecloudIo(SimpleCrypter):
- __name__ = "FilecloudIo"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'https?://(?:www\.)?(filecloud\.io|ifile\.it)/_\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Filecloud.io folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- LINK_PATTERN = r'href="(http://filecloud\.io/\w+)" title'
- NAME_PATTERN = r'>(?P<N>.+?) - filecloud\.io<'
-
-
-getInfo = create_getInfo(FilecloudIoFolder)
diff --git a/module/plugins/crypter/FilecryptCc.py b/module/plugins/crypter/FilecryptCc.py
deleted file mode 100644
index 938ceafa9..000000000
--- a/module/plugins/crypter/FilecryptCc.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# http://filecrypt.cc/Container/64E039F859.html
-
-import binascii
-import re
-
-from Crypto.Cipher import AES
-from urlparse import urljoin
-
-from pyload.plugin.Crypter import Crypter
-from module.plugins.internal.CaptchaService import ReCaptcha
-
-
-class FilecryptCc(Crypter):
- __name__ = "FilecryptCc"
- __type__ = "crypter"
- __version__ = "0.11"
-
- __pattern__ = r'https?://(?:www\.)?filecrypt\.cc/Container/\w+'
-
- __description__ = """Filecrypt.cc decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
-
-
- # URL_REPLACEMENTS = [(r'.html$', ""), (r'$', ".html")] #@TODO: Extend SimpleCrypter
-
- DLC_LINK_PATTERN = r'<button class="dlcdownload" type="button" title="Download \*.dlc" onclick="DownloadDLC\(\'(.+)\'\);"><i></i><span>dlc<'
- WEBLINK_PATTERN = r"openLink.?'([\w_-]*)',"
-
- CAPTCHA_PATTERN = r'<img id="nc" src="(.+?)"'
- CIRCLE_CAPTCHA_PATTERN = r'<input type="image" src="(.+?)"'
-
- MIRROR_PAGE_PATTERN = r'"[\w]*" href="(http://filecrypt.cc/Container/\w+\.html\?mirror=\d+)">'
-
-
- def setup(self):
- self.links = []
-
-
- def decrypt(self, pyfile):
- self.html = self.load(pyfile.url, cookies=True)
-
- if "content notfound" in self.html: #@NOTE: "content notfound" is NOT a typo
- self.offline()
-
- self.handlePasswordProtection()
- self.handleCaptcha()
- self.handleMirrorPages()
-
- for handle in (self.handleCNL, self.handleWeblinks, self.handleDlcContainer):
- handle()
- if self.links:
- self.packages = [(pyfile.package().name, self.links, pyfile.package().name)]
- return
-
-
- def handleMirrorPages(self):
- if "mirror=" not in self.siteWithLinks:
- return
-
- mirror = re.findall(self.MIRROR_PAGE_PATTERN, self.siteWithLinks)
-
- self.logInfo(_("Found %d mirrors") % len(mirror))
-
- for i in mirror[1:]:
- self.siteWithLinks = self.siteWithLinks + self.load(i, cookies=True).decode("utf-8", "replace")
-
-
- def handlePasswordProtection(self):
- if '<input type="text" name="password"' not in self.html:
- return
-
- self.logInfo(_("Folder is password protected"))
-
- password = self.getPassword()
-
- if not password:
- self.fail(_("Please enter the password in package section and try again"))
-
- self.html = self.load(self.pyfile.url, post={"password": password}, cookies=True)
-
-
- def handleCaptcha(self):
- m = re.search(self.CAPTCHA_PATTERN, self.html)
- m2 = re.search(self.CIRCLE_CAPTCHA_PATTERN, self.html)
-
- if m: #: normal captcha
- self.logDebug("Captcha-URL: %s" % m.group(1))
-
- captcha_code = self.decryptCaptcha(urljoin("http://filecrypt.cc", m.group(1)),
- forceUser=True,
- imgtype="gif")
-
- self.siteWithLinks = self.load(self.pyfile.url,
- post={'recaptcha_response_field': captcha_code},
- cookies=True,
- decode=True)
- elif m2: #: circle captcha
- self.logDebug("Captcha-URL: %s" % m2.group(1))
-
- captcha_code = self.decryptCaptcha(urljoin("http://filecrypt.cc", m2.group(1)),
- forceUser=True,
- imgtype="gif",
- result_type='positional')
-
- self.siteWithLinks = self.load(self.pyfile.url,
- post={'button.x': captcha_code[0], 'button.y': captcha_code[1]},
- cookies=True,
- decode=True)
-
- else:
- recaptcha = ReCaptcha(self)
- captcha_key = recaptcha.detect_key()
-
- if captcha_key:
- response, challenge = recaptcha.challenge(captcha_key)
- self.siteWithLinks = self.load(self.pyfile.url,
- post={'g-recaptcha-response': response},
- decode=True)
- else:
- self.logInfo(_("No captcha found"))
- self.siteWithLinks = self.html
-
- if "recaptcha_image" in self.siteWithLinks or "data-sitekey" in self.siteWithLinks:
- self.invalidCaptcha()
- self.retry()
-
-
- def handleDlcContainer(self):
- dlc = re.findall(self.DLC_LINK_PATTERN, self.siteWithLinks)
-
- if not dlc:
- return
-
- for i in dlc:
- self.links.append("http://filecrypt.cc/DLC/%s.dlc" % i)
-
-
- def handleWeblinks(self):
- try:
- weblinks = re.findall(self.WEBLINK_PATTERN, self.siteWithLinks)
-
- for link in weblinks:
- res = self.load("http://filecrypt.cc/Link/%s.html" % link, cookies=True)
- link2 = re.search('<iframe noresize src="(.*)"></iframe>', res)
- res2 = self.load(link2.group(1), just_header=True, cookies=True)
- self.links.append(res2['location'])
-
- except Exception, e:
- self.logDebug("Error decrypting weblinks: %s" % e)
-
-
- def handleCNL(self):
- try:
- vjk = re.findall('<input type="hidden" name="jk" value="function f\(\){ return \'(.*)\';}">', self.siteWithLinks)
- vcrypted = re.findall('<input type="hidden" name="crypted" value="(.*)">', self.siteWithLinks)
-
- for i in xrange(len(vcrypted)):
- self.links.extend(self._getLinks(vcrypted[i], vjk[i]))
-
- except Exception, e:
- self.logDebug("Error decrypting CNL: %s" % e)
-
-
- def _getLinks(self, crypted, jk):
- # Get key
- key = binascii.unhexlify(str(jk))
-
- # Decrypt
- Key = key
- IV = key
- obj = AES.new(Key, AES.MODE_CBC, IV)
- text = obj.decrypt(crypted.decode('base64'))
-
- # Extract links
- text = text.replace("\x00", "").replace("\r", "")
- links = filter(bool, text.split('\n'))
-
- return links
diff --git a/module/plugins/crypter/FilefactoryCom.py b/module/plugins/crypter/FilefactoryCom.py
deleted file mode 100644
index c6bdb81eb..000000000
--- a/module/plugins/crypter/FilefactoryCom.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter
-
-
-class FilefactoryCom(SimpleCrypter):
- __name__ = "FilefactoryCom"
- __type__ = "crypter"
- __version__ = "0.32"
-
- __pattern__ = r'https?://(?:www\.)?filefactory\.com/(?:f|folder)/\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Filefactory.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- COOKIES = [("filefactory.com", "locale", "en_US.utf8")]
-
- LINK_PATTERN = r'<td>\s*<a href="(.+?)"'
- NAME_PATTERN = r'<h1>Files in <span>(?P<N>.+?)<'
- PAGES_PATTERN = r'data-paginator-totalPages="(\d+)'
-
-
- def loadPage(self, page_n):
- return self.load(self.pyfile.url, get={'page': page_n, 'show': 100})
-
-
-getInfo = create_getInfo(FilefactoryComFolder)
diff --git a/module/plugins/crypter/FilerNet.py b/module/plugins/crypter/FilerNet.py
deleted file mode 100644
index 054c8d3a7..000000000
--- a/module/plugins/crypter/FilerNet.py
+++ /dev/null
@@ -1,27 +0,0 @@
-import re
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter
-
-
-class FilerNet(SimpleCrypter):
- __name__ = "FilerNet"
- __type__ = "crypter"
- __version__ = "0.42"
-
- __pattern__ = r'https?://filer\.net/folder/\w{16}'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Filer.net decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("nath_schwarz", "nathan.notwhite@gmail.com"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
- LINK_PATTERN = r'href="(/get/\w{16})">(?!<)'
-
- NAME_PATTERN = r'<h3>(?P<N>.+?) - <small'
- OFFLINE_PATTERN = r'Nicht gefunden'
-
-
-getInfo = create_getInfo(FilerNetFolder)
diff --git a/module/plugins/crypter/FilesonicCom.py b/module/plugins/crypter/FilesonicCom.py
deleted file mode 100644
index b1722c1bb..000000000
--- a/module/plugins/crypter/FilesonicCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class FilesonicCom(DeadCrypter):
- __name__ = "FilesonicCom"
- __type__ = "crypter"
- __version__ = "0.12"
-
- __pattern__ = r'http://(?:www\.)?filesonic\.com/folder/\w+'
-
- __description__ = """Filesonic.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(FilesonicCom)
diff --git a/module/plugins/crypter/FilestubeCom.py b/module/plugins/crypter/FilestubeCom.py
deleted file mode 100644
index befe6f9a7..000000000
--- a/module/plugins/crypter/FilestubeCom.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter
-
-
-class FilestubeCom(SimpleCrypter):
- __name__ = "FilestubeCom"
- __type__ = "crypter"
- __version__ = "0.05"
-
- __pattern__ = r'http://(?:www\.)?filestube\.(?:com|to)/\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Filestube.com decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- LINK_PATTERN = r'<a class=\"file-link-main(?: noref)?\" [^>]* href=\"(http://[^\"]+)'
- NAME_PATTERN = r'<h1\s*> (?P<N>.+) download\s*</h1>'
-
-
-getInfo = create_getInfo(FilestubeCom)
diff --git a/module/plugins/crypter/FiletramCom.py b/module/plugins/crypter/FiletramCom.py
deleted file mode 100644
index 6c3c071ec..000000000
--- a/module/plugins/crypter/FiletramCom.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter
-
-
-class FiletramCom(SimpleCrypter):
- __name__ = "FiletramCom"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?filetram\.com/[^/]+/.+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Filetram.com decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("igel", "igelkun@myopera.com"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
- LINK_PATTERN = r'\s+(http://.+)'
- NAME_PATTERN = r'<title>(?P<N>.+?) - Free Download'
-
-
-getInfo = create_getInfo(FiletramCom)
diff --git a/module/plugins/crypter/FiredriveCom.py b/module/plugins/crypter/FiredriveCom.py
deleted file mode 100644
index bf315ad16..000000000
--- a/module/plugins/crypter/FiredriveCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class FiredriveCom(DeadCrypter):
- __name__ = "FiredriveCom"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'https?://(?:www\.)?(firedrive|putlocker)\.com/share/.+'
- __config__ = []
-
- __description__ = """Firedrive.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
-getInfo = create_getInfo(FiredriveCom)
diff --git a/module/plugins/crypter/FreakhareCom.py b/module/plugins/crypter/FreakhareCom.py
deleted file mode 100644
index c5fd2ee29..000000000
--- a/module/plugins/crypter/FreakhareCom.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
-
-
-class FreakhareCom(SimpleCrypter):
- __name__ = "FreakhareCom"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?freakshare\.com/folder/.+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Freakhare.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- LINK_PATTERN = r'<a href="(http://freakshare\.com/files/[^"]+)" target="_blank">'
- NAME_PATTERN = r'Folder:</b> (?P<N>.+)'
- PAGES_PATTERN = r'Pages: +(\d+)'
-
-
- def loadPage(self, page_n):
- if not hasattr(self, 'f_id') and not hasattr(self, 'f_md5'):
- m = re.search(r'http://freakshare.com/\?x=folder&f_id=(\d+)&f_md5=(\w+)', self.html)
- if m:
- self.f_id = m.group(1)
- self.f_md5 = m.group(2)
- return self.load('http://freakshare.com/', get={'x': 'folder',
- 'f_id': self.f_id,
- 'f_md5': self.f_md5,
- 'entrys': '20',
- 'page': page_n - 1,
- 'order': ''}, decode=True)
-
-
-getInfo = create_getInfo(FreakhareComFolder)
diff --git a/module/plugins/crypter/FreetexthostCom.py b/module/plugins/crypter/FreetexthostCom.py
deleted file mode 100644
index 4634455b6..000000000
--- a/module/plugins/crypter/FreetexthostCom.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
-
-
-class FreetexthostCom(SimpleCrypter):
- __name__ = "FreetexthostCom"
- __type__ = "crypter"
- __version__ = "0.01"
-
- __pattern__ = r'http://(?:www\.)?freetexthost\.com/\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Freetexthost.com decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- def getLinks(self):
- m = re.search(r'<div id="contentsinner">\s*(.+)<div class="viewcount">', self.html, re.S)
- if m is None:
- self.error(_("Unable to extract links"))
- links = m.group(1)
- return links.strip().split("<br />\r\n")
-
-
-getInfo = create_getInfo(FreetexthostCom)
diff --git a/module/plugins/crypter/FshareVn.py b/module/plugins/crypter/FshareVn.py
deleted file mode 100644
index e85085cf1..000000000
--- a/module/plugins/crypter/FshareVn.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
-
-
-class FshareVn(SimpleCrypter):
- __name__ = "FshareVn"
- __type__ = "crypter"
- __version__ = "0.01"
-
- __pattern__ = r'http://(?:www\.)?fshare\.vn/folder/.+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Fshare.vn folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- LINK_PATTERN = r'<li class="w_80pc"><a href="([^"]+)" target="_blank">'
-
-
-getInfo = create_getInfo(FshareVnFolder)
diff --git a/module/plugins/crypter/Go4UpCom.py b/module/plugins/crypter/Go4UpCom.py
deleted file mode 100644
index ffd945737..000000000
--- a/module/plugins/crypter/Go4UpCom.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urlparse import urljoin
-
-from pyload.plugin.internal.SimpleCrypter import SimpleCrypter, create_getInfo
-
-
-class Go4UpCom(SimpleCrypter):
- __name__ = "Go4UpCom"
- __type__ = "crypter"
- __version__ = "0.11"
-
- __pattern__ = r'http://go4up\.com/(dl/\w{12}|rd/\w{12}/\d+)'
-
- __description__ = """Go4Up.com decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("rlindner81", "rlindner81@gmail.com"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- LINK_PATTERN = r'(http://go4up\.com/rd/.+?)<'
-
- NAME_PATTERN = r'<title>Download (.+?)<'
-
- OFFLINE_PATTERN = r'>\s*(404 Page Not Found|File not Found|Mirror does not exist)'
-
-
- def getLinks(self
- links = []
-
- m = re.search(r'(/download/gethosts/.+?)"')
- if m:
- self.html = self.load(urljoin("http://go4up.com/", m.group(1)))
- pages = [self.load(url) for url in re.findall(self.LINK_PATTERN, self.html)]
- else:
- pages = [self.html]
-
- for html in pages:
- try:
- links.append(re.search(r'<b><a href="(.+?)"', html).group(1))
- except Exception:
- continue
-
- return links
-
-
-getInfo = create_getInfo(Go4UpCom)
diff --git a/module/plugins/crypter/HotfileCom.py b/module/plugins/crypter/HotfileCom.py
deleted file mode 100644
index 72eec8f93..000000000
--- a/module/plugins/crypter/HotfileCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class HotfileCom(DeadCrypter):
- __name__ = "HotfileCom"
- __type__ = "crypter"
- __version__ = "0.30"
-
- __pattern__ = r'https?://(?:www\.)?hotfile\.com/list/\w+/\w+'
- __config__ = []
-
- __description__ = """Hotfile.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org")]
-
-
-getInfo = create_getInfo(HotfileCom)
diff --git a/module/plugins/crypter/ILoadTo.py b/module/plugins/crypter/ILoadTo.py
deleted file mode 100644
index d3e50630c..000000000
--- a/module/plugins/crypter/ILoadTo.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class ILoadTo(DeadCrypter):
- __name__ = "ILoadTo"
- __type__ = "crypter"
- __version__ = "0.11"
-
- __pattern__ = r'http://(?:www\.)?iload\.to/go/\d+-[\w.-]+/'
- __config__ = []
-
- __description__ = """Iload.to decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("hzpz", "")]
-
-
-getInfo = create_getInfo(ILoadTo)
diff --git a/module/plugins/crypter/ImgurComAlbum.py b/module/plugins/crypter/ImgurComAlbum.py
deleted file mode 100644
index 6c074f5f1..000000000
--- a/module/plugins/crypter/ImgurComAlbum.py
+++ /dev/null
@@ -1,30 +0,0 @@
-import re
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
-from module.utils import uniqify
-
-
-class ImgurComAlbum(SimpleCrypter):
- __name__ = "ImgurComAlbum"
- __type__ = "crypter"
- __version__ = "0.51"
-
- __pattern__ = r'https?://(?:www\.|m\.)?imgur\.com/(a|gallery|)/?\w{5,7}'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Imgur.com decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("nath_schwarz", "nathan.notwhite@gmail.com")]
-
-
- NAME_PATTERN = r'(?P<N>.+?) - Imgur'
- LINK_PATTERN = r'i\.imgur\.com/\w{7}s?\.(?:jpeg|jpg|png|gif|apng)'
-
-
- def getLinks(self):
- f = lambda url: "http://" + re.sub(r'(\w{7})s\.', r'\1.', url)
- return uniqify(map(f, re.findall(self.LINK_PATTERN, self.html)))
-
-
-getInfo = create_getInfo(ImgurComAlbum)
diff --git a/module/plugins/crypter/LinkSaveIn.py b/module/plugins/crypter/LinkSaveIn.py
deleted file mode 100644
index e96d0438e..000000000
--- a/module/plugins/crypter/LinkSaveIn.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleDereferer import SimpleDereferer
-
-
-class LinkSaveIn(SimpleDereferer):
- __name__ = "LinkSaveIn"
- __type__ = "crypter"
- __version__ = "2.03"
-
- __pattern__ = r'https?://(?:www\.)?linksave\.in/\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """LinkSave.in decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- COOKIES = [("linksave.in", "Linksave_Language", "english")]
-
- OFFLINE_PATTERN = r'>(Error )?404 -'
diff --git a/module/plugins/crypter/LofCc.py b/module/plugins/crypter/LofCc.py
deleted file mode 100644
index e18349877..000000000
--- a/module/plugins/crypter/LofCc.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class LofCc(DeadCrypter):
- __name__ = "LofCc"
- __type__ = "crypter"
- __version__ = "0.21"
-
- __pattern__ = r'http://(?:www\.)?lof\.cc/(.+)'
- __config__ = []
-
- __description__ = """Lof.cc decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("mkaay", "mkaay@mkaay.de")]
-
-
-getInfo = create_getInfo(LofCc)
diff --git a/module/plugins/crypter/MBLinkInfo.py b/module/plugins/crypter/MBLinkInfo.py
deleted file mode 100644
index 7f1561756..000000000
--- a/module/plugins/crypter/MBLinkInfo.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class MBLinkInfo(DeadCrypter):
- __name__ = "MBLinkInfo"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?mblink\.info/?\?id=(\d+)'
- __config__ = []
-
- __description__ = """MBLink.info decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Gummibaer", "Gummibaer@wiki-bierkiste.de"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
-getInfo = create_getInfo(MBLinkInfo)
diff --git a/module/plugins/crypter/MegaCoNzFolder.py b/module/plugins/crypter/MegaCoNzFolder.py
deleted file mode 100644
index 4bef61f67..000000000
--- a/module/plugins/crypter/MegaCoNzFolder.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.Crypter import Crypter
-
-
-class MegaCoNzFolder(Crypter):
- __name__ = "MegaCoNzFolder"
- __type__ = "crypter"
- __version__ = "0.04"
-
- __pattern__ = r'(?:https?://(?:www\.)?mega\.co\.nz/|mega:|chrome:.+?)#F!(?P<ID>[\w^_]+)!(?P<KEY>[\w,\\-]+)'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Mega.co.nz folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- def setup(self):
- self.req.setOption("timeout", 300)
-
-
- def decrypt(self, pyfile):
- url = "https://mega.co.nz/#F!%s!%s" % re.match(self.__pattern__, pyfile.url).groups()
- self.html = self.load("http://rapidgen.org/linkfinder", post={'linklisturl': url})
- self.urls = re.findall(r'(https://mega.co.nz/#N!.+?)<', self.html)
-
- if not self.urls: #@TODO: Remove in 0.4.10
- self.fail(_("No link grabbed"))
diff --git a/module/plugins/crypter/MegaRapidCz.py b/module/plugins/crypter/MegaRapidCz.py
deleted file mode 100644
index 86235444b..000000000
--- a/module/plugins/crypter/MegaRapidCz.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
-
-
-class MegaRapidCz(SimpleCrypter):
- __name__ = "MegaRapidCz"
- __type__ = "crypter"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?(share|mega)rapid\.cz/slozka/\d+/\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Share-Rapid.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- LINK_PATTERN = r'<td class="soubor"[^>]*><a href="([^"]+)">'
-
-
-getInfo = create_getInfo(MegaRapidCzFolder)
diff --git a/module/plugins/crypter/MegauploadCom.py b/module/plugins/crypter/MegauploadCom.py
deleted file mode 100644
index 6981cebc8..000000000
--- a/module/plugins/crypter/MegauploadCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class MegauploadCom(DeadCrypter):
- __name__ = "MegauploadCom"
- __type__ = "crypter"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?megaupload\.com/(\?f|xml/folderfiles\.php\?.*&?folderid)=\w+'
-
- __description__ = """Megaupload.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(MegauploadCom)
diff --git a/module/plugins/crypter/Movie2KTo.py b/module/plugins/crypter/Movie2KTo.py
deleted file mode 100644
index 92bc128c7..000000000
--- a/module/plugins/crypter/Movie2KTo.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class Movie2KTo(DeadCrypter):
- __name__ = "Movie2KTo"
- __type__ = "crypter"
- __version__ = "0.51"
-
- __pattern__ = r'http://(?:www\.)?movie2k\.to/(.+)\.html'
- __config__ = []
-
- __description__ = """Movie2k.to decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("4Christopher", "4Christopher@gmx.de")]
-
-
-getInfo = create_getInfo(Movie2KTo)
diff --git a/module/plugins/crypter/MultiUpOrg.py b/module/plugins/crypter/MultiUpOrg.py
deleted file mode 100644
index 7955fca6c..000000000
--- a/module/plugins/crypter/MultiUpOrg.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-from urlparse import urljoin
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
-
-
-class MultiUpOrg(SimpleCrypter):
- __name__ = "MultiUpOrg"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?multiup\.org/(en|fr)/(?P<TYPE>project|download|miror)/\w+(/\w+)?'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """MultiUp.org decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- NAME_PATTERN = r'<title>.*(?:Project|Projet|ownload|élécharger) (?P<N>.+?) (\(|- )'
-
-
- def getLinks(self):
- m_type = re.match(self.__pattern__, self.pyfile.url).group('TYPE')
-
- if m_type == "project":
- pattern = r'\n(http://www\.multiup\.org/(?:en|fr)/download/.*)'
- else:
- pattern = r'style="width:97%;text-align:left".*\n.*href="(.*)"'
- if m_type == "download":
- dl_pattern = r'href="(.*)">.*\n.*<h5>DOWNLOAD</h5>'
- miror_page = urljoin("http://www.multiup.org", re.search(dl_pattern, self.html).group(1))
- self.html = self.load(miror_page)
-
- return re.findall(pattern, self.html)
-
-
-getInfo = create_getInfo(MultiUpOrg)
diff --git a/module/plugins/crypter/MultiuploadCom.py b/module/plugins/crypter/MultiuploadCom.py
deleted file mode 100644
index 98708bd95..000000000
--- a/module/plugins/crypter/MultiuploadCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class MultiuploadCom(DeadCrypter):
- __name__ = "MultiuploadCom"
- __type__ = "crypter"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?multiupload\.(com|nl)/\w+'
-
- __description__ = """MultiUpload.com decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(MultiuploadCom)
diff --git a/module/plugins/crypter/NetfolderIn.py b/module/plugins/crypter/NetfolderIn.py
deleted file mode 100644
index 62dc5c914..000000000
--- a/module/plugins/crypter/NetfolderIn.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
-
-
-class NetfolderIn(SimpleCrypter):
- __name__ = "NetfolderIn"
- __type__ = "crypter"
- __version__ = "0.72"
-
- __pattern__ = r'http://(?:www\.)?netfolder\.in/(folder\.php\?folder_id=)?(?P<ID>\w+)(?(1)|/\w+)'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """NetFolder.in decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("fragonib", "fragonib[AT]yahoo[DOT]es")]
-
-
- NAME_PATTERN = r'<div class="Text">Inhalt des Ordners <span.*>(?P<N>.+)</span></div>'
-
-
- def prepare(self):
- super(NetfolderIn, self).prepare()
-
- # Check for password protection
- if self.isPasswordProtected():
- self.html = self.submitPassword()
- if not self.html:
- self.fail(_("Incorrect password, please set right password on Add package form and retry"))
-
-
- def isPasswordProtected(self):
- if '<input type="password" name="password"' in self.html:
- self.logDebug("Links are password protected")
- return True
- return False
-
-
- def submitPassword(self):
- # Gather data
- try:
- m = re.match(self.__pattern__, self.pyfile.url)
- id = m.group('ID')
- except AttributeError:
- self.logDebug("Unable to get package id from url [%s]" % self.pyfile.url)
- return
- url = "http://netfolder.in/folder.php?folder_id=" + id
- password = self.getPassword()
-
- # Submit package password
- post = {'password': password, 'save': 'Absenden'}
- self.logDebug("Submitting password [%s] for protected links with id [%s]" % (password, id))
- html = self.load(url, {}, post)
-
- # Check for invalid password
- if '<div class="InPage_Error">' in html:
- self.logDebug("Incorrect password, please set right password on Edit package form and retry")
- return None
-
- return html
-
-
- def getLinks(self):
- links = re.search(r'name="list" value="(.*?)"', self.html).group(1).split(",")
- self.logDebug("Package has %d links" % len(links))
- return links
-
-
-getInfo = create_getInfo(NetfolderIn)
diff --git a/module/plugins/crypter/NosvideoCom.py b/module/plugins/crypter/NosvideoCom.py
deleted file mode 100644
index 1e280abd2..000000000
--- a/module/plugins/crypter/NosvideoCom.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
-
-
-class NosvideoCom(SimpleCrypter):
- __name__ = "NosvideoCom"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?nosvideo\.com/\?v=\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Nosvideo.com decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("igel", "igelkun@myopera.com")]
-
-
- LINK_PATTERN = r'href="(http://(?:w{3}\.)?nosupload\.com/\?d=\w+)"'
- NAME_PATTERN = r'<[tT]itle>Watch (?P<N>.+?)<'
-
-
-getInfo = create_getInfo(NosvideoCom)
diff --git a/module/plugins/crypter/OronCom.py b/module/plugins/crypter/OronCom.py
deleted file mode 100644
index 42483c497..000000000
--- a/module/plugins/crypter/OronCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class OronCom(DeadCrypter):
- __name__ = "OronCom"
- __type__ = "crypter"
- __version__ = "0.11"
-
- __pattern__ = r'http://(?:www\.)?oron\.com/folder/\w+'
- __config__ = []
-
- __description__ = """Oron.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("DHMH", "webmaster@pcProfil.de")]
-
-
-getInfo = create_getInfo(OronCom)
diff --git a/module/plugins/crypter/PastebinCom.py b/module/plugins/crypter/PastebinCom.py
deleted file mode 100644
index b3d5a4bea..000000000
--- a/module/plugins/crypter/PastebinCom.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
-
-
-class PastebinCom(SimpleCrypter):
- __name__ = "PastebinCom"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?pastebin\.com/\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Pastebin.com decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- LINK_PATTERN = r'<div class="de\d+">(https?://[^ <]+)(?:[^<]*)</div>'
- NAME_PATTERN = r'<div class="paste_box_line1" title="(?P<N>[^"]+)">'
-
-
-getInfo = create_getInfo(PastebinCom)
diff --git a/module/plugins/crypter/RSLayerCom.py b/module/plugins/crypter/RSLayerCom.py
deleted file mode 100644
index ebd3c509c..000000000
--- a/module/plugins/crypter/RSLayerCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class RSLayerCom(DeadCrypter):
- __name__ = "RSLayerCom"
- __type__ = "crypter"
- __version__ = "0.21"
-
- __pattern__ = r'http://(?:www\.)?rs-layer\.com/directory-'
- __config__ = []
-
- __description__ = """RS-Layer.com decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("hzpz", "")]
-
-
-getInfo = create_getInfo(RSLayerCom)
diff --git a/module/plugins/crypter/RelinkUs.py b/module/plugins/crypter/RelinkUs.py
deleted file mode 100644
index b361f87d8..000000000
--- a/module/plugins/crypter/RelinkUs.py
+++ /dev/null
@@ -1,293 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import binascii
-import re
-import os
-
-from Crypto.Cipher import AES
-from pyload.plugin.Crypter import Crypter
-from module.utils import safe_join
-
-
-class RelinkUs(Crypter):
- __name__ = "RelinkUs"
- __type__ = "crypter"
- __version__ = "3.12"
-
- __pattern__ = r'http://(?:www\.)?relink\.us/(f/|((view|go)\.php\?id=))(?P<ID>.+)'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Relink.us decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("fragonib", "fragonib[AT]yahoo[DOT]es"),
- ("AndroKev", "neureither.kevin@gmail.com")]
-
-
- PREFERRED_LINK_SOURCES = ["cnl2", "dlc", "web"]
-
- OFFLINE_TOKEN = r'<title>Tattooside'
-
- PASSWORD_TOKEN = r'container_password.php'
- PASSWORD_ERROR_ROKEN = r'You have entered an incorrect password'
- PASSWORD_SUBMIT_URL = r'http://www.relink.us/container_password.php'
-
- CAPTCHA_TOKEN = r'container_captcha.php'
- CAPTCHA_ERROR_ROKEN = r'You have solved the captcha wrong'
- CAPTCHA_IMG_URL = r'http://www.relink.us/core/captcha/circlecaptcha.php'
- CAPTCHA_SUBMIT_URL = r'http://www.relink.us/container_captcha.php'
-
- FILE_TITLE_REGEX = r'<th>Title</th><td>(.*)</td></tr>'
- FILE_NOTITLE = r'No title'
-
- CNL2_FORM_REGEX = r'<form id="cnl_form-(.*?)</form>'
- CNL2_FORMINPUT_REGEX = r'<input.*?name="%s".*?value="(.*?)"'
- CNL2_JK_KEY = "jk"
- CNL2_CRYPTED_KEY = "crypted"
-
- DLC_LINK_REGEX = r'<a href=".*?" class="dlc_button" target="_blank">'
- DLC_DOWNLOAD_URL = r'http://www.relink.us/download.php'
-
- WEB_FORWARD_REGEX = r'getFile\(\'(.+)\'\)'
- WEB_FORWARD_URL = r'http://www.relink.us/frame.php'
- WEB_LINK_REGEX = r'<iframe name="Container" height="100%" frameborder="no" width="100%" src="(.+)"></iframe>'
-
-
- def setup(self):
- self.fileid = None
- self.package = None
- self.captcha = False
-
-
- def decrypt(self, pyfile):
- # Init
- self.initPackage(pyfile)
-
- # Request package
- self.requestPackage()
-
- # Check for online
- if not self.isOnline():
- self.offline()
-
- # Check for protection
- if self.isPasswordProtected():
- self.unlockPasswordProtection()
- self.handleErrors()
-
- if self.isCaptchaProtected():
- self.captcha = True
- self.unlockCaptchaProtection()
- self.handleErrors()
-
- # Get package name and folder
- (package_name, folder_name) = self.getPackageInfo()
-
- # Extract package links
- package_links = []
- for sources in self.PREFERRED_LINK_SOURCES:
- package_links.extend(self.handleLinkSource(sources))
- if package_links: # use only first source which provides links
- break
- package_links = set(package_links)
-
- # Pack
- if package_links:
- self.packages = [(package_name, package_links, folder_name)]
-
-
- def initPackage(self, pyfile):
- self.fileid = re.match(self.__pattern__, pyfile.url).group('ID')
- self.package = pyfile.package()
-
-
- def requestPackage(self):
- self.html = self.load(self.pyfile.url, decode=True)
-
-
- def isOnline(self):
- if self.OFFLINE_TOKEN in self.html:
- self.logDebug("File not found")
- return False
- return True
-
-
- def isPasswordProtected(self):
- if self.PASSWORD_TOKEN in self.html:
- self.logDebug("Links are password protected")
- return True
-
-
- def isCaptchaProtected(self):
- if self.CAPTCHA_TOKEN in self.html:
- self.logDebug("Links are captcha protected")
- return True
- return False
-
-
- def unlockPasswordProtection(self):
- password = self.getPassword()
-
- self.logDebug("Submitting password [%s] for protected links" % password)
-
- if password:
- passwd_url = self.PASSWORD_SUBMIT_URL + "?id=%s" % self.fileid
- passwd_data = {'id': self.fileid, 'password': password, 'pw': 'submit'}
- self.html = self.load(passwd_url, post=passwd_data, decode=True)
-
-
- def unlockCaptchaProtection(self):
- self.logDebug("Request user positional captcha resolving")
- captcha_img_url = self.CAPTCHA_IMG_URL + "?id=%s" % self.fileid
- coords = self.decryptCaptcha(captcha_img_url, forceUser=True, imgtype="png", result_type='positional')
- self.logDebug("Captcha resolved, coords [%s]" % str(coords))
- captcha_post_url = self.CAPTCHA_SUBMIT_URL + "?id=%s" % self.fileid
- captcha_post_data = {'button.x': coords[0], 'button.y': coords[1], 'captcha': 'submit'}
- self.html = self.load(captcha_post_url, post=captcha_post_data, decode=True)
-
-
- def getPackageInfo(self):
- name = folder = None
-
- # Try to get info from web
- m = re.search(self.FILE_TITLE_REGEX, self.html)
- if m is not None:
- title = m.group(1).strip()
- if not self.FILE_NOTITLE in title:
- name = folder = title
- self.logDebug("Found name [%s] and folder [%s] in package info" % (name, folder))
-
- # Fallback to defaults
- if not name or not folder:
- name = self.package.name
- folder = self.package.folder
- self.logDebug("Package info not found, defaulting to pyfile name [%s] and folder [%s]" % (name, folder))
-
- # Return package info
- return name, folder
-
-
- def handleErrors(self):
- if self.PASSWORD_ERROR_ROKEN in self.html:
- msg = "Incorrect password, please set right password on 'Edit package' form and retry"
- self.logDebug(msg)
- self.fail(_(msg))
-
- if self.captcha:
- if self.CAPTCHA_ERROR_ROKEN in self.html:
- self.invalidCaptcha()
- self.retry()
- else:
- self.correctCaptcha()
-
-
- def handleLinkSource(self, source):
- if source == 'cnl2':
- return self.handleCNL2Links()
- elif source == 'dlc':
- return self.handleDLCLinks()
- elif source == 'web':
- return self.handleWEBLinks()
- else:
- self.error(_('Unknown source type "%s"') % source)
-
-
- def handleCNL2Links(self):
- self.logDebug("Search for CNL2 links")
- package_links = []
- m = re.search(self.CNL2_FORM_REGEX, self.html, re.S)
- if m is not None:
- cnl2_form = m.group(1)
- try:
- (vcrypted, vjk) = self._getCipherParams(cnl2_form)
- for (crypted, jk) in zip(vcrypted, vjk):
- package_links.extend(self._getLinks(crypted, jk))
- except Exception:
- self.logDebug("Unable to decrypt CNL2 links")
- return package_links
-
-
- def handleDLCLinks(self):
- self.logDebug("Search for DLC links")
- package_links = []
- m = re.search(self.DLC_LINK_REGEX, self.html)
- if m is not None:
- container_url = self.DLC_DOWNLOAD_URL + "?id=%s&dlc=1" % self.fileid
- self.logDebug("Downloading DLC container link [%s]" % container_url)
- try:
- dlc = self.load(container_url)
- dlc_filename = self.fileid + ".dlc"
- dlc_filepath = save_join(self.config['general']['download_folder'], dlc_filename)
- with open(dlc_filepath, "wb") as f:
- f.write(dlc)
- package_links.append(dlc_filepath)
-
- except Exception:
- self.fail(_("Unable to download DLC container"))
-
- return package_links
-
-
- def handleWEBLinks(self):
- self.logDebug("Search for WEB links")
-
- package_links = []
- params = re.findall(self.WEB_FORWARD_REGEX, self.html)
-
- self.logDebug("Decrypting %d Web links" % len(params))
-
- for index, param in enumerate(params):
- try:
- url = self.WEB_FORWARD_URL + "?%s" % param
-
- self.logDebug("Decrypting Web link %d, %s" % (index + 1, url))
-
- res = self.load(url, decode=True)
- link = re.search(self.WEB_LINK_REGEX, res).group(1)
-
- package_links.append(link)
-
- except Exception, detail:
- self.logDebug("Error decrypting Web link %s, %s" % (index, detail))
-
- self.setWait(4)
- self.wait()
-
- return package_links
-
-
- def _getCipherParams(self, cnl2_form):
- # Get jk
- jk_re = self.CNL2_FORMINPUT_REGEX % self.CNL2_JK_KEY
- vjk = re.findall(jk_re, cnl2_form, re.I)
-
- # Get crypted
- crypted_re = self.CNL2_FORMINPUT_REGEX % RelinkUs.CNL2_CRYPTED_KEY
- vcrypted = re.findall(crypted_re, cnl2_form, re.I)
-
- # Log and return
- self.logDebug("Detected %d crypted blocks" % len(vcrypted))
- return vcrypted, vjk
-
-
- def _getLinks(self, crypted, jk):
- # Get key
- jreturn = self.js.eval("%s f()" % jk)
- self.logDebug("JsEngine returns value [%s]" % jreturn)
- key = binascii.unhexlify(jreturn)
-
- # Decrypt
- Key = key
- IV = key
- obj = AES.new(Key, AES.MODE_CBC, IV)
- text = obj.decrypt(crypted.decode('base64'))
-
- # Extract links
- text = text.replace("\x00", "").replace("\r", "")
- links = filter(bool, text.split('\n'))
-
- # Log and return
- self.logDebug("Package has %d links" % len(links))
- return links
diff --git a/module/plugins/crypter/SecuredIn.py b/module/plugins/crypter/SecuredIn.py
deleted file mode 100644
index 9aee9e52e..000000000
--- a/module/plugins/crypter/SecuredIn.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class SecuredIn(DeadCrypter):
- __name__ = "SecuredIn"
- __type__ = "crypter"
- __version__ = "0.21"
-
- __pattern__ = r'http://(?:www\.)?secured\.in/download-[\d]+-\w{8}\.html'
- __config__ = []
-
- __description__ = """Secured.in decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("mkaay", "mkaay@mkaay.de")]
-
-
-getInfo = create_getInfo(SecuredIn)
diff --git a/module/plugins/crypter/SharingmatrixCom.py b/module/plugins/crypter/SharingmatrixCom.py
deleted file mode 100644
index be23ada49..000000000
--- a/module/plugins/crypter/SharingmatrixCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class SharingmatrixCom(DeadCrypter):
- __name__ = "SharingmatrixCom"
- __type__ = "crypter"
- __version__ = "0.01"
-
- __pattern__ = r'http://(?:www\.)?sharingmatrix\.com/folder/\w+'
-
- __description__ = """Sharingmatrix.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(SharingmatrixCom)
diff --git a/module/plugins/crypter/SpeedLoadOrg.py b/module/plugins/crypter/SpeedLoadOrg.py
deleted file mode 100644
index 190ec66eb..000000000
--- a/module/plugins/crypter/SpeedLoadOrg.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class SpeedLoadOrg(DeadCrypter):
- __name__ = "SpeedLoadOrg"
- __type__ = "crypter"
- __version__ = "0.30"
-
- __pattern__ = r'http://(?:www\.)?speedload\.org/(\d+~f$|folder/\d+/)'
- __config__ = []
-
- __description__ = """Speedload decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
-getInfo = create_getInfo(SpeedLoadOrg)
diff --git a/module/plugins/crypter/StealthTo.py b/module/plugins/crypter/StealthTo.py
deleted file mode 100644
index 8513fb3f8..000000000
--- a/module/plugins/crypter/StealthTo.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class StealthTo(DeadCrypter):
- __name__ = "StealthTo"
- __type__ = "crypter"
- __version__ = "0.20"
-
- __pattern__ = r'http://(?:www\.)?stealth\.to/folder/.+'
- __config__ = []
-
- __description__ = """Stealth.to decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("spoob", "spoob@pyload.org")]
-
-
-getInfo = create_getInfo(StealthTo)
diff --git a/module/plugins/crypter/TnyCz.py b/module/plugins/crypter/TnyCz.py
deleted file mode 100644
index d36128550..000000000
--- a/module/plugins/crypter/TnyCz.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
-
-import re
-
-
-class TnyCz(SimpleCrypter):
- __name__ = "TnyCz"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?tny\.cz/\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Tny.cz decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- NAME_PATTERN = r'<title>(?P<N>.+) - .+</title>'
-
-
- def getLinks(self):
- m = re.search(r'<a id=\'save_paste\' href="(.+save\.php\?hash=.+)">', self.html)
- return re.findall(".+", self.load(m.group(1), decode=True)) if m else None
-
-
-getInfo = create_getInfo(TnyCz)
diff --git a/module/plugins/crypter/TrailerzoneInfo.py b/module/plugins/crypter/TrailerzoneInfo.py
deleted file mode 100644
index ca14e6df5..000000000
--- a/module/plugins/crypter/TrailerzoneInfo.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class TrailerzoneInfo(DeadCrypter):
- __name__ = "TrailerzoneInfo"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?trailerzone\.info/.+'
- __config__ = []
-
- __description__ = """TrailerZone.info decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("godofdream", "soilfiction@gmail.com")]
-
-
-getInfo = create_getInfo(TrailerzoneInfo)
diff --git a/module/plugins/crypter/TurbobitNet.py b/module/plugins/crypter/TurbobitNet.py
deleted file mode 100644
index 67f7c74d4..000000000
--- a/module/plugins/crypter/TurbobitNet.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
-from pyload.utils import json_loads
-
-
-class TurbobitNet(SimpleCrypter):
- __name__ = "TurbobitNet"
- __type__ = "crypter"
- __version__ = "0.05"
-
- __pattern__ = r'http://(?:www\.)?turbobit\.net/download/folder/(?P<ID>\w+)'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Turbobit.net folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- NAME_PATTERN = r'src=\'/js/lib/grid/icon/folder.png\'> <span>(?P<N>.+?)</span>'
-
-
- def _getLinks(self, id, page=1):
- gridFile = self.load("http://turbobit.net/downloadfolder/gridFile",
- get={"rootId": id, "rows": 200, "page": page}, decode=True)
- grid = json_loads(gridFile)
-
- if grid['rows']:
- for i in grid['rows']:
- yield i['id']
- for id in self._getLinks(id, page + 1):
- yield id
- else:
- return
-
-
- def getLinks(self):
- id = re.match(self.__pattern__, self.pyfile.url).group('ID')
- fixurl = lambda id: "http://turbobit.net/%s.html" % id
- return map(fixurl, self._getLinks(id))
-
-
-getInfo = create_getInfo(TurbobitNetFolder)
diff --git a/module/plugins/crypter/TusfilesNet.py b/module/plugins/crypter/TusfilesNet.py
deleted file mode 100644
index 94b6bbb5d..000000000
--- a/module/plugins/crypter/TusfilesNet.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import math
-import re
-from urlparse import urljoin
-
-from module.plugins.internal.XFSCrypter import XFSCrypter, create_getInfo
-
-
-class TusfilesNet(XFSCrypter):
- __name__ = "TusfilesNet"
- __type__ = "crypter"
- __version__ = "0.08"
-
- __pattern__ = r'https?://(?:www\.)?tusfiles\.net/go/(?P<ID>\w+)'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Tusfiles.net folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
- PAGES_PATTERN = r'>\((\d+) \w+\)<'
-
- URL_REPLACEMENTS = [(__pattern__ + ".*", r'https://www.tusfiles.net/go/\g<ID>/')]
-
-
- def loadPage(self, page_n):
- return self.load(urljoin(self.pyfile.url, str(page_n)), decode=True)
-
-
- def handlePages(self, pyfile):
- pages = re.search(self.PAGES_PATTERN, self.html)
- if pages:
- pages = int(math.ceil(int(pages.group('pages')) / 25.0))
- else:
- return
-
- for p in xrange(2, pages + 1):
- self.html = self.loadPage(p)
- self.links += self.getLinks()
-
-
-getInfo = create_getInfo(TusfilesNetFolder)
diff --git a/module/plugins/crypter/UploadableCh.py b/module/plugins/crypter/UploadableCh.py
deleted file mode 100644
index 8e4ff71c0..000000000
--- a/module/plugins/crypter/UploadableCh.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
-
-
-class UploadableCh(SimpleCrypter):
- __name__ = "UploadableCh"
- __type__ = "crypter"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?uploadable\.ch/list/\w+'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Uploadable.ch folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("guidobelix", "guidobelix@hotmail.it"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- LINK_PATTERN = r'"(.+?)" class="icon_zipfile">'
- NAME_PATTERN = r'<div class="folder"><span>&nbsp;</span>(?P<N>.+?)</div>'
- OFFLINE_PATTERN = r'We are sorry... The URL you entered cannot be found on the server.'
- TEMP_OFFLINE_PATTERN = r'<div class="icon_err">'
-
-
-getInfo = create_getInfo(UploadableChFolder)
diff --git a/module/plugins/crypter/UploadedTo.py b/module/plugins/crypter/UploadedTo.py
deleted file mode 100644
index f6bc861de..000000000
--- a/module/plugins/crypter/UploadedTo.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urlparse import urljoin
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
-
-
-class UploadedTo(SimpleCrypter):
- __name__ = "UploadedTo"
- __type__ = "crypter"
- __version__ = "0.42"
-
- __pattern__ = r'http://(?:www\.)?(uploaded|ul)\.(to|net)/(f|folder|list)/(?P<ID>\w+)'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """UploadedTo decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- PLAIN_PATTERN = r'<small class="date"><a href="([\w/]+)" onclick='
- NAME_PATTERN = r'<title>(?P<N>.+?)<'
-
-
- def getLinks(self):
- m = re.search(self.PLAIN_PATTERN, self.html)
- if m is None:
- self.error(_("PLAIN_PATTERN not found"))
-
- plain_link = urljoin("http://uploaded.net/", m.group(1))
- return self.load(plain_link).split('\n')[:-1]
-
-
-getInfo = create_getInfo(UploadedToFolder)
diff --git a/module/plugins/crypter/WiiReloadedOrg.py b/module/plugins/crypter/WiiReloadedOrg.py
deleted file mode 100644
index 7b4270e65..000000000
--- a/module/plugins/crypter/WiiReloadedOrg.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class WiiReloadedOrg(DeadCrypter):
- __name__ = "WiiReloadedOrg"
- __type__ = "crypter"
- __version__ = "0.11"
-
- __pattern__ = r'http://(?:www\.)?wii-reloaded\.org/protect/get\.php\?i=.+'
- __config__ = []
-
- __description__ = """Wii-Reloaded.org decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("hzpz", "")]
-
-
-getInfo = create_getInfo(WiiReloadedOrg)
diff --git a/module/plugins/crypter/WuploadCom.py b/module/plugins/crypter/WuploadCom.py
deleted file mode 100644
index 0a098a40c..000000000
--- a/module/plugins/crypter/WuploadCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadCrypter import DeadCrypter, create_getInfo
-
-
-class WuploadCom(DeadCrypter):
- __name__ = "WuploadCom"
- __type__ = "crypter"
- __version__ = "0.01"
-
- __pattern__ = r'http://(?:www\.)?wupload\.com/folder/\w+'
-
- __description__ = """Wupload.com folder decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(WuploadCom)
diff --git a/module/plugins/crypter/XFileSharingPro.py b/module/plugins/crypter/XFileSharingPro.py
deleted file mode 100644
index a965f0c48..000000000
--- a/module/plugins/crypter/XFileSharingPro.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.XFSCrypter import XFSCrypter, create_getInfo
-
-
-class XFileSharingPro(XFSCrypter):
- __name__ = "XFileSharingPro"
- __type__ = "crypter"
- __version__ = "0.04"
-
- __pattern__ = r'^unmatchable$'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """XFileSharingPro dummy folder decrypter plugin for hook"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- def _log(self, type, args):
- msg = " | ".join(str(a).strip() for a in args if a)
- logger = getattr(self.log, type)
- logger("%s: %s: %s" % (self.__name__, self.HOSTER_NAME, msg or _("%s MARK" % type.upper())))
-
-
- def init(self):
- super(XFileSharingPro, self).init()
-
- self.__pattern__ = self.core.pluginManager.crypterPlugins[self.__name__]['pattern']
-
- self.HOSTER_DOMAIN = re.match(self.__pattern__, self.pyfile.url).group("DOMAIN").lower()
- self.HOSTER_NAME = "".join(part.capitalize() for part in re.split(r'(\.|\d+)', self.HOSTER_DOMAIN) if part != '.')
-
- if self.HOSTER_NAME[0].isdigit():
- self.HOSTER_NAME = 'X' + self.HOSTER_NAME
-
- account = self.core.accountManager.getAccountPlugin(self.HOSTER_NAME)
-
- if account and account.canUse():
- self.account = account
-
- elif self.account:
- self.account.HOSTER_DOMAIN = self.HOSTER_DOMAIN
-
- else:
- return
-
- self.user, data = self.account.selectAccount()
- self.req = self.account.getAccountRequest(self.user)
- self.premium = self.account.isPremium(self.user)
-
-
-getInfo = create_getInfo(XFileSharingProFolder)
diff --git a/module/plugins/hooks/AlldebridCom.py b/module/plugins/hooks/AlldebridCom.py
deleted file mode 100644
index fd89571eb..000000000
--- a/module/plugins/hooks/AlldebridCom.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class AlldebridCom(MultiHook):
- __name__ = "AlldebridCom"
- __type__ = "hook"
- __version__ = "0.16"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 ),
- ("ssl" , "bool" , "Use HTTPS" , True )]
-
- __description__ = """Alldebrid.com hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Andy Voigt", "spamsales@online.de")]
-
-
- def getHosters(self):
- https = "https" if self.getConfig("ssl") else "http"
- html = self.getURL(https + "://www.alldebrid.com/api.php", get={'action': "get_host"}).replace("\"", "").strip()
-
- return [x.strip() for x in html.split(",") if x.strip()]
diff --git a/module/plugins/hooks/AndroidPhoneNotify.py b/module/plugins/hooks/AndroidPhoneNotify.py
deleted file mode 100644
index a3b24a255..000000000
--- a/module/plugins/hooks/AndroidPhoneNotify.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from time import time
-
-from module.network.RequestFactory import getURL
-from module.plugins.Hook import Hook
-
-
-class AndroidPhoneNotify(Hook):
- __name__ = "AndroidPhoneNotify"
- __type__ = "hook"
- __version__ = "0.05"
-
- __config__ = [("apikey" , "str" , "API key" , "" ),
- ("notifycaptcha" , "bool", "Notify captcha request" , True ),
- ("notifypackage" , "bool", "Notify package finished" , True ),
- ("notifyprocessed", "bool", "Notify processed packages status" , True ),
- ("timeout" , "int" , "Timeout between captchas in seconds" , 5 ),
- ("force" , "bool", "Send notifications if client is connected", False)]
-
- __description__ = """Send push notifications to your Android Phone using notifymyandroid.com"""
- __license__ = "GPLv3"
- __authors__ = [("Steven Kosyra", "steven.kosyra@gmail.com"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- event_list = ["allDownloadsProcessed"]
-
-
- #@TODO: Remove in 0.4.10
- def initPeriodical(self):
- pass
-
-
- def setup(self):
- self.info = {} #@TODO: Remove in 0.4.10
- self.last_notify = 0
-
-
- def newCaptchaTask(self, task):
- if not self.getConfig("notifycaptcha"):
- return False
-
- if time() - self.last_notify < self.getConf("timeout"):
- return False
-
- self.notify(_("Captcha"), _("New request waiting user input"))
-
-
- def packageFinished(self, pypack):
- if self.getConfig("notifypackage"):
- self.notify(_("Package finished"), pypack.name)
-
-
- def allDownloadsProcessed(self):
- if not self.getConfig("notifyprocessed"):
- return False
-
- if any(True for pdata in self.core.api.getQueue() if pdata.linksdone < pdata.linkstotal):
- self.notify(_("Package failed"), _("One or more packages was not completed successfully"))
- else:
- self.notify(_("All packages finished"))
-
-
- def notify(self, event, msg=""):
- apikey = self.getConfig("apikey")
-
- if not apikey:
- return False
-
- if self.core.isClientConnected() and not self.getConfig("force"):
- return False
-
- getURL("http://www.notifymyandroid.com/publicapi/notify",
- get={'apikey' : apikey,
- 'application': "pyLoad",
- 'event' : event,
- 'description': msg})
-
- self.last_notify = time()
diff --git a/module/plugins/hooks/BypassCaptcha.py b/module/plugins/hooks/BypassCaptcha.py
deleted file mode 100644
index bd19fe953..000000000
--- a/module/plugins/hooks/BypassCaptcha.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pycurl import FORM_FILE, LOW_SPEED_TIME
-
-from module.network.HTTPRequest import BadHeader
-from module.network.RequestFactory import getURL, getRequest
-from module.plugins.Addon import Addon, threaded
-
-
-class BypassCaptchaException(Exception):
-
- def __init__(self, err):
- self.err = err
-
-
- def getCode(self):
- return self.err
-
-
- def __str__(self):
- return "<BypassCaptchaException %s>" % self.err
-
-
- def __repr__(self):
- return "<BypassCaptchaException %s>" % self.err
-
-
-class BypassCaptcha(Addon):
- __name__ = "BypassCaptcha"
- __type__ = "hook"
- __version__ = "0.06"
-
- __config__ = [("force", "bool", "Force BC even if client is connected", False),
- ("passkey", "password", "Passkey", "")]
-
- __description__ = """Send captchas to BypassCaptcha.com"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("Godofdream", "soilfcition@gmail.com"),
- ("zoidberg", "zoidberg@mujmail.cz")]
-
-
- PYLOAD_KEY = "4f771155b640970d5607f919a615bdefc67e7d32"
-
- SUBMIT_URL = "http://bypasscaptcha.com/upload.php"
- RESPOND_URL = "http://bypasscaptcha.com/check_value.php"
- GETCREDITS_URL = "http://bypasscaptcha.com/ex_left.php"
-
-
- def getCredits(self):
- res = getURL(self.GETCREDITS_URL, post={"key": self.getConfig("passkey")})
-
- data = dict(x.split(' ', 1) for x in res.splitlines())
- return int(data['Left'])
-
-
- def submit(self, captcha, captchaType="file", match=None):
- req = getRequest()
-
- #raise timeout threshold
- req.c.setopt(LOW_SPEED_TIME, 80)
-
- try:
- res = req.load(self.SUBMIT_URL,
- post={'vendor_key': self.PYLOAD_KEY,
- 'key': self.getConfig("passkey"),
- 'gen_task_id': "1",
- 'file': (FORM_FILE, captcha)},
- multipart=True)
- finally:
- req.close()
-
- data = dict(x.split(' ', 1) for x in res.splitlines())
- if not data or "Value" not in data:
- raise BypassCaptchaException(res)
-
- result = data['Value']
- ticket = data['TaskId']
- self.logDebug("Result %s : %s" % (ticket, result))
-
- return ticket, result
-
-
- def respond(self, ticket, success):
- try:
- res = getURL(self.RESPOND_URL, post={"task_id": ticket, "key": self.getConfig("passkey"),
- "cv": 1 if success else 0})
- except BadHeader, e:
- self.logError(_("Could not send response"), e)
-
-
- def captchaTask(self, task):
- if "service" in task.data:
- return False
-
- if not task.isTextual():
- return False
-
- if not self.getConfig("passkey"):
- return False
-
- if self.core.isClientConnected() and not self.getConfig("force"):
- return False
-
- if self.getCredits() > 0:
- task.handler.append(self)
- task.data['service'] = self.__name__
- task.setWaiting(100)
- self._processCaptcha(task)
-
- else:
- self.logInfo(_("Your %s account has not enough credits") % self.__name__)
-
-
- def captchaCorrect(self, task):
- if task.data['service'] == self.__name__ and "ticket" in task.data:
- self.respond(task.data['ticket'], True)
-
-
- def captchaInvalid(self, task):
- if task.data['service'] == self.__name__ and "ticket" in task.data:
- self.respond(task.data['ticket'], False)
-
-
- @threaded
- def _processCaptcha(self, task):
- c = task.captchaFile
- try:
- ticket, result = self.submit(c)
- except BypassCaptchaException, e:
- task.error = e.getCode()
- return
-
- task.data['ticket'] = ticket
- task.setResult(result)
diff --git a/module/plugins/hooks/Captcha9Kw.py b/module/plugins/hooks/Captcha9Kw.py
deleted file mode 100644
index 04caff345..000000000
--- a/module/plugins/hooks/Captcha9Kw.py
+++ /dev/null
@@ -1,251 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import re
-
-from base64 import b64encode
-from time import sleep
-
-from pyload.network.HTTPRequest import BadHeader
-from pyload.network.RequestFactory import getURL
-
-from module.plugins.Hook import Hook, threaded
-
-
-class Captcha9kw(Hook):
- __name__ = "Captcha9Kw"
- __type__ = "hook"
- __version__ = "0.28"
-
- __config__ = [("ssl" , "bool" , "Use HTTPS" , True ),
- ("force" , "bool" , "Force captcha resolving even if client is connected" , True ),
- ("confirm" , "bool" , "Confirm Captcha (cost +6 credits)" , False ),
- ("captchaperhour", "int" , "Captcha per hour" , "9999" ),
- ("captchapermin" , "int" , "Captcha per minute" , "9999" ),
- ("prio" , "int" , "Priority (max 10)(cost +0 -> +10 credits)" , "0" ),
- ("queue" , "int" , "Max. Queue (max 999)" , "50" ),
- ("hoster_options", "string" , "Hoster options (format: pluginname:prio=1:selfsolfe=1:confirm=1:timeout=900|...)", "ShareonlineBiz:prio=0:timeout=999 | UploadedTo:prio=0:timeout=999"),
- ("selfsolve" , "bool" , "Selfsolve (manually solve your captcha in your 9kw client if active)" , "0" ),
- ("passkey" , "password", "API key" , "" ),
- ("timeout" , "int" , "Timeout in seconds (min 60, max 3999)" , "900" )]
-
- __description__ = """Send captchas to 9kw.eu"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- API_URL = "http://www.9kw.eu/index.cgi"
-
-
- def activate(self):
- if self.getConfig("ssl"):
- self.API_URL = self.API_URL.replace("http://", "https://")
-
-
- def getCredits(self):
- res = getURL(self.API_URL,
- get={'apikey': self.getConfig("passkey"),
- 'pyload': "1",
- 'source': "pyload",
- 'action': "usercaptchaguthaben"})
-
- if res.isdigit():
- self.logInfo(_("%s credits left") % res)
- credits = self.info['credits'] = int(res)
- return credits
- else:
- self.logError(res)
- return 0
-
-
- @threaded
- def _processCaptcha(self, task):
- try:
- with open(task.captchaFile, 'rb') as f:
- data = f.read()
-
- except IOError, e:
- self.logError(e)
- return
-
- pluginname = re.search(r'_([^_]*)_\d+.\w+', task.captchaFile).group(1)
- option = {'min' : 2,
- 'max' : 50,
- 'phrase' : 0,
- 'numeric' : 0,
- 'case_sensitive': 0,
- 'math' : 0,
- 'prio' : min(max(self.getConfig("prio"), 0), 10),
- 'confirm' : self.getConfig("confirm"),
- 'timeout' : min(max(self.getConfig("timeout"), 300), 3999),
- 'selfsolve' : self.getConfig("selfsolve"),
- 'cph' : self.getConfig("captchaperhour"),
- 'cpm' : self.getConfig("captchapermin")}
-
- for opt in str(self.getConfig("hoster_options").split('|')):
-
- details = map(str.strip, opt.split(':'))
-
- if not details or details[0].lower() != pluginname.lower():
- continue
-
- for d in details:
- hosteroption = d.split("=")
-
- if len(hosteroption) < 2 or not hosteroption[1].isdigit():
- continue
-
- o = hosteroption[0].lower()
- if o in option:
- option[o] = hosteroption[1]
-
- break
-
- post_data = {'apikey' : self.getConfig("passkey"),
- 'prio' : option['prio'],
- 'confirm' : option['confirm'],
- 'maxtimeout' : option['timeout'],
- 'selfsolve' : option['selfsolve'],
- 'captchaperhour': option['cph'],
- 'captchapermin' : option['cpm'],
- 'case-sensitive': option['case_sensitive'],
- 'min_len' : option['min'],
- 'max_len' : option['max'],
- 'phrase' : option['phrase'],
- 'numeric' : option['numeric'],
- 'math' : option['math'],
- 'oldsource' : pluginname,
- 'pyload' : "1",
- 'source' : "pyload",
- 'base64' : "1",
- 'mouse' : 1 if task.isPositional() else 0,
- 'file-upload-01': b64encode(data),
- 'action' : "usercaptchaupload"}
-
- for _i in xrange(5):
- try:
- res = getURL(self.API_URL, post=post_data)
- except BadHeader, e:
- sleep(3)
- else:
- if res and res.isdigit():
- break
- else:
- self.logError(_("Bad upload: %s") % res)
- return
-
- self.logDebug(_("NewCaptchaID ticket: %s") % res, task.captchaFile)
-
- task.data["ticket"] = res
-
- for _i in xrange(int(self.getConfig("timeout") / 5)):
- result = getURL(self.API_URL,
- get={'apikey': self.getConfig("passkey"),
- 'id' : res,
- 'pyload': "1",
- 'info' : "1",
- 'source': "pyload",
- 'action': "usercaptchacorrectdata"})
-
- if not result or result == "NO DATA":
- sleep(5)
- else:
- break
- else:
- self.logDebug("Could not send request: %s" % res)
- result = None
-
- self.logInfo(_("Captcha result for ticket %s: %s") % (res, result))
-
- task.setResult(result)
-
-
- def captchaTask(self, task):
- if not task.isTextual() and not task.isPositional():
- return
-
- if not self.getConfig("passkey"):
- return
-
- if self.core.isClientConnected() and not self.getConfig("force"):
- return
-
- credits = self.getCredits()
-
- if not credits:
- self.logError(_("Your captcha 9kw.eu account has not enough credits"))
- return
-
- queue = min(self.getConfig("queue"), 999)
- timeout = min(max(self.getConfig("timeout"), 300), 3999)
- pluginname = re.search(r'_([^_]*)_\d+.\w+', task.captchaFile).group(1)
-
- for _i in xrange(5):
- servercheck = getURL("http://www.9kw.eu/grafik/servercheck.txt")
- if queue < re.search(r'queue=(\d+)', servercheck).group(1):
- break
-
- sleep(10)
- else:
- self.fail(_("Too many captchas in queue"))
-
- for opt in str(self.getConfig("hoster_options").split('|')):
- details = map(str.strip, opt.split(':'))
-
- if not details or details[0].lower() != pluginname.lower():
- continue
-
- for d in details:
- hosteroption = d.split("=")
-
- if len(hosteroption) > 1 \
- and hosteroption[0].lower() == 'timeout' \
- and hosteroption[1].isdigit():
- timeout = int(hosteroption[1])
-
- break
-
- task.handler.append(self)
-
- task.setWaiting(timeout)
-
- self._processCaptcha(task)
-
-
- def _captchaResponse(self, task, correct):
- type = "correct" if correct else "refund"
-
- if 'ticket' not in task.data:
- self.logDebug("No CaptchaID for %s request (task: %s)" % (type, task))
- return
-
- passkey = self.getConfig("passkey")
-
- for _i in xrange(3):
- res = getURL(self.API_URL,
- get={'action' : "usercaptchacorrectback",
- 'apikey' : passkey,
- 'api_key': passkey,
- 'correct': "1" if correct else "2",
- 'pyload' : "1",
- 'source' : "pyload",
- 'id' : task.data["ticket"]})
-
- self.logDebug("Request %s: %s" % (type, res))
-
- if res == "OK":
- break
-
- sleep(5)
- else:
- self.logDebug("Could not send %s request: %s" % (type, res))
-
-
- def captchaCorrect(self, task):
- self._captchaResponse(task, True)
-
-
- def captchaInvalid(self, task):
- self._captchaResponse(task, False)
diff --git a/module/plugins/hooks/CaptchaBrotherhood.py b/module/plugins/hooks/CaptchaBrotherhood.py
deleted file mode 100644
index ba9d3eb8e..000000000
--- a/module/plugins/hooks/CaptchaBrotherhood.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import StringIO
-import pycurl
-
-try:
- from PIL import Image
-except ImportError:
- import Image
-
-from time import sleep
-from urllib import urlencode
-
-from pyload.network.RequestFactory import getURL, getRequest
-from module.plugins.Hook import Hook, threaded
-
-
-class CaptchaBrotherhoodException(Exception):
-
- def __init__(self, err):
- self.err = err
-
-
- def getCode(self):
- return self.err
-
-
- def __str__(self):
- return "<CaptchaBrotherhoodException %s>" % self.err
-
-
- def __repr__(self):
- return "<CaptchaBrotherhoodException %s>" % self.err
-
-
-class CaptchaBrotherhood(Addon):
- __name__ = "CaptchaBrotherhood"
- __type__ = "hook"
- __version__ = "0.08"
-
- __config__ = [("username", "str", "Username", ""),
- ("force", "bool", "Force CT even if client is connected", False),
- ("passkey", "password", "Password", "")]
-
- __description__ = """Send captchas to CaptchaBrotherhood.com"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("zoidberg", "zoidberg@mujmail.cz")]
-
-
- API_URL = "http://www.captchabrotherhood.com/"
-
-
- def getCredits(self):
- res = getURL(self.API_URL + "askCredits.aspx",
- get={"username": self.getConfig("username"), "password": self.getConfig("passkey")})
- if not res.startswith("OK"):
- raise CaptchaBrotherhoodException(res)
- else:
- credits = int(res[3:])
- self.logInfo(_("%d credits left") % credits)
- self.info['credits'] = credits
- return credits
-
-
- def submit(self, captcha, captchaType="file", match=None):
- try:
- img = Image.open(captcha)
- output = StringIO.StringIO()
- self.logDebug("CAPTCHA IMAGE", img, img.format, img.mode)
- if img.format in ("GIF", "JPEG"):
- img.save(output, img.format)
- else:
- if img.mode != "RGB":
- img = img.convert("RGB")
- img.save(output, "JPEG")
- data = output.getvalue()
- output.close()
- except Exception, e:
- raise CaptchaBrotherhoodException("Reading or converting captcha image failed: %s" % e)
-
- req = getRequest()
-
- url = "%ssendNewCaptcha.aspx?%s" % (self.API_URL,
- urlencode({'username' : self.getConfig("username"),
- 'password' : self.getConfig("passkey"),
- 'captchaSource': "pyLoad",
- 'timeout' : "80"}))
-
- req.c.setopt(pycurl.URL, url)
- req.c.setopt(pycurl.POST, 1)
- req.c.setopt(pycurl.POSTFIELDS, data)
- req.c.setopt(pycurl.HTTPHEADER, ["Content-Type: text/html"])
-
- try:
- req.c.perform()
- res = req.getResponse()
- except Exception, e:
- raise CaptchaBrotherhoodException("Submit captcha image failed")
-
- req.close()
-
- if not res.startswith("OK"):
- raise CaptchaBrotherhoodException(res[1])
-
- ticket = res[3:]
-
- for _i in xrange(15):
- sleep(5)
- res = self.api_response("askCaptchaResult", ticket)
- if res.startswith("OK-answered"):
- return ticket, res[12:]
-
- raise CaptchaBrotherhoodException("No solution received in time")
-
-
- def api_response(self, api, ticket):
- res = getURL("%s%s.aspx" % (self.API_URL, api),
- get={"username": self.getConfig("username"),
- "password": self.getConfig("passkey"),
- "captchaID": ticket})
- if not res.startswith("OK"):
- raise CaptchaBrotherhoodException("Unknown response: %s" % res)
-
- return res
-
-
- def captchaTask(self, task):
- if "service" in task.data:
- return False
-
- if not task.isTextual():
- return False
-
- if not self.getConfig("username") or not self.getConfig("passkey"):
- return False
-
- if self.core.isClientConnected() and not self.getConfig("force"):
- return False
-
- if self.getCredits() > 10:
- task.handler.append(self)
- task.data['service'] = self.__name__
- task.setWaiting(100)
- self._processCaptcha(task)
- else:
- self.logInfo(_("Your CaptchaBrotherhood Account has not enough credits"))
-
-
- def captchaInvalid(self, task):
- if task.data['service'] == self.__name__ and "ticket" in task.data:
- res = self.api_response("complainCaptcha", task.data['ticket'])
-
-
- @threaded
- def _processCaptcha(self, task):
- c = task.captchaFile
- try:
- ticket, result = self.submit(c)
- except CaptchaBrotherhoodException, e:
- task.error = e.getCode()
- return
-
- task.data['ticket'] = ticket
- task.setResult(result)
diff --git a/module/plugins/hooks/ClickAndLoad.py b/module/plugins/hooks/ClickAndLoad.py
deleted file mode 100644
index 8b53872e4..000000000
--- a/module/plugins/hooks/ClickAndLoad.py
+++ /dev/null
@@ -1,124 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import socket
-
-from threading import Lock
-
-from module.plugins.Hook import Hook, threaded
-
-
-def forward(source, destination):
- try:
- bufsize = 1024
- bufdata = source.recv(bufsize)
- while bufdata:
- destination.sendall(bufdata)
- bufdata = source.recv(bufsize)
- finally:
- destination.shutdown(socket.SHUT_WR)
-
-
-#: create_connection wrapper for python 2.5 socket module
-def create_connection(address, timeout=object(), source_address=None):
- if hasattr(socket, 'create_connection'):
- if type(timeout) == object:
- timeout = socket._GLOBAL_DEFAULT_TIMEOUT
-
- return socket.create_connection(address, timeout, source_address)
-
- else:
- host, port = address
- err = None
- for res in getaddrinfo(host, port, 0, SOCK_STREAM):
- af, socktype, proto, canonname, sa = res
- sock = None
- try:
- sock = socket(af, socktype, proto)
- if type(timeout) != object:
- sock.settimeout(timeout)
- if source_address:
- sock.bind(source_address)
- sock.connect(sa)
- return sock
-
- except socket.error, _:
- err = _
- if sock is not None:
- sock.close()
-
- if err is not None:
- raise err
- else:
- raise socket.error("getaddrinfo returns an empty list")
-
-
-class ClickAndLoad(Hook):
- __name__ = "ClickAndLoad"
- __type__ = "hook"
- __version__ = "0.35"
-
- __config__ = [("activated", "bool", "Activated" , True),
- ("port" , "int" , "Port" , 9666),
- ("extern" , "bool", "Listen on the public network interface", True)]
-
- __description__ = """Click'N'Load hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.de"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- #@TODO: Remove in 0.4.10
- def initPeriodical(self):
- pass
-
-
- def coreReady(self):
- if not self.config['webinterface']['activated']:
- return
-
- ip = socket.gethostbyname(socket.gethostname()) if self.getConfig("extern") else "127.0.0.1"
- webport = int(self.config['webinterface']['port'])
- cnlport = self.getConfig('port')
-
- self.proxy(ip, webport, cnlport)
-
-
- @threaded
- def proxy(self, ip, webport, cnlport):
- self.manager.startThread(self._server, ip, webport, cnlport)
- lock = Lock()
- lock.acquire()
- lock.acquire()
-
-
- def _server(self, ip, webport, cnlport, thread):
- try:
- server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- server_socket.bind((ip, cnlport))
- server_socket.listen(5)
-
- while True:
- client_socket = server_socket.accept()[0]
- dock_socket = create_connection(("127.0.0.1", webport))
-
- self.manager.startThread(forward, dock_socket, client_socket)
- self.manager.startThread(forward, client_socket, dock_socket)
-
- except socket.error, e:
- self.logDebug(e)
- self._server(ip, webport, cnlport, thread)
-
- except Exception, e:
- self.logError(e)
-
- try:
- client_socket.close()
- dock_socket.close()
- except Exception:
- pass
-
- try:
- server_socket.close()
- except Exception:
- pass
diff --git a/module/plugins/hooks/DeathByCaptcha.py b/module/plugins/hooks/DeathByCaptcha.py
deleted file mode 100644
index 8786df12f..000000000
--- a/module/plugins/hooks/DeathByCaptcha.py
+++ /dev/null
@@ -1,214 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import re
-
-from base64 import b64encode
-from pycurl import FORM_FILE, HTTPHEADER
-from time import sleep
-
-from pyload.utils import json_loads
-from pyload.network.HTTPRequest import BadHeader
-from pyload.network.RequestFactory import getRequest
-from module.plugins.Hook import Hook, threaded
-
-
-class DeathByCaptchaException(Exception):
- DBC_ERRORS = {'not-logged-in': 'Access denied, check your credentials',
- 'invalid-credentials': 'Access denied, check your credentials',
- 'banned': 'Access denied, account is suspended',
- 'insufficient-funds': 'Insufficient account balance to decrypt CAPTCHA',
- 'invalid-captcha': 'CAPTCHA is not a valid image',
- 'service-overload': 'CAPTCHA was rejected due to service overload, try again later',
- 'invalid-request': 'Invalid request',
- 'timed-out': 'No CAPTCHA solution received in time'}
-
-
- def __init__(self, err):
- self.err = err
-
-
- def getCode(self):
- return self.err
-
-
- def getDesc(self):
- if self.err in self.DBC_ERRORS.keys():
- return self.DBC_ERRORS[self.err]
- else:
- return self.err
-
-
- def __str__(self):
- return "<DeathByCaptchaException %s>" % self.err
-
-
- def __repr__(self):
- return "<DeathByCaptchaException %s>" % self.err
-
-
-class DeathByCaptcha(Addon):
- __name__ = "DeathByCaptcha"
- __type__ = "hook"
- __version__ = "0.06"
-
- __config__ = [("username", "str", "Username", ""),
- ("passkey", "password", "Password", ""),
- ("force", "bool", "Force DBC even if client is connected", False)]
-
- __description__ = """Send captchas to DeathByCaptcha.com"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("zoidberg", "zoidberg@mujmail.cz")]
-
-
- API_URL = "http://api.dbcapi.me/api/"
-
-
- def api_response(self, api="captcha", post=False, multipart=False):
- req = getRequest()
- req.c.setopt(HTTPHEADER, ["Accept: application/json", "User-Agent: pyLoad %s" % self.core.version])
-
- if post:
- if not isinstance(post, dict):
- post = {}
- post.update({"username": self.getConfig("username"),
- "password": self.getConfig("passkey")})
-
- res = None
- try:
- json = req.load("%s%s" % (self.API_URL, api),
- post=post,
- multipart=multipart)
- self.logDebug(json)
- res = json_loads(json)
-
- if "error" in res:
- raise DeathByCaptchaException(res['error'])
- elif "status" not in res:
- raise DeathByCaptchaException(str(res))
-
- except BadHeader, e:
- if 403 == e.code:
- raise DeathByCaptchaException('not-logged-in')
- elif 413 == e.code:
- raise DeathByCaptchaException('invalid-captcha')
- elif 503 == e.code:
- raise DeathByCaptchaException('service-overload')
- elif e.code in (400, 405):
- raise DeathByCaptchaException('invalid-request')
- else:
- raise
-
- finally:
- req.close()
-
- return res
-
-
- def getCredits(self):
- res = self.api_response("user", True)
-
- if 'is_banned' in res and res['is_banned']:
- raise DeathByCaptchaException('banned')
- elif 'balance' in res and 'rate' in res:
- self.info.update(res)
- else:
- raise DeathByCaptchaException(res)
-
-
- def getStatus(self):
- res = self.api_response("status", False)
-
- if 'is_service_overloaded' in res and res['is_service_overloaded']:
- raise DeathByCaptchaException('service-overload')
-
-
- def submit(self, captcha, captchaType="file", match=None):
- #@NOTE: Workaround multipart-post bug in HTTPRequest.py
- if re.match("^\w*$", self.getConfig("passkey")):
- multipart = True
- data = (FORM_FILE, captcha)
- else:
- multipart = False
- with open(captcha, 'rb') as f:
- data = f.read()
- data = "base64:" + b64encode(data)
-
- res = self.api_response("captcha", {"captchafile": data}, multipart)
-
- if "captcha" not in res:
- raise DeathByCaptchaException(res)
- ticket = res['captcha']
-
- for _i in xrange(24):
- sleep(5)
- res = self.api_response("captcha/%d" % ticket, False)
- if res['text'] and res['is_correct']:
- break
- else:
- raise DeathByCaptchaException('timed-out')
-
- result = res['text']
- self.logDebug("Result %s : %s" % (ticket, result))
-
- return ticket, result
-
-
- def captchaTask(self, task):
- if "service" in task.data:
- return False
-
- if not task.isTextual():
- return False
-
- if not self.getConfig("username") or not self.getConfig("passkey"):
- return False
-
- if self.core.isClientConnected() and not self.getConfig("force"):
- return False
-
- try:
- self.getStatus()
- self.getCredits()
- except DeathByCaptchaException, e:
- self.logError(e.getDesc())
- return False
-
- balance, rate = self.info['balance'], self.info['rate']
- self.logInfo(_("Account balance"),
- _("US$%.3f (%d captchas left at %.2f cents each)") % (balance / 100,
- balance // rate, rate))
-
- if balance > rate:
- task.handler.append(self)
- task.data['service'] = self.__name__
- task.setWaiting(180)
- self._processCaptcha(task)
-
-
- def captchaInvalid(self, task):
- if task.data['service'] == self.__name__ and "ticket" in task.data:
- try:
- res = self.api_response("captcha/%d/report" % task.data['ticket'], True)
-
- except DeathByCaptchaException, e:
- self.logError(e.getDesc())
-
- except Exception, e:
- self.logError(e)
-
-
- @threaded
- def _processCaptcha(self, task):
- c = task.captchaFile
- try:
- ticket, result = self.submit(c)
- except DeathByCaptchaException, e:
- task.error = e.getCode()
- self.logError(e.getDesc())
- return
-
- task.data['ticket'] = ticket
- task.setResult(result)
diff --git a/module/plugins/hooks/DebridItaliaCom.py b/module/plugins/hooks/DebridItaliaCom.py
deleted file mode 100644
index 719f3dd3a..000000000
--- a/module/plugins/hooks/DebridItaliaCom.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class DebridItaliaCom(MultiHook):
- __name__ = "DebridItaliaCom"
- __type__ = "hook"
- __version__ = "0.12"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Debriditalia.com hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- def getHosters(self):
- return self.getURL("http://debriditalia.com/api.php", get={'hosts': ""}).replace('"', '').split(',')
diff --git a/module/plugins/hooks/EasybytezCom.py b/module/plugins/hooks/EasybytezCom.py
deleted file mode 100644
index 85c616054..000000000
--- a/module/plugins/hooks/EasybytezCom.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class EasybytezCom(MultiHook):
- __name__ = "EasybytezCom"
- __type__ = "hook"
- __version__ = "0.07"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """EasyBytez.com hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- def getHosters(self):
- user, data = self.account.selectAccount()
-
- req = self.account.getAccountRequest(user)
- html = req.load("http://www.easybytez.com")
-
- return re.search(r'</textarea>\s*Supported sites:(.*)', html).group(1).split(',')
diff --git a/module/plugins/hooks/ExpertDecoders.py b/module/plugins/hooks/ExpertDecoders.py
deleted file mode 100644
index 04f6d0795..000000000
--- a/module/plugins/hooks/ExpertDecoders.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-from base64 import b64encode
-from pycurl import LOW_SPEED_TIME
-from uuid import uuid4
-
-from module.network.HTTPRequest import BadHeader
-from module.network.RequestFactory import getURL, getRequest
-from module.plugins.Hook import Hook, threaded
-
-
-class ExpertDecoders(Addon):
- __name__ = "ExpertDecoders"
- __type__ = "hook"
- __version__ = "0.04"
-
- __config__ = [("force", "bool", "Force CT even if client is connected", False),
- ("passkey", "password", "Access key", "")]
-
- __description__ = """Send captchas to expertdecoders.com"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("zoidberg", "zoidberg@mujmail.cz")]
-
-
- API_URL = "http://www.fasttypers.org/imagepost.ashx"
-
-
- def getCredits(self):
- res = getURL(self.API_URL, post={"key": self.getConfig("passkey"), "action": "balance"})
-
- if res.isdigit():
- self.logInfo(_("%s credits left") % res)
- self.info['credits'] = credits = int(res)
- return credits
- else:
- self.logError(res)
- return 0
-
-
- @threaded
- def _processCaptcha(self, task):
- task.data['ticket'] = ticket = uuid4()
- result = None
-
- with open(task.captchaFile, 'rb') as f:
- data = f.read()
-
- req = getRequest()
- #raise timeout threshold
- req.c.setopt(LOW_SPEED_TIME, 80)
-
- try:
- result = req.load(self.API_URL,
- post={'action' : "upload",
- 'key' : self.getConfig("passkey"),
- 'file' : b64encode(data),
- 'gen_task_id': ticket})
- finally:
- req.close()
-
- self.logDebug("Result %s : %s" % (ticket, result))
- task.setResult(result)
-
-
- def captchaTask(self, task):
- if not task.isTextual():
- return False
-
- if not self.getConfig("passkey"):
- return False
-
- if self.core.isClientConnected() and not self.getConfig("force"):
- return False
-
- if self.getCredits() > 0:
- task.handler.append(self)
- task.setWaiting(100)
- self._processCaptcha(task)
-
- else:
- self.logInfo(_("Your ExpertDecoders Account has not enough credits"))
-
-
- def captchaInvalid(self, task):
- if "ticket" in task.data:
-
- try:
- res = getURL(self.API_URL,
- post={'action': "refund", 'key': self.getConfig("passkey"), 'gen_task_id': task.data['ticket']})
- self.logInfo(_("Request refund"), res)
-
- except BadHeader, e:
- self.logError(_("Could not send refund request"), e)
diff --git a/module/plugins/hooks/FastixRu.py b/module/plugins/hooks/FastixRu.py
deleted file mode 100644
index 5f339c4c0..000000000
--- a/module/plugins/hooks/FastixRu.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.utils import json_loads
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class FastixRu(MultiHook):
- __name__ = "FastixRu"
- __type__ = "hook"
- __version__ = "0.05"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Fastix.ru hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Massimo Rosamilia", "max@spiritix.eu")]
-
-
- def getHosters(self):
- html = self.getURL("http://fastix.ru/api_v2",
- get={'apikey': "5182964c3f8f9a7f0b00000a_kelmFB4n1IrnCDYuIFn2y",
- 'sub' : "allowed_sources"})
- host_list = json_loads(html)
- host_list = host_list['allow']
- return host_list
diff --git a/module/plugins/hooks/FreeWayMe.py b/module/plugins/hooks/FreeWayMe.py
deleted file mode 100644
index 6fec037d8..000000000
--- a/module/plugins/hooks/FreeWayMe.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class FreeWayMe(MultiHook):
- __name__ = "FreeWayMe"
- __type__ = "hook"
- __version__ = "0.14"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """FreeWay.me hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Nicolas Giese", "james@free-way.me")]
-
-
- def getHosters(self):
- hostis = self.getURL("https://www.free-way.me/ajax/jd.php", get={'id': 3}).replace("\"", "").strip()
- self.logDebug("Hosters", hostis)
- return [x.strip() for x in hostis.split(",") if x.strip()]
diff --git a/module/plugins/hooks/ImageTyperz.py b/module/plugins/hooks/ImageTyperz.py
deleted file mode 100644
index 8bf326f4d..000000000
--- a/module/plugins/hooks/ImageTyperz.py
+++ /dev/null
@@ -1,153 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import re
-
-from base64 import b64encode
-from pycurl import FORM_FILE, LOW_SPEED_TIME
-
-from module.network.RequestFactory import getURL, getRequest
-from module.plugins.Hook import Hook, threaded
-
-
-class ImageTyperzException(Exception):
-
- def __init__(self, err):
- self.err = err
-
-
- def getCode(self):
- return self.err
-
-
- def __str__(self):
- return "<ImageTyperzException %s>" % self.err
-
-
- def __repr__(self):
- return "<ImageTyperzException %s>" % self.err
-
-
-class ImageTyperz(Addon):
- __name__ = "ImageTyperz"
- __type__ = "hook"
- __version__ = "0.06"
-
- __config__ = [("username", "str", "Username", ""),
- ("passkey", "password", "Password", ""),
- ("force", "bool", "Force IT even if client is connected", False)]
-
- __description__ = """Send captchas to ImageTyperz.com"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("zoidberg", "zoidberg@mujmail.cz")]
-
-
- SUBMIT_URL = "http://captchatypers.com/Forms/UploadFileAndGetTextNEW.ashx"
- RESPOND_URL = "http://captchatypers.com/Forms/SetBadImage.ashx"
- GETCREDITS_URL = "http://captchatypers.com/Forms/RequestBalance.ashx"
-
-
- def getCredits(self):
- res = getURL(self.GETCREDITS_URL,
- post={'action': "REQUESTBALANCE",
- 'username': self.getConfig("username"),
- 'password': self.getConfig("passkey")})
-
- if res.startswith('ERROR'):
- raise ImageTyperzException(res)
-
- try:
- balance = float(res)
- except Exception:
- raise ImageTyperzException("Invalid response")
-
- self.logInfo(_("Account balance: $%s left") % res)
- return balance
-
-
- def submit(self, captcha, captchaType="file", match=None):
- req = getRequest()
- #raise timeout threshold
- req.c.setopt(LOW_SPEED_TIME, 80)
-
- try:
- #@NOTE: Workaround multipart-post bug in HTTPRequest.py
- if re.match("^\w*$", self.getConfig("passkey")):
- multipart = True
- data = (FORM_FILE, captcha)
- else:
- multipart = False
- with open(captcha, 'rb') as f:
- data = f.read()
- data = b64encode(data)
-
- res = req.load(self.SUBMIT_URL,
- post={'action': "UPLOADCAPTCHA",
- 'username': self.getConfig("username"),
- 'password': self.getConfig("passkey"), "file": data},
- multipart=multipart)
- finally:
- req.close()
-
- if res.startswith("ERROR"):
- raise ImageTyperzException(res)
- else:
- data = res.split('|')
- if len(data) == 2:
- ticket, result = data
- else:
- raise ImageTyperzException("Unknown response: %s" % res)
-
- return ticket, result
-
-
- def captchaTask(self, task):
- if "service" in task.data:
- return False
-
- if not task.isTextual():
- return False
-
- if not self.getConfig("username") or not self.getConfig("passkey"):
- return False
-
- if self.core.isClientConnected() and not self.getConfig("force"):
- return False
-
- if self.getCredits() > 0:
- task.handler.append(self)
- task.data['service'] = self.__name__
- task.setWaiting(100)
- self._processCaptcha(task)
-
- else:
- self.logInfo(_("Your %s account has not enough credits") % self.__name__)
-
-
- def captchaInvalid(self, task):
- if task.data['service'] == self.__name__ and "ticket" in task.data:
- res = getURL(self.RESPOND_URL,
- post={'action': "SETBADIMAGE",
- 'username': self.getConfig("username"),
- 'password': self.getConfig("passkey"),
- 'imageid': task.data['ticket']})
-
- if res == "SUCCESS":
- self.logInfo(_("Bad captcha solution received, requested refund"))
- else:
- self.logError(_("Bad captcha solution received, refund request failed"), res)
-
-
- @threaded
- def _processCaptcha(self, task):
- c = task.captchaFile
- try:
- ticket, result = self.submit(c)
- except ImageTyperzException, e:
- task.error = e.getCode()
- return
-
- task.data['ticket'] = ticket
- task.setResult(result)
diff --git a/module/plugins/hooks/JustPremium.py b/module/plugins/hooks/JustPremium.py
deleted file mode 100644
index b70d8dd2c..000000000
--- a/module/plugins/hooks/JustPremium.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.Hook import Hook
-
-
-class JustPremium(Hook):
- __name__ = "JustPremium"
- __type__ = "hook"
- __version__ = "0.21"
-
- __config__ = [("excluded", "str", "Exclude hosters (comma separated)", "")]
-
- __description__ = """Remove all not premium links from urls added"""
- __license__ = "GPLv3"
- __authors__ = [("mazleu", "mazleica@gmail.com"),
- ("Walter Purcaro", "vuolter@gmail.com"),
- ("immenz", "immenz@gmx.net")]
-
-
- event_list = ["linksAdded"]
-
-
- def linksAdded(self, links, pid):
- hosterdict = self.core.pluginManager.hosterPlugins
- linkdict = self.core.api.checkURLs(links)
-
- premiumplugins = set(account.type for account in self.core.api.getAccounts(False) \
- if account.valid and account.premium)
- multihosters = set(hoster for hoster in self.core.pluginManager.hosterPlugins \
- if 'new_name' in hosterdict[hoster] \
- and hosterdict[hoster]['new_name'] in premiumplugins)
-
- #: Found at least one hoster with account or multihoster
- if not any(True for pluginname in linkdict if pluginname in premiumplugins | multihosters):
- return
-
- excluded = map(lambda domain: "".join(part.capitalize() for part in re.split(r'(\.|\d+)', domain) if part != '.'),
- self.getConfig('excluded').replace(' ', '').replace(',', '|').replace(';', '|').split('|'))
-
- for pluginname in set(linkdict.keys()) - (premiumplugins | multihosters).union(excluded):
- self.logInfo(_("Remove links of plugin: %s") % pluginname)
- for link in linkdict[pluginname]:
- self.logDebug("Remove link: %s" % link)
- links.remove(link)
diff --git a/module/plugins/hooks/LinkdecrypterCom.py b/module/plugins/hooks/LinkdecrypterCom.py
deleted file mode 100644
index f85a598bc..000000000
--- a/module/plugins/hooks/LinkdecrypterCom.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class LinkdecrypterCom(MultiHook):
- __name__ = "LinkdecrypterCom"
- __type__ = "hook"
- __version__ = "1.02"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Linkdecrypter.com hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- def getCrypters(self):
- return re.search(r'>Supported\(\d+\)</b>: <i>(.[\w.\-, ]+)',
- self.getURL("http://linkdecrypter.com/").replace("(g)", "")).group(1).split(', ')
diff --git a/module/plugins/hooks/LinksnappyCom.py b/module/plugins/hooks/LinksnappyCom.py
deleted file mode 100644
index 7e607a3d3..000000000
--- a/module/plugins/hooks/LinksnappyCom.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.utils import json_loads
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class LinksnappyCom(MultiHook):
- __name__ = "LinksnappyCom"
- __type__ = "hook"
- __version__ = "0.04"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Linksnappy.com hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- def getHosters(self):
- json_data = self.getURL("http://gen.linksnappy.com/lseAPI.php", get={'act': "FILEHOSTS"})
- json_data = json_loads(json_data)
-
- return json_data['return'].keys()
diff --git a/module/plugins/hooks/MegaDebridEu.py b/module/plugins/hooks/MegaDebridEu.py
deleted file mode 100644
index 0711b3546..000000000
--- a/module/plugins/hooks/MegaDebridEu.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.utils import json_loads
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class MegaDebridEu(MultiHook):
- __name__ = "MegaDebridEu"
- __type__ = "hook"
- __version__ = "0.05"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Mega-debrid.eu hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("D.Ducatel", "dducatel@je-geek.fr")]
-
-
- def getHosters(self):
- reponse = self.getURL("http://www.mega-debrid.eu/api.php", get={'action': "getHosters"})
- json_data = json_loads(reponse)
-
- if json_data['response_code'] == "ok":
- host_list = [element[0] for element in json_data['hosters']]
- else:
- self.logError(_("Unable to retrieve hoster list"))
- host_list = list()
-
- return host_list
diff --git a/module/plugins/hooks/MultihostersCom.py b/module/plugins/hooks/MultihostersCom.py
deleted file mode 100644
index bf88cfae7..000000000
--- a/module/plugins/hooks/MultihostersCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.hooks.ZeveraCom import ZeveraCom
-
-
-class MultihostersCom(ZeveraCom):
- __name__ = "MultihostersCom"
- __type__ = "hook"
- __version__ = "0.02"
-
- __config__ = [("mode" , "all;listed;unlisted", "Use for plugins (if supported)" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed", "bool" , "Revert to standard download if download fails", False),
- ("interval" , "int" , "Reload interval in hours (0 to disable)" , 12 )]
-
- __description__ = """Multihosters.com hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("tjeh", "tjeh@gmx.net")]
diff --git a/module/plugins/hooks/MultishareCz.py b/module/plugins/hooks/MultishareCz.py
deleted file mode 100644
index d02f4f8e3..000000000
--- a/module/plugins/hooks/MultishareCz.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class MultishareCz(MultiHook):
- __name__ = "MultishareCz"
- __type__ = "hook"
- __version__ = "0.07"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """MultiShare.cz hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- HOSTER_PATTERN = r'<img class="logo-shareserveru"[^>]*?alt="([^"]+)"></td>\s*<td class="stav">[^>]*?alt="OK"'
-
-
- def getHosters(self):
- html = self.getURL("http://www.multishare.cz/monitoring/")
- return re.findall(self.HOSTER_PATTERN, html)
diff --git a/module/plugins/hooks/MyfastfileCom.py b/module/plugins/hooks/MyfastfileCom.py
deleted file mode 100644
index a1b5aaba0..000000000
--- a/module/plugins/hooks/MyfastfileCom.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.MultiHook import MultiHook
-from pyload.utils import json_loads
-
-
-class MyfastfileCom(MultiHook):
- __name__ = "MyfastfileCom"
- __type__ = "hook"
- __version__ = "0.05"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Myfastfile.com hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- def getHosters(self):
- json_data = self.getURL("http://myfastfile.com/api.php", get={'hosts': ""}, decode=True)
- self.logDebug("JSON data", json_data)
- json_data = json_loads(json_data)
-
- return json_data['hosts']
diff --git a/module/plugins/hooks/NoPremiumPl.py b/module/plugins/hooks/NoPremiumPl.py
deleted file mode 100644
index 1727bec70..000000000
--- a/module/plugins/hooks/NoPremiumPl.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.common.json_layer import json_loads
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class NoPremiumPl(MultiHook):
- __name__ = "NoPremiumPl"
- __type__ = "hook"
- __version__ = "0.03"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """NoPremium.pl hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("goddie", "dev@nopremium.pl")]
-
-
- def getHosters(self):
- hostings = json_loads(self.getURL("https://www.nopremium.pl/clipboard.php?json=3").strip())
- hostings_domains = [domain for row in hostings for domain in row["domains"] if row["sdownload"] == "0"]
-
- self.logDebug(hostings_domains)
-
- return hostings_domains
diff --git a/module/plugins/hooks/OverLoadMe.py b/module/plugins/hooks/OverLoadMe.py
deleted file mode 100644
index b15ce2766..000000000
--- a/module/plugins/hooks/OverLoadMe.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class OverLoadMe(MultiHook):
- __name__ = "OverLoadMe"
- __type__ = "hook"
- __version__ = "0.04"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 ),
- ("ssl" , "bool" , "Use HTTPS" , True )]
-
- __description__ = """Over-Load.me hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("marley", "marley@over-load.me")]
-
-
- def getHosters(self):
- https = "https" if self.getConfig("ssl") else "http"
- html = self.getURL(https + "://api.over-load.me/hoster.php",
- get={'auth': "0001-cb1f24dadb3aa487bda5afd3b76298935329be7700cd7-5329be77-00cf-1ca0135f"}).replace("\"", "").strip()
- self.logDebug("Hosterlist", html)
-
- return [x.strip() for x in html.split(",") if x.strip()]
diff --git a/module/plugins/hooks/PremiumTo.py b/module/plugins/hooks/PremiumTo.py
deleted file mode 100644
index b629b111e..000000000
--- a/module/plugins/hooks/PremiumTo.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class PremiumTo(MultiHook):
- __name__ = "PremiumTo"
- __type__ = "hook"
- __version__ = "0.08"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Premium.to hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("zoidberg", "zoidberg@mujmail.cz"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
- def getHosters(self):
- html = self.getURL("http://premium.to/api/hosters.php",
- get={'username': self.account.username, 'password': self.account.password})
- return [x.strip() for x in html.replace("\"", "").split(";")]
diff --git a/module/plugins/hooks/PremiumizeMe.py b/module/plugins/hooks/PremiumizeMe.py
deleted file mode 100644
index 18b6187c4..000000000
--- a/module/plugins/hooks/PremiumizeMe.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.utils import json_loads
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class PremiumizeMe(MultiHook):
- __name__ = "PremiumizeMe"
- __type__ = "hook"
- __version__ = "0.17"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Premiumize.me hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Florian Franzen", "FlorianFranzen@gmail.com")]
-
-
- def getHosters(self):
- # Get account data
- user, data = self.account.selectAccount()
-
- # Get supported hosters list from premiumize.me using the
- # json API v1 (see https://secure.premiumize.me/?show=api)
- answer = self.getURL("https://api.premiumize.me/pm-api/v1.php",
- get={'method': "hosterlist", 'params[login]': user, 'params[pass]': data['password']})
- data = json_loads(answer)
-
- # If account is not valid thera are no hosters available
- if data['status'] != 200:
- return []
-
- # Extract hosters from json file
- return data['result']['hosterlist']
diff --git a/module/plugins/hooks/PutdriveCom.py b/module/plugins/hooks/PutdriveCom.py
deleted file mode 100644
index f665dabee..000000000
--- a/module/plugins/hooks/PutdriveCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.hooks.ZeveraCom import ZeveraCom
-
-
-class PutdriveCom(ZeveraCom):
- __name__ = "PutdriveCom"
- __type__ = "hook"
- __version__ = "0.01"
-
- __config__ = [("mode" , "all;listed;unlisted", "Use for plugins (if supported)" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed", "bool" , "Revert to standard download if download fails", False),
- ("interval" , "int" , "Reload interval in hours (0 to disable)" , 12 )]
-
- __description__ = """Putdrive.com hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
diff --git a/module/plugins/hooks/RPNetBiz.py b/module/plugins/hooks/RPNetBiz.py
deleted file mode 100644
index 2277b10ab..000000000
--- a/module/plugins/hooks/RPNetBiz.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.utils import json_loads
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class RPNetBiz(MultiHook):
- __name__ = "RPNetBiz"
- __type__ = "hook"
- __version__ = "0.14"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """RPNet.biz hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Dman", "dmanugm@gmail.com")]
-
-
- def getHosters(self):
- # Get account data
- user, data = self.account.selectAccount()
-
- res = self.getURL("https://premium.rpnet.biz/client_api.php",
- get={'username': user, 'password': data['password'], 'action': "showHosterList"})
- hoster_list = json_loads(res)
-
- # If account is not valid thera are no hosters available
- if 'error' in hoster_list:
- return []
-
- # Extract hosters from json file
- return hoster_list['hosters']
diff --git a/module/plugins/hooks/RapideoPl.py b/module/plugins/hooks/RapideoPl.py
deleted file mode 100644
index b605eca17..000000000
--- a/module/plugins/hooks/RapideoPl.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.common.json_layer import json_loads
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class RapideoPl(MultiHook):
- __name__ = "RapideoPl"
- __type__ = "hook"
- __version__ = "0.03"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Rapideo.pl hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("goddie", "dev@rapideo.pl")]
-
-
- def getHosters(self):
- hostings = json_loads(self.getURL("https://www.rapideo.pl/clipboard.php?json=3").strip())
- hostings_domains = [domain for row in hostings for domain in row["domains"] if row["sdownload"] == "0"]
-
- self.logDebug(hostings_domains)
-
- return hostings_domains
diff --git a/module/plugins/hooks/RealdebridCom.py b/module/plugins/hooks/RealdebridCom.py
deleted file mode 100644
index d9c9407dd..000000000
--- a/module/plugins/hooks/RealdebridCom.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class RealdebridCom(MultiHook):
- __name__ = "RealdebridCom"
- __type__ = "hook"
- __version__ = "0.46"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 ),
- ("ssl" , "bool" , "Use HTTPS" , True )]
-
- __description__ = """Real-Debrid.com hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Devirex Hazzard", "naibaf_11@yahoo.de")]
-
-
- def getHosters(self):
- https = "https" if self.getConfig("ssl") else "http"
- html = self.getURL(https + "://real-debrid.com/api/hosters.php").replace("\"", "").strip()
-
- return [x.strip() for x in html.split(",") if x.strip()]
diff --git a/module/plugins/hooks/RehostTo.py b/module/plugins/hooks/RehostTo.py
deleted file mode 100644
index 845601c3f..000000000
--- a/module/plugins/hooks/RehostTo.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class RehostTo(MultiHook):
- __name__ = "RehostTo"
- __type__ = "hook"
- __version__ = "0.50"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Rehost.to hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org")]
-
-
- def getHosters(self):
- user, data = self.account.selectAccount()
- html = self.getURL("http://rehost.to/api.php",
- get={'cmd' : "get_supported_och_dl",
- 'long_ses': self.account.getAccountInfo(user)['session']})
- return [x.strip() for x in html.replace("\"", "").split(",")]
diff --git a/module/plugins/hooks/SimplyPremiumCom.py b/module/plugins/hooks/SimplyPremiumCom.py
deleted file mode 100644
index e51cbd1bc..000000000
--- a/module/plugins/hooks/SimplyPremiumCom.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.utils import json_loads
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class SimplyPremiumCom(MultiHook):
- __name__ = "SimplyPremiumCom"
- __type__ = "hook"
- __version__ = "0.05"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Simply-Premium.com hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("EvolutionClip", "evolutionclip@live.de")]
-
-
- def getHosters(self):
- json_data = self.getURL("http://www.simply-premium.com/api/hosts.php", get={'format': "json", 'online': 1})
- json_data = json_loads(json_data)
-
- host_list = [element['regex'] for element in json_data['result']]
-
- return host_list
diff --git a/module/plugins/hooks/SimplydebridCom.py b/module/plugins/hooks/SimplydebridCom.py
deleted file mode 100644
index 4d27f5ae4..000000000
--- a/module/plugins/hooks/SimplydebridCom.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class SimplydebridCom(MultiHook):
- __name__ = "SimplydebridCom"
- __type__ = "hook"
- __version__ = "0.04"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Simply-Debrid.com hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Kagenoshin", "kagenoshin@gmx.ch")]
-
-
- def getHosters(self):
- html = self.getURL("http://simply-debrid.com/api.php", get={'list': 1})
- return [x.strip() for x in html.rstrip(';').replace("\"", "").split(";")]
diff --git a/module/plugins/hooks/SmoozedCom.py b/module/plugins/hooks/SmoozedCom.py
deleted file mode 100644
index 9ba2daac9..000000000
--- a/module/plugins/hooks/SmoozedCom.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class SmoozedCom(MultiHook):
- __name__ = "SmoozedCom"
- __type__ = "hook"
- __version__ = "0.03"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Smoozed.com hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("", "")]
-
-
- def getHosters(self):
- user, data = self.account.selectAccount()
- return self.account.getAccountInfo(user)["hosters"]
diff --git a/module/plugins/hooks/UnrestrictLi.py b/module/plugins/hooks/UnrestrictLi.py
deleted file mode 100644
index b4c547883..000000000
--- a/module/plugins/hooks/UnrestrictLi.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.utils import json_loads
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class UnrestrictLi(MultiHook):
- __name__ = "UnrestrictLi"
- __type__ = "hook"
- __version__ = "0.05"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 ),
- ("history" , "bool" , "Delete History" , False)]
-
- __description__ = """Unrestrict.li hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- def getHosters(self):
- json_data = self.getURL("http://unrestrict.li/api/jdownloader/hosts.php", get={'format': "json"})
- json_data = json_loads(json_data)
-
- return [element['host'] for element in json_data['result']]
diff --git a/module/plugins/hooks/WindowsPhoneNotify.py b/module/plugins/hooks/WindowsPhoneNotify.py
deleted file mode 100644
index e0dd75f92..000000000
--- a/module/plugins/hooks/WindowsPhoneNotify.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import httplib
-
-from time import time
-
-from module.plugins.Hook import Hook
-
-
-class WindowsPhoneNotify(Hook):
- __name__ = "WindowsPhoneNotify"
- __type__ = "hook"
- __version__ = "0.07"
-
- __config__ = [("id" , "str" , "Push ID" , "" ),
- ("url" , "str" , "Push url" , "" ),
- ("notifycaptcha" , "bool", "Notify captcha request" , True ),
- ("notifypackage" , "bool", "Notify package finished" , True ),
- ("notifyprocessed", "bool", "Notify processed packages status" , True ),
- ("timeout" , "int" , "Timeout between captchas in seconds" , 5 ),
- ("force" , "bool", "Send notifications if client is connected", False)]
-
- __description__ = """Send push notifications to Windows Phone"""
- __license__ = "GPLv3"
- __authors__ = [("Andy Voigt", "phone-support@hotmail.de"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- event_list = ["allDownloadsProcessed"]
-
-
- #@TODO: Remove in 0.4.10
- def initPeriodical(self):
- pass
-
-
- def setup(self):
- self.info = {} #@TODO: Remove in 0.4.10
- self.last_notify = 0
-
-
- def newCaptchaTask(self, task):
- if not self.getConfig("notifycaptcha"):
- return False
-
- if time() - self.last_notify < self.getConf("timeout"):
- return False
-
- self.notify(_("Captcha"), _("New request waiting user input"))
-
-
- def packageFinished(self, pypack):
- if self.getConfig("notifypackage"):
- self.notify(_("Package finished"), pypack.name)
-
-
- def allDownloadsProcessed(self):
- if not self.getConfig("notifyprocessed"):
- return False
-
- if any(True for pdata in self.core.api.getQueue() if pdata.linksdone < pdata.linkstotal):
- self.notify(_("Package failed"), _("One or more packages was not completed successfully"))
- else:
- self.notify(_("All packages finished"))
-
-
- def getXmlData(self, msg):
- return ("<?xml version='1.0' encoding='utf-8'?> <wp:Notification xmlns:wp='WPNotification'> "
- "<wp:Toast> <wp:Text1>pyLoad</wp:Text1> <wp:Text2>%s</wp:Text2> "
- "</wp:Toast> </wp:Notification>" % msg)
-
-
- def notify(self, event, msg=""):
- id = self.getConfig("id")
- url = self.getConfig("url")
-
- if not id or not url:
- return False
-
- if self.core.isClientConnected() and not self.getConfig("force"):
- return False
-
- request = self.getXmlData("%s: %s" % (event, msg) if msg else event)
- webservice = httplib.HTTP(url)
-
- webservice.putrequest("POST", id)
- webservice.putheader("Host", url)
- webservice.putheader("Content-type", "text/xml")
- webservice.putheader("X-NotificationClass", "2")
- webservice.putheader("X-WindowsPhone-Target", "toast")
- webservice.putheader("Content-length", "%d" % len(request))
- webservice.endheaders()
- webservice.send(request)
- webservice.close()
-
- self.last_notify = time()
diff --git a/module/plugins/hooks/XFileSharingPro.py b/module/plugins/hooks/XFileSharingPro.py
deleted file mode 100644
index 78e14c179..000000000
--- a/module/plugins/hooks/XFileSharingPro.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.Addon import Addon
-
-
-class XFileSharingPro(Addon):
- __name__ = "XFileSharingPro"
- __type__ = "hook"
- __version__ = "0.31"
-
- __config__ = [("activated" , "bool", "Activated" , True ),
- ("use_hoster_list" , "bool", "Load listed hosters only" , False),
- ("use_crypter_list", "bool", "Load listed crypters only" , False),
- ("use_builtin_list", "bool", "Load built-in plugin list" , True ),
- ("hoster_list" , "str" , "Hoster list (comma separated)" , "" ),
- ("crypter_list" , "str" , "Crypter list (comma separated)", "" )]
-
- __description__ = """Load XFileSharingPro based hosters and crypter which don't need a own plugin to run"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- # event_list = ["pluginConfigChanged"]
- regexp = {'hoster' : (r'https?://(?:www\.)?(?P<DOMAIN>[\w.^_]+(?:\.[a-zA-Z]{2,})(?:\:\d+)?)/(?:embed-)?\w{12}(?:\W|$)',
- r'https?://(?:[^/]+\.)?(?P<DOMAIN>%s)/(?:embed-)?\w+'),
- 'crypter': (r'https?://(?:www\.)?(?P<DOMAIN>[\w.^_]+(?:\.[a-zA-Z]{2,})(?:\:\d+)?)/(?:user|folder)s?/\w+',
- r'https?://(?:[^/]+\.)?(?P<DOMAIN>%s)/(?:user|folder)s?/\w+')}
-
- HOSTER_BUILTIN = [#WORKING HOSTERS:
- "180upload.com", "backin.net", "eyesfile.ca", "file4safe.com", "fileband.com", "filedwon.com",
- "fileparadox.in", "filevice.com", "hostingbulk.com", "junkyvideo.com", "linestorage.com", "ravishare.com",
- "ryushare.com", "salefiles.com", "sendmyway.com", "sharesix.com", "thefile.me", "verzend.be", "xvidstage.com",
- #NOT TESTED:
- "101shared.com", "4upfiles.com", "filemaze.ws", "filenuke.com", "linkzhost.com", "mightyupload.com",
- "rockdizfile.com", "sharebeast.com", "sharerepo.com", "shareswift.com", "uploadbaz.com", "uploadc.com",
- "vidbull.com", "zalaa.com", "zomgupload.com",
- #NOT WORKING:
- "amonshare.com", "banicrazy.info", "boosterking.com", "host4desi.com", "laoupload.com", "rd-fs.com"]
- CRYPTER_BUILTIN = ["junocloud.me", "rapidfileshare.net"]
-
-
- # def pluginConfigChanged(self.__name__, plugin, name, value):
- # self.loadPattern()
-
-
- def activate(self):
- self.loadPattern()
-
-
- def loadPattern(self):
- use_builtin_list = self.getConfig('use_builtin_list')
-
- for type in ("hoster", "crypter"):
- every_plugin = not self.getConfig("use_%s_list" % type)
-
- if every_plugin:
- self.logInfo(_("Handling any %s I can!") % type)
- pattern = self.regexp[type][0]
- else:
- plugins = self.getConfig('%s_list' % type)
- plugin_set = set(plugins.replace(' ', '').replace('\\', '').replace('|', ',').replace(';', ',').lower().split(','))
-
- if use_builtin_list:
- plugin_set |= set(x.lower() for x in getattr(self, "%s_BUILTIN" % type.upper()))
-
- plugin_set -= set(('', u''))
-
- if not plugin_set:
- self.logInfo(_("No %s to handle") % type)
- self._unload(type)
- return
-
- match_list = '|'.join(sorted(plugin_set))
-
- len_match_list = len(plugin_set)
- self.logInfo(_("Handling %d %s%s: %s") % (len_match_list,
- type,
- "" if len_match_list == 1 else "s",
- match_list.replace('|', ', ')))
-
- pattern = self.regexp[type][1] % match_list.replace('.', '\.')
-
- dict = self.core.pluginManager.plugins[type]["XFileSharingPro"]
- dict['pattern'] = pattern
- dict['re'] = re.compile(pattern)
-
- self.logDebug("Loaded %s pattern: %s" % (type, pattern))
-
-
- def _unload(self, type):
- dict = self.core.pluginManager.plugins[type]["XFileSharingPro"]
- dict['pattern'] = r'^unmatchable$'
- dict['re'] = re.compile(dict['pattern'])
-
-
- def deactivate(self):
- # self.unloadHoster("BasePlugin")
- for type in ("hoster", "crypter"):
- self._unload(type, "XFileSharingPro")
-
-
- # def downloadFailed(self, pyfile):
- # if pyfile.pluginname == "BasePlugin" \
- # and pyfile.hasStatus("failed") \
- # and not self.getConfig("use_hoster_list") \
- # and self.unloadHoster("BasePlugin"):
- # self.logDebug("Unloaded XFileSharingPro from BasePlugin")
- # pyfile.setStatus("queued")
diff --git a/module/plugins/hooks/ZeveraCom.py b/module/plugins/hooks/ZeveraCom.py
deleted file mode 100644
index 215ec3673..000000000
--- a/module/plugins/hooks/ZeveraCom.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.MultiHook import MultiHook
-
-
-class ZeveraCom(MultiHook):
- __name__ = "ZeveraCom"
- __type__ = "hook"
- __version__ = "0.05"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Zevera.com hook plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- def getHosters(self):
- html = self.account.api_response(pyreq.getHTTPRequest(timeout=120), cmd="gethosters")
- return [x.strip() for x in html.split(",")]
diff --git a/module/plugins/hoster/AlldebridCom.py b/module/plugins/hoster/AlldebridCom.py
deleted file mode 100644
index 427eb42f0..000000000
--- a/module/plugins/hoster/AlldebridCom.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from random import randrange
-from urllib import unquote
-
-from module.common.json_layer import json_loads
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-from module.utils import parseFileSize
-
-
-class AlldebridCom(MultiHoster):
- __name__ = "AlldebridCom"
- __type__ = "hoster"
- __version__ = "0.44"
-
- __pattern__ = r'https?://(?:www\.|s\d+\.)?alldebrid\.com/dl/[\w^_]+'
-
- __description__ = """Alldebrid.com multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Andy Voigt", "spamsales@online.de")]
-
-
- def getFilename(self, url):
- try:
- name = unquote(url.rsplit("/", 1)[1])
- except IndexError:
- name = "Unknown_Filename..."
-
- if name.endswith("..."): # incomplete filename, append random stuff
- name += "%s.tmp" % randrange(100, 999)
-
- return name
-
-
- def setup(self):
- self.chunkLimit = 16
-
-
- def handlePremium(self, pyfile):
- password = self.getPassword()
-
- data = json_loads(self.load("http://www.alldebrid.com/service.php",
- get={'link': pyfile.url, 'json': "true", 'pw': password}))
-
- self.logDebug("Json data", data)
-
- if data['error']:
- if data['error'] == "This link isn't available on the hoster website.":
- self.offline()
- else:
- self.logWarning(data['error'])
- self.tempOffline()
- else:
- if pyfile.name and not pyfile.name.endswith('.tmp'):
- pyfile.name = data['filename']
- pyfile.size = parseFileSize(data['filesize'])
- self.link = data['link']
-
- if self.getConfig("ssl"):
- self.link = self.link.replace("http://", "https://")
- else:
- self.link = self.link.replace("https://", "http://")
-
- if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown"):
- #only use when name wasnt already set
- pyfile.name = self.getFilename(self.link)
-
-
- def checkFile(self):
- if self.checkDownload({'error': "<title>An error occured while processing your request</title>"}) == "error":
- self.retry(wait_time=60, reason=_("An error occured while generating link"))
-
- return super(AlldebridCom, self).checkFile()
-
-
-getInfo = create_getInfo(AlldebridCom)
diff --git a/module/plugins/hoster/AndroidfilehostCom.py b/module/plugins/hoster/AndroidfilehostCom.py
deleted file mode 100644
index b6e43d632..000000000
--- a/module/plugins/hoster/AndroidfilehostCom.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# -*- coding: utf-8 -*
-#
-# Test links:
-# https://www.androidfilehost.com/?fid=95916177934518197
-
-import re
-
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class AndroidfilehostCom(SimpleHoster):
- __name__ = "AndroidfilehostCom"
- __type__ = "hoster"
- __version__ = "0.01"
-
- __pattern__ = r'https?://(?:www\.)?androidfilehost\.com/\?fid=\d+'
-
- __description__ = """Androidfilehost.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
-
-
- NAME_PATTERN = r'<br />(?P<N>.*?)</h1>'
- SIZE_PATTERN = r'<h4>size</h4>\s*<p>(?P<S>[\d.,]+)(?P<U>[\w^_]+)</p>'
- HASHSUM_PATTERN = r'<h4>(?P<T>.*?)</h4>\s*<p><code>(?P<H>.*?)</code></p>'
-
- OFFLINE_PATTERN = r'404 not found'
-
- WAIT_PATTERN = r'users must wait <strong>(\d+) secs'
-
-
- def setup(self):
- self.multiDL = True
- self.resumeDownload = True
- self.chunkLimit = 1
-
-
- def handleFree(self, pyfile):
- wait = re.search(self.WAIT_PATTERN, self.html)
- self.logDebug("Waiting time: %s seconds" % wait.group(1))
-
- fid = re.search(r'id="fid" value="(\d+)" />', self.html).group(1)
- self.logDebug("fid: %s" % fid)
-
- html = self.load("https://www.androidfilehost.com/libs/otf/mirrors.otf.php",
- post={'submit': 'submit',
- 'action': 'getdownloadmirrors',
- 'fid' : fid},
- decode=True)
-
- self.link = re.findall('"url":"(.*?)"', html)[0].replace("\\", "")
- mirror_host = self.link.split("/")[2]
-
- self.logDebug("Mirror Host: %s" % mirror_host)
-
- html = self.load("https://www.androidfilehost.com/libs/otf/stats.otf.php",
- get={'fid' : fid,
- 'w' : 'download',
- 'mirror': mirror_host},
- decode=True)
-
-
-getInfo = create_getInfo(AndroidfilehostCom)
diff --git a/module/plugins/hoster/BasketbuildCom.py b/module/plugins/hoster/BasketbuildCom.py
deleted file mode 100644
index db482c7c5..000000000
--- a/module/plugins/hoster/BasketbuildCom.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# -*- coding: utf-8 -*
-#
-# Test links:
-# https://s.basketbuild.com/filedl/devs?dev=pacman&dl=pacman/falcon/RC-3/pac_falcon-RC-3-20141103.zip
-# https://s.basketbuild.com/filedl/gapps?dl=gapps-gb-20110828-signed.zip
-
-import re
-
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class BasketbuildCom(SimpleHoster):
- __name__ = "BasketbuildCom"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'https?://(?:www\.)?(?:\w\.)?basketbuild\.com/filedl/.+'
-
- __description__ = """basketbuild.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
-
-
- NAME_PATTERN = r'File Name:</strong> (?P<N>.+?)<br/>'
- SIZE_PATTERN = r'File Size:</strong> (?P<S>[\d.,]+) (?P<U>[\w^_]+)'
- OFFLINE_PATTERN = r'404 - Page Not Found'
-
-
- def setup(self):
- self.multiDL = True
- self.resumeDownload = True
- self.chunkLimit = 1
-
-
- def handleFree(self, pyfile):
- try:
- link1 = re.search(r'href="(.+dlgate/.+)"', self.html).group(1)
- self.html = self.load(link1)
-
- except AttributeError:
- self.error(_("Hop #1 not found"))
-
- else:
- self.logDebug("Next hop: %s" % link1)
-
- try:
- wait = re.search(r'var sec = (\d+)', self.html).group(1)
- self.logDebug("Wait %s seconds" % wait)
- self.wait(wait)
-
- except AttributeError:
- self.logDebug("No wait time found")
-
- try:
- self.link = re.search(r'id="dlLink">\s*<a href="(.+?)"', self.html).group(1)
-
- except AttributeError:
- self.error(_("DL-Link not found"))
-
-
-getInfo = create_getInfo(BasketbuildCom)
diff --git a/module/plugins/hoster/BayfilesCom.py b/module/plugins/hoster/BayfilesCom.py
deleted file mode 100644
index 0929ece01..000000000
--- a/module/plugins/hoster/BayfilesCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class BayfilesCom(DeadHoster):
- __name__ = "BayfilesCom"
- __type__ = "hoster"
- __version__ = "0.09"
-
- __pattern__ = r'https?://(?:www\.)?bayfiles\.(com|net)/file/(?P<ID>\w+/\w+/[^/]+)'
-
- __description__ = """Bayfiles.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
-getInfo = create_getInfo(BayfilesCom)
diff --git a/module/plugins/hoster/BezvadataCz.py b/module/plugins/hoster/BezvadataCz.py
deleted file mode 100644
index 86ef46cc3..000000000
--- a/module/plugins/hoster/BezvadataCz.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class BezvadataCz(SimpleHoster):
- __name__ = "BezvadataCz"
- __type__ = "hoster"
- __version__ = "0.26"
-
- __pattern__ = r'http://(?:www\.)?bezvadata\.cz/stahnout/.+'
-
- __description__ = """BezvaData.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<p><b>Soubor: (?P<N>[^<]+)</b></p>'
- SIZE_PATTERN = r'<li><strong>Velikost:</strong> (?P<S>[^<]+)</li>'
- OFFLINE_PATTERN = r'<title>BezvaData \| Soubor nenalezen</title>'
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = True
-
-
- def handleFree(self, pyfile):
- #download button
- m = re.search(r'<a class="stahnoutSoubor".*?href="(.*?)"', self.html)
- if m is None:
- self.error(_("Page 1 URL not found"))
- url = "http://bezvadata.cz%s" % m.group(1)
-
- #captcha form
- self.html = self.load(url)
- self.checkErrors()
- for _i in xrange(5):
- action, inputs = self.parseHtmlForm('frm-stahnoutFreeForm')
- if not inputs:
- self.error(_("FreeForm"))
-
- m = re.search(r'<img src="data:image/png;base64,(.*?)"', self.html)
- if m is None:
- self.error(_("Wrong captcha image"))
-
- #captcha image is contained in html page as base64encoded data but decryptCaptcha() expects image url
- self.load, proper_load = self.loadcaptcha, self.load
- try:
- inputs['captcha'] = self.decryptCaptcha(m.group(1), imgtype='png')
- finally:
- self.load = proper_load
-
- if '<img src="data:image/png;base64' in self.html:
- self.invalidCaptcha()
- else:
- self.correctCaptcha()
- break
- else:
- self.fail(_("No valid captcha code entered"))
-
- #download url
- self.html = self.load("http://bezvadata.cz%s" % action, post=inputs)
- self.checkErrors()
- m = re.search(r'<a class="stahnoutSoubor2" href="(.*?)">', self.html)
- if m is None:
- self.error(_("Page 2 URL not found"))
- url = "http://bezvadata.cz%s" % m.group(1)
- self.logDebug("DL URL %s" % url)
-
- #countdown
- m = re.search(r'id="countdown">(\d\d):(\d\d)<', self.html)
- wait_time = (int(m.group(1)) * 60 + int(m.group(2))) if m else 120
- self.wait(wait_time, False)
-
- self.download(url)
-
-
- def checkErrors(self):
- if 'images/button-download-disable.png' in self.html:
- self.longWait(5 * 60, 24) #: parallel dl limit
- elif '<div class="infobox' in self.html:
- self.tempOffline()
-
- self.info.pop('error', None)
-
-
- def loadcaptcha(self, data, *args, **kwargs):
- return data.decode('base64')
-
-
-getInfo = create_getInfo(BezvadataCz)
diff --git a/module/plugins/hoster/BillionuploadsCom.py b/module/plugins/hoster/BillionuploadsCom.py
deleted file mode 100644
index fb79fe29a..000000000
--- a/module/plugins/hoster/BillionuploadsCom.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class BillionuploadsCom(XFSHoster):
- __name__ = "BillionuploadsCom"
- __type__ = "hoster"
- __version__ = "0.04"
-
- __pattern__ = r'http://(?:www\.)?billionuploads\.com/\w{12}'
-
- __description__ = """Billionuploads.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<td class="dofir" title="(?P<N>.+?)"'
- SIZE_PATTERN = r'<td class="dofir">(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
-
-
-getInfo = create_getInfo(BillionuploadsCom)
diff --git a/module/plugins/hoster/BitshareCom.py b/module/plugins/hoster/BitshareCom.py
deleted file mode 100644
index feb2b682c..000000000
--- a/module/plugins/hoster/BitshareCom.py
+++ /dev/null
@@ -1,158 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import re
-
-from pyload.plugin.internal.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class BitshareCom(SimpleHoster):
- __name__ = "BitshareCom"
- __type__ = "hoster"
- __version__ = "0.53"
-
- __pattern__ = r'http://(?:www\.)?bitshare\.com/(files/)?(?(1)|\?f=)(?P<ID>\w+)(?(1)/(?P<NAME>.+?)\.html)'
-
- __description__ = """Bitshare.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Paul King", ""),
- ("fragonib", "fragonib[AT]yahoo[DOT]es")]
-
-
- COOKIES = [("bitshare.com", "language_selection", "EN")]
-
- INFO_PATTERN = r'Downloading (?P<N>.+) - (?P<S>[\d.,]+) (?P<U>[\w^_]+)</h1>'
- OFFLINE_PATTERN = r'[Ff]ile (not available|was deleted|was not found)'
-
- AJAXID_PATTERN = r'var ajaxdl = "(.*?)";'
- TRAFFIC_USED_UP = r'Your Traffic is used up for today'
-
-
- def setup(self):
- self.multiDL = self.premium
- self.chunkLimit = 1
-
-
- def process(self, pyfile):
- if self.premium:
- self.account.relogin(self.user)
-
- # File id
- m = re.match(self.__pattern__, pyfile.url)
- self.file_id = max(m.group('ID1'), m.group('ID2'))
- self.logDebug("File id is [%s]" % self.file_id)
-
- # Load main page
- self.html = self.load(pyfile.url, ref=False, decode=True)
-
- # Check offline
- if re.search(self.OFFLINE_PATTERN, self.html):
- self.offline()
-
- # Check Traffic used up
- if re.search(self.TRAFFIC_USED_UP, self.html):
- self.logInfo(_("Your Traffic is used up for today"))
- self.wait(30 * 60, True)
- self.retry()
-
- # File name
- m = re.match(self.__pattern__, pyfile.url)
- name1 = m.group('NAME') if m else None
-
- m = re.search(self.INFO_PATTERN, self.html)
- name2 = m.group('N') if m else None
-
- pyfile.name = max(name1, name2)
-
- # Ajax file id
- self.ajaxid = re.search(self.AJAXID_PATTERN, self.html).group(1)
- self.logDebug("File ajax id is [%s]" % self.ajaxid)
-
- # This may either download our file or forward us to an error page
- self.download(self.getDownloadUrl())
-
- if self.checkDownload({"error": ">Error occured<"}):
- self.retry(5, 5 * 60, "Bitshare host : Error occured")
-
-
- def getDownloadUrl(self):
- # Return location if direct download is active
- if self.premium:
- header = self.load(self.pyfile.url, cookies=True, just_header=True)
- if 'location' in header:
- return header['location']
-
- # Get download info
- self.logDebug("Getting download info")
- res = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html",
- post={"request": "generateID", "ajaxid": self.ajaxid})
-
- self.handleErrors(res, ':')
-
- parts = res.split(":")
- filetype = parts[0]
- wait = int(parts[1])
- captcha = int(parts[2])
-
- self.logDebug("Download info [type: '%s', waiting: %d, captcha: %d]" % (filetype, wait, captcha))
-
- # Waiting
- if wait > 0:
- self.logDebug("Waiting %d seconds." % wait)
- if wait < 120:
- self.wait(wait, False)
- else:
- self.wait(wait - 55, True)
- self.retry()
-
- # Resolve captcha
- if captcha == 1:
- self.logDebug("File is captcha protected")
- recaptcha = ReCaptcha(self)
-
- # Try up to 3 times
- for i in xrange(3):
- response, challenge = recaptcha.challenge()
- res = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html",
- post={"request" : "validateCaptcha",
- "ajaxid" : self.ajaxid,
- "recaptcha_challenge_field": challenge,
- "recaptcha_response_field" : response})
- if self.handleCaptchaErrors(res):
- break
-
- # Get download URL
- self.logDebug("Getting download url")
- res = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html",
- post={"request": "getDownloadURL", "ajaxid": self.ajaxid})
-
- self.handleErrors(res, '#')
-
- url = res.split("#")[-1]
-
- return url
-
-
- def handleErrors(self, res, separator):
- self.logDebug("Checking response [%s]" % res)
- if "ERROR:Session timed out" in res:
- self.retry()
- elif "ERROR" in res:
- msg = res.split(separator)[-1]
- self.fail(msg)
-
-
- def handleCaptchaErrors(self, res):
- self.logDebug("Result of captcha resolving [%s]" % res)
- if "SUCCESS" in res:
- self.correctCaptcha()
- return True
- elif "ERROR:SESSION ERROR" in res:
- self.retry()
-
- self.invalidCaptcha()
-
-
-getInfo = create_getInfo(BitshareCom)
diff --git a/module/plugins/hoster/BoltsharingCom.py b/module/plugins/hoster/BoltsharingCom.py
deleted file mode 100644
index 93f6d619a..000000000
--- a/module/plugins/hoster/BoltsharingCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class BoltsharingCom(DeadHoster):
- __name__ = "BoltsharingCom"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?boltsharing\.com/\w{12}'
-
- __description__ = """Boltsharing.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(BoltsharingCom)
diff --git a/module/plugins/hoster/CatShareNet.py b/module/plugins/hoster/CatShareNet.py
deleted file mode 100644
index d61856b7c..000000000
--- a/module/plugins/hoster/CatShareNet.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class CatShareNet(SimpleHoster):
- __name__ = "CatShareNet"
- __type__ = "hoster"
- __version__ = "0.11"
-
- __pattern__ = r'http://(?:www\.)?catshare\.net/\w{16}'
-
- __description__ = """CatShare.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("z00nx", "z00nx0@gmail.com"),
- ("prOq", ""),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- TEXT_ENCODING = True
-
- INFO_PATTERN = r'<title>(?P<N>.+) \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)<'
- OFFLINE_PATTERN = ur'Podany plik został usunięty\s*</div>'
-
- IP_BLOCKED_PATTERN = ur'>Nasz serwis wykrył ÅŒe Twój adres IP nie pochodzi z Polski.<'
- WAIT_PATTERN = r'var\scount\s=\s(\d+);'
-
- LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'<form action="(.+?)" method="GET">'
-
-
- def setup(self):
- self.multiDL = self.premium
- self.resumeDownload = True
-
-
- def getFileInfo(self):
- m = re.search(self.IP_BLOCKED_PATTERN, self.html)
- if m:
- self.fail(_("Only connections from Polish IP address are allowed"))
- return super(CatShareNet, self).getFileInfo()
-
-
- def handleFree(self, pyfile):
- recaptcha = ReCaptcha(self)
-
- response, challenge = recaptcha.challenge()
- self.html = self.load(pyfile.url,
- post={'recaptcha_challenge_field': challenge,
- 'recaptcha_response_field' : response})
-
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.invalidCaptcha()
- self.retry(reason=_("Wrong captcha entered"))
-
- self.link = m.group(1)
-
-
-getInfo = create_getInfo(CatShareNet)
diff --git a/module/plugins/hoster/CloudzerNet.py b/module/plugins/hoster/CloudzerNet.py
deleted file mode 100644
index cb764e335..000000000
--- a/module/plugins/hoster/CloudzerNet.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class CloudzerNet(DeadHoster):
- __name__ = "CloudzerNet"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'https?://(?:www\.)?(cloudzer\.net/file/|clz\.to/(file/)?)\w+'
-
- __description__ = """Cloudzer.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("gs", "I-_-I-_-I@web.de"),
- ("z00nx", "z00nx0@gmail.com"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
-getInfo = create_getInfo(CloudzerNet)
diff --git a/module/plugins/hoster/CloudzillaTo.py b/module/plugins/hoster/CloudzillaTo.py
deleted file mode 100644
index ee966c280..000000000
--- a/module/plugins/hoster/CloudzillaTo.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class CloudzillaTo(SimpleHoster):
- __name__ = "CloudzillaTo"
- __type__ = "hoster"
- __version__ = "0.06"
-
- __pattern__ = r'http://(?:www\.)?cloudzilla\.to/share/file/(?P<ID>[\w^_]+)'
-
- __description__ = """Cloudzilla.to hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- INFO_PATTERN = r'title="(?P<N>.+?)">\1</span> <span class="size">\((?P<S>[\d.]+) (?P<U>[\w^_]+)'
- OFFLINE_PATTERN = r'>File not found...<'
-
- PASSWORD_PATTERN = r'<div id="pwd_protected">'
-
-
- def checkErrors(self):
- m = re.search(self.PASSWORD_PATTERN, self.html)
- if m:
- self.html = self.load(self.pyfile.url, get={'key': self.getPassword()})
-
- if re.search(self.PASSWORD_PATTERN, self.html):
- self.retry(reason="Wrong password")
-
-
- def handleFree(self, pyfile):
- self.html = self.load("http://www.cloudzilla.to/generateticket/",
- post={'file_id': self.info['pattern']['ID'], 'key': self.getPassword()})
-
- ticket = dict(re.findall(r'<(.+?)>([^<>]+?)</', self.html))
-
- self.logDebug(ticket)
-
- if 'error' in ticket:
- if "File is password protected" in ticket['error']:
- self.retry(reason="Wrong password")
- else:
- self.fail(ticket['error'])
-
- if 'wait' in ticket:
- self.wait(ticket['wait'], int(ticket['wait']) > 5)
-
- self.link = "http://%(server)s/download/%(file_id)s/%(ticket_id)s" % {'server' : ticket['server'],
- 'file_id' : self.info['pattern']['ID'],
- 'ticket_id': ticket['ticket_id']}
-
-
- def handlePremium(self, pyfile):
- return self.handleFree(pyfile)
-
-
-getInfo = create_getInfo(CloudzillaTo)
diff --git a/module/plugins/hoster/CramitIn.py b/module/plugins/hoster/CramitIn.py
deleted file mode 100644
index 8e239cdc5..000000000
--- a/module/plugins/hoster/CramitIn.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class CramitIn(XFSHoster):
- __name__ = "CramitIn"
- __type__ = "hoster"
- __version__ = "0.07"
-
- __pattern__ = r'http://(?:www\.)?cramit\.in/\w{12}'
-
- __description__ = """Cramit.in hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- INFO_PATTERN = r'<span class=t2>\s*(?P<N>.*?)</span>.*?<small>\s*\((?P<S>.*?)\)'
-
- LINK_PATTERN = r'href="(http://cramit\.in/file_download/.*?)"'
-
-
-getInfo = create_getInfo(CramitIn)
diff --git a/module/plugins/hoster/CrockoCom.py b/module/plugins/hoster/CrockoCom.py
deleted file mode 100644
index a2abc2b7b..000000000
--- a/module/plugins/hoster/CrockoCom.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class CrockoCom(SimpleHoster):
- __name__ = "CrockoCom"
- __type__ = "hoster"
- __version__ = "0.19"
-
- __pattern__ = r'http://(?:www\.)?(crocko|easy-share)\.com/\w+'
-
- __description__ = """Crocko hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<span class="fz24">Download:\s*<strong>(?P<N>.*)'
- SIZE_PATTERN = r'<span class="tip1"><span class="inner">(?P<S>[^<]+)</span></span>'
- OFFLINE_PATTERN = r'<h1>Sorry,<br />the page you\'re looking for <br />isn\'t here.</h1>|File not found'
-
- CAPTCHA_PATTERN = re.compile(r"u='(/file_contents/captcha/\w+)';\s*w='(\d+)';")
-
- FORM_PATTERN = r'<form method="post" action="([^"]+)">(.*?)</form>'
- FORM_INPUT_PATTERN = r'<input[^>]* name="?([^" ]+)"? value="?([^" ]+)"?[^>]*>'
-
- NAME_REPLACEMENTS = [(r'<[^>]*>', '')]
-
-
- def handleFree(self, pyfile):
- if "You need Premium membership to download this file." in self.html:
- self.fail(_("You need Premium membership to download this file"))
-
- for _i in xrange(5):
- m = re.search(self.CAPTCHA_PATTERN, self.html)
- if m:
- url, wait_time = 'http://crocko.com' + m.group(1), int(m.group(2))
- self.wait(wait_time)
- self.html = self.load(url)
- else:
- break
-
- m = re.search(self.FORM_PATTERN, self.html, re.S)
- if m is None:
- self.error(_("FORM_PATTERN not found"))
-
- action, form = m.groups()
- inputs = dict(re.findall(self.FORM_INPUT_PATTERN, form))
- recaptcha = ReCaptcha(self)
-
- for _i in xrange(5):
- inputs['recaptcha_response_field'], inputs['recaptcha_challenge_field'] = recaptcha.challenge()
- self.download(action, post=inputs)
-
- if self.checkDownload({"captcha": recaptcha.KEY_AJAX_PATTERN}):
- self.invalidCaptcha()
- else:
- break
- else:
- self.fail(_("No valid captcha solution received"))
-
-
-getInfo = create_getInfo(CrockoCom)
diff --git a/module/plugins/hoster/CyberlockerCh.py b/module/plugins/hoster/CyberlockerCh.py
deleted file mode 100644
index 1c6a04caf..000000000
--- a/module/plugins/hoster/CyberlockerCh.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class CyberlockerCh(DeadHoster):
- __name__ = "CyberlockerCh"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?cyberlocker\.ch/\w+'
-
- __description__ = """Cyberlocker.ch hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
-getInfo = create_getInfo(CyberlockerCh)
diff --git a/module/plugins/hoster/CzshareCom.py b/module/plugins/hoster/CzshareCom.py
deleted file mode 100644
index 419e43a7a..000000000
--- a/module/plugins/hoster/CzshareCom.py
+++ /dev/null
@@ -1,161 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# http://czshare.com/5278880/random.bin
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-from pyload.utils import parseFileSize
-
-
-class CzshareCom(SimpleHoster):
- __name__ = "CzshareCom"
- __type__ = "hoster"
- __version__ = "0.98"
-
- __pattern__ = r'http://(?:www\.)?(czshare|sdilej)\.(com|cz)/(\d+/|download\.php\?).+'
-
- __description__ = """CZshare.com hoster plugin, now Sdilej.cz"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<div class="tab" id="parameters">\s*<p>\s*Cel. n.zev: <a href=[^>]*>(?P<N>[^<]+)</a>'
- SIZE_PATTERN = r'<div class="tab" id="category">(?:\s*<p>[^\n]*</p>)*\s*Velikost:\s*(?P<S>[\d .,]+)(?P<U>[\w^_]+)\s*</div>'
- OFFLINE_PATTERN = r'<div class="header clearfix">\s*<h2 class="red">'
-
- SIZE_REPLACEMENTS = [(' ', '')]
- URL_REPLACEMENTS = [(r'http://[^/]*/download.php\?.*?id=(\w+).*', r'http://sdilej.cz/\1/x/')]
-
- CHECK_TRAFFIC = True
-
- FREE_URL_PATTERN = r'<a href="([^"]+)" class="page-download">[^>]*alt="([^"]+)" /></a>'
- FREE_FORM_PATTERN = r'<form action="download\.php" method="post">\s*<img src="captcha\.php" id="captcha" />(.*?)</form>'
- PREMIUM_FORM_PATTERN = r'<form action="/profi_down\.php" method="post">(.*?)</form>'
- FORM_INPUT_PATTERN = r'<input[^>]* name="([^"]+)" value="([^"]+)"[^>]*/>'
- MULTIDL_PATTERN = r'<p><font color=\'red\'>Z[^<]*PROFI.</font></p>'
- USER_CREDIT_PATTERN = r'<div class="credit">\s*kredit: <strong>([\d .,]+)(\w+)</strong>\s*</div><!-- .credit -->'
-
-
- def checkTrafficLeft(self):
- # check if user logged in
- m = re.search(self.USER_CREDIT_PATTERN, self.html)
- if m is None:
- self.account.relogin(self.user)
- self.html = self.load(self.pyfile.url, cookies=True, decode=True)
- m = re.search(self.USER_CREDIT_PATTERN, self.html)
- if m is None:
- return False
-
- # check user credit
- try:
- credit = parseFileSize(m.group(1).replace(' ', ''), m.group(2))
- self.logInfo(_("Premium download for %i KiB of Credit") % (self.pyfile.size / 1024))
- self.logInfo(_("User %s has %i KiB left") % (self.user, credit / 1024))
- if credit < self.pyfile.size:
- self.logInfo(_("Not enough credit to download file: %s") % self.pyfile.name)
- return False
- except Exception, e:
- # let's continue and see what happens...
- self.logError(e)
-
- return True
-
-
- def handlePremium(self, pyfile):
- # parse download link
- try:
- form = re.search(self.PREMIUM_FORM_PATTERN, self.html, re.S).group(1)
- inputs = dict(re.findall(self.FORM_INPUT_PATTERN, form))
- except Exception, e:
- self.logError(e)
- self.resetAccount()
-
- # download the file, destination is determined by pyLoad
- self.download("http://sdilej.cz/profi_down.php", post=inputs, disposition=True)
-
-
- def handleFree(self, pyfile):
- # get free url
- m = re.search(self.FREE_URL_PATTERN, self.html)
- if m is None:
- self.error(_("FREE_URL_PATTERN not found"))
-
- parsed_url = "http://sdilej.cz" + m.group(1)
-
- self.logDebug("PARSED_URL:" + parsed_url)
-
- # get download ticket and parse html
- self.html = self.load(parsed_url, cookies=True, decode=True)
- if re.search(self.MULTIDL_PATTERN, self.html):
- self.longWait(5 * 60, 12)
-
- try:
- form = re.search(self.FREE_FORM_PATTERN, self.html, re.S).group(1)
- inputs = dict(re.findall(self.FORM_INPUT_PATTERN, form))
- pyfile.size = int(inputs['size'])
-
- except Exception, e:
- self.logError(e)
- self.error(_("Form"))
-
- # get and decrypt captcha
- captcha_url = 'http://sdilej.cz/captcha.php'
- for _i in xrange(5):
- inputs['captchastring2'] = self.decryptCaptcha(captcha_url)
- self.html = self.load(parsed_url, cookies=True, post=inputs, decode=True)
-
- if u"<li>ZadanÃœ ověřovací kód nesouhlasí!</li>" in self.html:
- self.invalidCaptcha()
-
- elif re.search(self.MULTIDL_PATTERN, self.html):
- self.longWait(5 * 60, 12)
-
- else:
- self.correctCaptcha()
- break
- else:
- self.fail(_("No valid captcha code entered"))
-
- m = re.search("countdown_number = (\d+);", self.html)
- self.setWait(int(m.group(1)) if m else 50)
-
- # download the file, destination is determined by pyLoad
- self.logDebug("WAIT URL", self.req.lastEffectiveURL)
-
- m = re.search("free_wait.php\?server=(.*?)&(.*)", self.req.lastEffectiveURL)
- if m is None:
- self.error(_("Download URL not found"))
-
- self.link = "http://%s/download.php?%s" % (m.group(1), m.group(2))
-
- self.wait()
-
-
- def checkFile(self):
- # check download
- check = self.checkDownload({
- "temp offline" : re.compile(r"^Soubor je do.*asn.* nedostupn.*$"),
- "credit" : re.compile(r"^Nem.*te dostate.*n.* kredit.$"),
- "multi-dl" : re.compile(self.MULTIDL_PATTERN),
- "captcha" : "<li>ZadanÃœ ověřovací kód nesouhlasí!</li>"
- })
-
- if check == "temp offline":
- self.fail(_("File not available - try later"))
-
- elif check == "credit":
- self.resetAccount()
-
- elif check == "multi-dl":
- self.longWait(5 * 60, 12)
-
- elif check == "captcha":
- self.invalidCaptcha()
- self.retry()
-
- return super(CzshareCom, self).checkFile()
-
-
-getInfo = create_getInfo(CzshareCom)
diff --git a/module/plugins/hoster/DataHu.py b/module/plugins/hoster/DataHu.py
deleted file mode 100644
index f24b5cdba..000000000
--- a/module/plugins/hoster/DataHu.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# http://data.hu/get/6381232/random.bin
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class DataHu(SimpleHoster):
- __name__ = "DataHu"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?data\.hu/get/\w+'
-
- __description__ = """Data.hu hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("crash", ""),
- ("stickell", "l.stickell@yahoo.it")]
-
-
- INFO_PATTERN = ur'<title>(?P<N>.*) \((?P<S>[^)]+)\) let\xf6lt\xe9se</title>'
- OFFLINE_PATTERN = ur'Az adott f\xe1jl nem l\xe9tezik'
- LINK_FREE_PATTERN = r'<div class="download_box_button"><a href="([^"]+)">'
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = self.premium
-
-
-getInfo = create_getInfo(DataHu)
diff --git a/module/plugins/hoster/DataportCz.py b/module/plugins/hoster/DataportCz.py
deleted file mode 100644
index 592bece93..000000000
--- a/module/plugins/hoster/DataportCz.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class DataportCz(SimpleHoster):
- __name__ = "DataportCz"
- __type__ = "hoster"
- __version__ = "0.41"
-
- __pattern__ = r'http://(?:www\.)?dataport\.cz/file/(.+)'
-
- __description__ = """Dataport.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<span itemprop="name">(?P<N>[^<]+)</span>'
- SIZE_PATTERN = r'<td class="fil">Velikost</td>\s*<td>(?P<S>[^<]+)</td>'
- OFFLINE_PATTERN = r'<h2>Soubor nebyl nalezen</h2>'
-
- CAPTCHA_PATTERN = r'<section id="captcha_bg">\s*<img src="(.*?)"'
- FREE_SLOTS_PATTERN = ur'Počet volnÜch slotů: <span class="darkblue">(\d+)</span><br />'
-
-
- def handleFree(self, pyfile):
- captchas = {"1": "jkeG", "2": "hMJQ", "3": "vmEK", "4": "ePQM", "5": "blBd"}
-
- for _i in xrange(60):
- action, inputs = self.parseHtmlForm('free_download_form')
- self.logDebug(action, inputs)
- if not action or not inputs:
- self.error(_("free_download_form"))
-
- if "captchaId" in inputs and inputs['captchaId'] in captchas:
- inputs['captchaCode'] = captchas[inputs['captchaId']]
- else:
- self.error(_("captcha"))
-
- self.html = self.download("http://www.dataport.cz%s" % action, post=inputs)
-
- check = self.checkDownload({"captcha": 'alert("\u0160patn\u011b opsan\u00fd k\u00f3d z obr\u00e1zu");',
- "slot" : 'alert("Je n\u00e1m l\u00edto, ale moment\u00e1ln\u011b nejsou'})
- if check == "captcha":
- self.error(_("invalid captcha"))
-
- elif check == "slot":
- self.logDebug("No free slots - wait 60s and retry")
- self.wait(60, False)
- self.html = self.load(pyfile.url, decode=True)
- continue
-
- else:
- break
-
-
-getInfo = create_getInfo(DataportCz)
diff --git a/module/plugins/hoster/DateiTo.py b/module/plugins/hoster/DateiTo.py
deleted file mode 100644
index 66102939a..000000000
--- a/module/plugins/hoster/DateiTo.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class DateiTo(SimpleHoster):
- __name__ = "DateiTo"
- __type__ = "hoster"
- __version__ = "0.07"
-
- __pattern__ = r'http://(?:www\.)?datei\.to/datei/(?P<ID>\w+)\.html'
-
- __description__ = """Datei.to hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'Dateiname:</td>\s*<td colspan="2"><strong>(?P<N>.*?)</'
- SIZE_PATTERN = r'Dateigr&ouml;&szlig;e:</td>\s*<td colspan="2">(?P<S>.*?)</'
- OFFLINE_PATTERN = r'>Datei wurde nicht gefunden<|>Bitte wÀhle deine Datei aus... <'
-
- WAIT_PATTERN = r'countdown\({seconds: (\d+)'
- MULTIDL_PATTERN = r'>Du lÀdst bereits eine Datei herunter<'
-
- DATA_PATTERN = r'url: "(.*?)", data: "(.*?)",'
-
-
- def handleFree(self, pyfile):
- url = 'http://datei.to/ajax/download.php'
- data = {'P': 'I', 'ID': self.info['pattern']['ID']}
- recaptcha = ReCaptcha(self)
-
- for _i in xrange(10):
- self.logDebug("URL", url, "POST", data)
- self.html = self.load(url, post=data)
- self.checkErrors()
-
- if url.endswith('download.php') and 'P' in data:
- if data['P'] == 'I':
- self.doWait()
-
- elif data['P'] == 'IV':
- break
-
- m = re.search(self.DATA_PATTERN, self.html)
- if m is None:
- self.error(_("data"))
- url = 'http://datei.to/' + m.group(1)
- data = dict(x.split('=') for x in m.group(2).split('&'))
-
- if url.endswith('recaptcha.php'):
- data['recaptcha_response_field'], data['recaptcha_challenge_field'] = recaptcha.challenge()
- else:
- self.fail(_("Too bad..."))
-
- self.download(self.html)
-
-
- def checkErrors(self):
- m = re.search(self.MULTIDL_PATTERN, self.html)
- if m:
- m = re.search(self.WAIT_PATTERN, self.html)
- wait_time = int(m.group(1)) if m else 30
-
- errmsg = self.info['error'] = _("Parallel downloads")
- self.retry(wait_time=wait_time, reason=errmsg)
-
- self.info.pop('error', None)
-
-
- def doWait(self):
- m = re.search(self.WAIT_PATTERN, self.html)
- wait_time = int(m.group(1)) if m else 30
-
- self.load('http://datei.to/ajax/download.php', post={'P': 'Ads'})
- self.wait(wait_time, False)
-
-
-getInfo = create_getInfo(DateiTo)
diff --git a/module/plugins/hoster/DdlstorageCom.py b/module/plugins/hoster/DdlstorageCom.py
deleted file mode 100644
index 32a5a8bb7..000000000
--- a/module/plugins/hoster/DdlstorageCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class DdlstorageCom(DeadHoster):
- __name__ = "DdlstorageCom"
- __type__ = "hoster"
- __version__ = "1.02"
-
- __pattern__ = r'https?://(?:www\.)?ddlstorage\.com/\w+'
-
- __description__ = """DDLStorage.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
-getInfo = create_getInfo(DdlstorageCom)
diff --git a/module/plugins/hoster/DebridItaliaCom.py b/module/plugins/hoster/DebridItaliaCom.py
deleted file mode 100644
index 8cda56c0c..000000000
--- a/module/plugins/hoster/DebridItaliaCom.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-
-
-class DebridItaliaCom(MultiHoster):
- __name__ = "DebridItaliaCom"
- __type__ = "hoster"
- __version__ = "0.17"
-
- __pattern__ = r'https?://(?:www\.|s\d+\.)?debriditalia\.com/dl/\d+'
-
- __description__ = """Debriditalia.com multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- URL_REPLACEMENTS = [("https://", "http://")]
-
-
- def handlePremium(self, pyfile):
- self.html = self.load("http://www.debriditalia.com/api.php",
- get={'generate': "on", 'link': pyfile.url, 'p': self.getPassword()})
-
- if "ERROR:" not in self.html:
- self.link = self.html.strip()
- else:
- self.info['error'] = re.search(r'ERROR:(.*)', self.html).group(1).strip()
-
- self.html = self.load("http://debriditalia.com/linkgen2.php",
- post={'xjxfun' : "convertiLink",
- 'xjxargs[]': "S<![CDATA[%s]]>" % pyfile.url,
- 'xjxargs[]': "S%s" % self.getPassword()})
- try:
- self.link = re.search(r'<a href="(.+?)"', self.html).group(1)
- except AttributeError:
- pass
-
-
-getInfo = create_getInfo(DebridItaliaCom)
diff --git a/module/plugins/hoster/DepositfilesCom.py b/module/plugins/hoster/DepositfilesCom.py
deleted file mode 100644
index c9e2040f8..000000000
--- a/module/plugins/hoster/DepositfilesCom.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urllib import unquote
-
-from pyload.plugin.internal.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class DepositfilesCom(SimpleHoster):
- __name__ = "DepositfilesCom"
- __type__ = "hoster"
- __version__ = "0.53"
-
- __pattern__ = r'https?://(?:www\.)?(depositfiles\.com|dfiles\.(eu|ru))(/\w{1,3})?/files/(?P<ID>\w+)'
-
- __description__ = """Depositfiles.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("spoob", "spoob@pyload.org"),
- ("zoidberg", "zoidberg@mujmail.cz"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- NAME_PATTERN = r'<script type="text/javascript">eval\( unescape\(\'(?P<N>.*?)\''
- SIZE_PATTERN = r': <b>(?P<S>[\d.,]+)&nbsp;(?P<U>[\w^_]+)</b>'
- OFFLINE_PATTERN = r'<span class="html_download_api-not_exists"></span>'
-
- NAME_REPLACEMENTS = [(r'\%u([0-9A-Fa-f]{4})', lambda m: unichr(int(m.group(1), 16))),
- (r'.*<b title="(?P<N>[^"]+).*', "\g<N>")]
- URL_REPLACEMENTS = [(__pattern__ + ".*", "https://dfiles.eu/files/\g<ID>")]
-
- COOKIES = [("dfiles.eu", "lang_current", "en")]
-
- LINK_FREE_PATTERN = r'<form id="downloader_file_form" action="(http://.+?\.(dfiles\.eu|depositfiles\.com)/.+?)" method="post"'
- LINK_PREMIUM_PATTERN = r'class="repeat"><a href="(.+?)"'
- LINK_MIRROR_PATTERN = r'class="repeat_mirror"><a href="(.+?)"'
-
-
- def handleFree(self, pyfile):
- if re.search(r'File is checked, please try again in a minute.', self.html) is not None:
- self.logInfo(_("The file is being checked. Waiting 1 minute"))
- self.retry(wait_time=60)
-
- wait = re.search(r'html_download_api-limit_interval\">(\d+)</span>', self.html)
- if wait:
- wait_time = int(wait.group(1))
- self.logInfo(_("Traffic used up. Waiting %d seconds") % wait_time)
- self.wait(wait_time, True)
- self.retry()
-
- wait = re.search(r'>Try in (\d+) minutes or use GOLD account', self.html)
- if wait:
- wait_time = int(wait.group(1))
- self.logInfo(_("All free slots occupied. Waiting %d minutes") % wait_time)
- self.setWait(wait_time * 60, False)
-
- wait = re.search(r'Please wait (\d+) sec', self.html)
- if wait:
- self.setWait(int(wait.group(1)))
-
- m = re.search(r"var fid = '(\w+)';", self.html)
- if m is None:
- self.retry(wait_time=5)
- params = {'fid': m.group(1)}
- self.logDebug("FID: %s" % params['fid'])
-
- self.wait()
- recaptcha = ReCaptcha(self)
- captcha_key = recaptcha.detect_key()
- if captcha_key is None:
- self.error(_("ReCaptcha key not found"))
-
- for _i in xrange(5):
- self.html = self.load("https://dfiles.eu/get_file.php", get=params)
-
- if '<input type=button value="Continue" onclick="check_recaptcha' in self.html:
- if 'response' in params:
- self.invalidCaptcha()
- params['response'], params['challenge'] = recaptcha.challenge(captcha_key)
- self.logDebug(params)
- continue
-
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m:
- if 'response' in params:
- self.correctCaptcha()
-
- self.link = unquote(m.group(1))
- break
- else:
- self.error(_("Download link"))
- else:
- self.fail(_("No valid captcha response received"))
-
-
- def handlePremium(self, pyfile):
- if '<span class="html_download_api-gold_traffic_limit">' in self.html:
- self.logWarning(_("Download limit reached"))
- self.retry(25, 60 * 60, "Download limit reached")
- elif 'onClick="show_gold_offer' in self.html:
- self.account.relogin(self.user)
- self.retry()
- else:
- link = re.search(self.LINK_PREMIUM_PATTERN, self.html)
- mirror = re.search(self.LINK_MIRROR_PATTERN, self.html)
-
- if link:
- self.link = link.group(1)
-
- elif mirror:
- self.link = mirror.group(1)
-
-
-getInfo = create_getInfo(DepositfilesCom)
diff --git a/module/plugins/hoster/DevhostSt.py b/module/plugins/hoster/DevhostSt.py
deleted file mode 100644
index 2365baa5f..000000000
--- a/module/plugins/hoster/DevhostSt.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# http://d-h.st/mM8
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class DevhostSt(SimpleHoster):
- __name__ = "DevhostSt"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'http://(?:www\.)?d-h\.st/(?!users/)\w{3}'
-
- __description__ = """d-h.st hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
-
-
- NAME_PATTERN = r'<span title="(?P<N>.*?)"'
- SIZE_PATTERN = r'</span> \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)<br'
- HASHSUM_PATTERN = r'>(?P<T>.*?) Sum</span>: &nbsp;(?P<H>.*?)<br'
-
- OFFLINE_PATTERN = r'>File Not Found'
- LINK_FREE_PATTERN = r'var product_download_url= \'(.+?)\''
-
-
- def setup(self):
- self.multiDL = True
- self.chunkLimit = 1
-
-
-getInfo = create_getInfo(DevhostSt)
diff --git a/module/plugins/hoster/DlFreeFr.py b/module/plugins/hoster/DlFreeFr.py
deleted file mode 100644
index 541989120..000000000
--- a/module/plugins/hoster/DlFreeFr.py
+++ /dev/null
@@ -1,140 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import pycurl
-import re
-
-from pyload.network.Browser import Browser
-from pyload.network.CookieJar import CookieJar
-from pyload.plugin.internal.captcha import AdYouLike
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns
-from pyload.utils import json_loads
-
-
-class CustomBrowser(Browser):
-
- def __init__(self, bucket=None, options={}):
- Browser.__init__(self, bucket, options)
-
-
- def load(self, *args, **kwargs):
- post = kwargs.get("post")
-
- if post is None and len(args) > 2:
- post = args[2]
-
- if post:
- self.http.c.setopt(pycurl.FOLLOWLOCATION, 0)
- self.http.c.setopt(pycurl.POST, 1)
- self.http.c.setopt(pycurl.CUSTOMREQUEST, "POST")
- else:
- self.http.c.setopt(pycurl.FOLLOWLOCATION, 1)
- self.http.c.setopt(pycurl.POST, 0)
- self.http.c.setopt(pycurl.CUSTOMREQUEST, "GET")
-
- return Browser.load(self, *args, **kwargs)
-
-
-class DlFreeFr(SimpleHoster):
- __name__ = "DlFreeFr"
- __type__ = "hoster"
- __version__ = "0.28"
-
- __pattern__ = r'http://(?:www\.)?dl\.free\.fr/(\w+|getfile\.pl\?file=/\w+)'
-
- __description__ = """Dl.free.fr hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("the-razer", "daniel_ AT gmx DOT net"),
- ("zoidberg", "zoidberg@mujmail.cz"),
- ("Toilal", "toilal.dev@gmail.com")]
-
-
- NAME_PATTERN = r'Fichier:</td>\s*<td[^>]*>(?P<N>[^>]*)</td>'
- SIZE_PATTERN = r'Taille:</td>\s*<td[^>]*>(?P<S>[\d.,]+\w)o'
- OFFLINE_PATTERN = r'Erreur 404 - Document non trouv|Fichier inexistant|Le fichier demand&eacute; n\'a pas &eacute;t&eacute; trouv&eacute;'
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = True
- self.limitDL = 5
- self.chunkLimit = 1
-
-
- def init(self):
- factory = self.core.requestFactory
- self.req = CustomBrowser(factory.bucket, factory.getOptions())
-
-
- def process(self, pyfile):
- pyfile.url = replace_patterns(pyfile.url, self.URL_REPLACEMENTS)
- valid_url = pyfile.url
- headers = self.load(valid_url, just_header=True)
-
- if headers.get('code') == 302:
- valid_url = headers.get('location')
- headers = self.load(valid_url, just_header=True)
-
- if headers.get('code') == 200:
- content_type = headers.get('content-type')
- if content_type and content_type.startswith("text/html"):
- # Undirect acces to requested file, with a web page providing it (captcha)
- self.html = self.load(valid_url)
- self.handleFree(pyfile)
- else:
- # Direct access to requested file for users using free.fr as Internet Service Provider.
- self.link = valid_url
-
- elif headers.get('code') == 404:
- self.offline()
-
- else:
- self.fail(_("Invalid return code: ") + str(headers.get('code')))
-
-
- def handleFree(self, pyfile):
- action, inputs = self.parseHtmlForm('action="getfile.pl"')
-
- adyoulike = AdYouLike(self)
- response, challenge = adyoulike.challenge()
- inputs.update(response)
-
- self.load("http://dl.free.fr/getfile.pl", post=inputs)
- headers = self.getLastHeaders()
- if headers.get("code") == 302 and "set-cookie" in headers and "location" in headers:
- m = re.search("(.*?)=(.*?); path=(.*?); domain=(.*?)", headers.get("set-cookie"))
- cj = CookieJar(__name__)
- if m:
- cj.setCookie(m.group(4), m.group(1), m.group(2), m.group(3))
- else:
- self.fail(_("Cookie error"))
-
- self.link = headers.get("location")
-
- self.req.setCookieJar(cj)
- else:
- self.fail(_("Invalid response"))
-
-
- def getLastHeaders(self):
- #parse header
- header = {"code": self.req.code}
- for line in self.req.http.header.splitlines():
- line = line.strip()
- if not line or ":" not in line:
- continue
-
- key, none, value = line.partition(":")
- key = key.lower().strip()
- value = value.strip()
-
- if key in header:
- if type(header[key]) == list:
- header[key].append(value)
- else:
- header[key] = [header[key], value]
- else:
- header[key] = value
- return header
-
-
-getInfo = create_getInfo(DlFreeFr)
diff --git a/module/plugins/hoster/DodanePl.py b/module/plugins/hoster/DodanePl.py
deleted file mode 100644
index 65d8452fa..000000000
--- a/module/plugins/hoster/DodanePl.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class DodanePl(DeadHoster):
- __name__ = "DodanePl"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?dodane\.pl/file/\d+'
-
- __description__ = """Dodane.pl hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("z00nx", "z00nx0@gmail.com")]
-
-
-getInfo = create_getInfo(DodanePl)
diff --git a/module/plugins/hoster/DuploadOrg.py b/module/plugins/hoster/DuploadOrg.py
deleted file mode 100644
index 6dd25407e..000000000
--- a/module/plugins/hoster/DuploadOrg.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class DuploadOrg(DeadHoster):
- __name__ = "DuploadOrg"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?dupload\.org/\w{12}'
-
- __description__ = """Dupload.grg hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
-getInfo = create_getInfo(DuploadOrg)
diff --git a/module/plugins/hoster/EasybytezCom.py b/module/plugins/hoster/EasybytezCom.py
deleted file mode 100644
index 6ca45f545..000000000
--- a/module/plugins/hoster/EasybytezCom.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class EasybytezCom(XFSHoster):
- __name__ = "EasybytezCom"
- __type__ = "hoster"
- __version__ = "0.23"
-
- __pattern__ = r'http://(?:www\.)?easybytez\.com/\w{12}'
-
- __description__ = """Easybytez.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
- OFFLINE_PATTERN = r'>File not available'
-
- LINK_PATTERN = r'(http://(\w+\.(easybytez|easyload|ezbytez|zingload)\.(com|to)|\d+\.\d+\.\d+\.\d+)/files/\d+/\w+/.+?)["\'<]'
-
-
-getInfo = create_getInfo(EasybytezCom)
diff --git a/module/plugins/hoster/EdiskCz.py b/module/plugins/hoster/EdiskCz.py
deleted file mode 100644
index 76e55ae3c..000000000
--- a/module/plugins/hoster/EdiskCz.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class EdiskCz(SimpleHoster):
- __name__ = "EdiskCz"
- __type__ = "hoster"
- __version__ = "0.23"
-
- __pattern__ = r'http://(?:www\.)?edisk\.(cz|sk|eu)/(stahni|sk/stahni|en/download)/.+'
-
- __description__ = """Edisk.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- INFO_PATTERN = r'<span class="fl" title="(?P<N>[^"]+)">\s*.*?\((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)</h1></span>'
- OFFLINE_PATTERN = r'<h3>This file does not exist due to one of the following:</h3><ul><li>'
-
- ACTION_PATTERN = r'/en/download/(\d+/.*\.html)'
- LINK_FREE_PATTERN = r'http://.*edisk\.cz.*\.html'
-
-
- def setup(self):
- self.multiDL = False
-
-
- def process(self, pyfile):
- url = re.sub("/(stahni|sk/stahni)/", "/en/download/", pyfile.url)
-
- self.logDebug("URL:" + url)
-
- m = re.search(self.ACTION_PATTERN, url)
- if m is None:
- self.error(_("ACTION_PATTERN not found"))
- action = m.group(1)
-
- self.html = self.load(url, decode=True)
- self.getFileInfo()
-
- self.html = self.load(re.sub("/en/download/", "/en/download-slow/", url))
-
- url = self.load(re.sub("/en/download/", "/x-download/", url), post={
- "action": action
- })
-
- if not re.match(self.LINK_FREE_PATTERN, url):
- self.fail(_("Unexpected server response"))
-
- self.download(url)
-
-
-getInfo = create_getInfo(EdiskCz)
diff --git a/module/plugins/hoster/EgoFilesCom.py b/module/plugins/hoster/EgoFilesCom.py
deleted file mode 100644
index ad5ad0796..000000000
--- a/module/plugins/hoster/EgoFilesCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class EgoFilesCom(DeadHoster):
- __name__ = "EgoFilesCom"
- __type__ = "hoster"
- __version__ = "0.16"
-
- __pattern__ = r'https?://(?:www\.)?egofiles\.com/\w+'
-
- __description__ = """Egofiles.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
-getInfo = create_getInfo(EgoFilesCom)
diff --git a/module/plugins/hoster/EnteruploadCom.py b/module/plugins/hoster/EnteruploadCom.py
deleted file mode 100644
index 0be9b8d76..000000000
--- a/module/plugins/hoster/EnteruploadCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class EnteruploadCom(DeadHoster):
- __name__ = "EnteruploadCom"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?enterupload\.com/\w+'
-
- __description__ = """EnterUpload.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(EnteruploadCom)
diff --git a/module/plugins/hoster/EpicShareNet.py b/module/plugins/hoster/EpicShareNet.py
deleted file mode 100644
index 061782468..000000000
--- a/module/plugins/hoster/EpicShareNet.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class EpicShareNet(DeadHoster):
- __name__ = "EpicShareNet"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'https?://(?:www\.)?epicshare\.net/\w{12}'
-
- __description__ = """EpicShare.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("t4skforce", "t4skforce1337[AT]gmail[DOT]com")]
-
-
-getInfo = create_getInfo(EpicShareNet)
diff --git a/module/plugins/hoster/EuroshareEu.py b/module/plugins/hoster/EuroshareEu.py
deleted file mode 100644
index 41cc37087..000000000
--- a/module/plugins/hoster/EuroshareEu.py
+++ /dev/null
@@ -1,67 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class EuroshareEu(SimpleHoster):
- __name__ = "EuroshareEu"
- __type__ = "hoster"
- __version__ = "0.27"
-
- __pattern__ = r'http://(?:www\.)?euroshare\.(eu|sk|cz|hu|pl)/file/.+'
-
- __description__ = """Euroshare.eu hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- INFO_PATTERN = r'<span style="float: left;"><strong>(?P<N>.+?)</strong> \((?P<S>.+?)\)</span>'
- OFFLINE_PATTERN = ur'<h2>S.bor sa nena.iel</h2>|Poşadovaná stránka neexistuje!'
-
- LINK_FREE_PATTERN = r'<a href="(/file/\d+/[^/]*/download/)"><div class="downloadButton"'
-
- ERR_PARDL_PATTERN = r'<h2>Prebieha s.ahovanie</h2>|<p>Naraz je z jednej IP adresy mo.n. s.ahova. iba jeden s.bor'
- ERR_NOT_LOGGED_IN_PATTERN = r'href="/customer-zone/login/"'
-
- URL_REPLACEMENTS = [(r"(http://[^/]*\.)(sk|cz|hu|pl)/", r"\1eu/")]
-
-
- def handlePremium(self, pyfile):
- if self.ERR_NOT_LOGGED_IN_PATTERN in self.html:
- self.account.relogin(self.user)
- self.retry(reason=_("User not logged in"))
-
- self.download(pyfile.url.rstrip('/') + "/download/")
-
- check = self.checkDownload({"login": re.compile(self.ERR_NOT_LOGGED_IN_PATTERN),
- "json" : re.compile(r'\{"status":"error".*?"message":"(.*?)"')})
-
- if check == "login" or (check == "json" and self.lastCheck.group(1) == "Access token expired"):
- self.account.relogin(self.user)
- self.retry(reason=_("Access token expired"))
-
- elif check == "json":
- self.fail(self.lastCheck.group(1))
-
-
- def handleFree(self, pyfile):
- if re.search(self.ERR_PARDL_PATTERN, self.html) is not None:
- self.longWait(5 * 60, 12)
-
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("LINK_FREE_PATTERN not found"))
-
- self.link = "http://euroshare.eu%s" % m.group(1)
-
-
- def checkFile(self):
- if self.checkDownload({"multi-dl": re.compile(self.ERR_PARDL_PATTERN)})
- self.longWait(5 * 60, 12)
-
- return super(EuroshareEu, self).checkFile()
-
-
-getInfo = create_getInfo(EuroshareEu)
diff --git a/module/plugins/hoster/ExashareCom.py b/module/plugins/hoster/ExashareCom.py
deleted file mode 100644
index 536c09b6d..000000000
--- a/module/plugins/hoster/ExashareCom.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class ExashareCom(XFSHoster):
- __name__ = "ExashareCom"
- __type__ = "hoster"
- __version__ = "0.01"
-
- __pattern__ = r'http://(?:www\.)?exashare\.com/\w{12}'
-
- __description__ = """Exashare.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- INFO_PATTERN = r'>(?P<NAME>.+?)<small>\( (?P<S>[\d.,]+) (?P<U>[\w^_]+)'
- LINK_FREE_PATTERN = r'file: "(.+?)"'
-
-
- def setup(self):
- self.multiDL = True
- self.chunkLimit = 1
- self.resumeDownload = self.premium
-
-
- def handleFree(self, pyfile):
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("Free download link not found"))
- else:
- self.link = m.group(1)
-
-
-getInfo = create_getInfo(ExashareCom)
diff --git a/module/plugins/hoster/ExtabitCom.py b/module/plugins/hoster/ExtabitCom.py
deleted file mode 100644
index f9f76b28b..000000000
--- a/module/plugins/hoster/ExtabitCom.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.utils import json_loads
-
-from module.plugins.internal.CaptchaService import ReCaptcha
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, secondsToMidnight
-
-
-class ExtabitCom(SimpleHoster):
- __name__ = "ExtabitCom"
- __type__ = "hoster"
- __version__ = "0.65"
-
- __pattern__ = r'http://(?:www\.)?extabit\.com/(file|go|fid)/(?P<ID>\w+)'
-
- __description__ = """Extabit.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<th>File:</th>\s*<td class="col-fileinfo">\s*<div title="(?P<N>[^"]+)">'
- SIZE_PATTERN = r'<th>Size:</th>\s*<td class="col-fileinfo">(?P<S>[^<]+)</td>'
- OFFLINE_PATTERN = r'>File not found<'
- TEMP_OFFLINE_PATTERN = r'>(File is temporary unavailable|No download mirror)<'
-
- LINK_FREE_PATTERN = r'[\'"](http://guest\d+\.extabit\.com/\w+/.*?)[\'"]'
-
-
- def handleFree(self, pyfile):
- if r">Only premium users can download this file" in self.html:
- self.fail(_("Only premium users can download this file"))
-
- m = re.search(r"Next free download from your ip will be available in <b>(\d+)\s*minutes", self.html)
- if m:
- self.wait(int(m.group(1)) * 60, True)
- elif "The daily downloads limit from your IP is exceeded" in self.html:
- self.logWarning(_("You have reached your daily downloads limit for today"))
- self.wait(secondsToMidnight(gmt=2), True)
-
- self.logDebug("URL: " + self.req.http.lastEffectiveURL)
- m = re.match(self.__pattern__, self.req.http.lastEffectiveURL)
- fileID = m.group('ID') if m else self.info['pattern']['ID']
-
- m = re.search(r'recaptcha/api/challenge\?k=(\w+)', self.html)
- if m:
- recaptcha = ReCaptcha(self)
- captcha_key = m.group(1)
-
- for _i in xrange(5):
- get_data = {"type": "recaptcha"}
- get_data['capture'], get_data['challenge'] = recaptcha.challenge(captcha_key)
- res = json_loads(self.load("http://extabit.com/file/%s/" % fileID, get=get_data))
- if "ok" in res:
- self.correctCaptcha()
- break
- else:
- self.invalidCaptcha()
- else:
- self.fail(_("Invalid captcha"))
- else:
- self.error(_("Captcha"))
-
- if not "href" in res:
- self.error(_("Bad JSON response"))
-
- self.html = self.load("http://extabit.com/file/%s%s" % (fileID, res['href']))
-
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("LINK_FREE_PATTERN not found"))
-
- url = m.group(1)
- self.download(url)
-
-
-getInfo = create_getInfo(ExtabitCom)
diff --git a/module/plugins/hoster/FastixRu.py b/module/plugins/hoster/FastixRu.py
deleted file mode 100644
index 8f1b9e694..000000000
--- a/module/plugins/hoster/FastixRu.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from random import randrange
-from urllib import unquote
-
-from pyload.utils import json_loads
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-
-
-class FastixRu(MultiHoster):
- __name__ = "FastixRu"
- __type__ = "hoster"
- __version__ = "0.09"
-
- __pattern__ = r'http://(?:www\.)?fastix\.(ru|it)/file/\w{24}'
-
- __description__ = """Fastix multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Massimo Rosamilia", "max@spiritix.eu")]
-
-
- def getFilename(self, url):
- try:
- name = unquote(url.rsplit("/", 1)[1])
- except IndexError:
- name = "Unknown_Filename..."
- if name.endswith("..."): # incomplete filename, append random stuff
- name += "%s.tmp" % randrange(100, 999)
- return name
-
-
- def setup(self):
- self.chunkLimit = 3
-
-
- def handlePremium(self, pyfile):
- api_key = self.account.getAccountData(self.user)
- api_key = api_key['api']
-
- self.html = self.load("http://fastix.ru/api_v2/",
- get={'apikey': api_key, 'sub': "getdirectlink", 'link': pyfile.url})
-
- data = json_loads(self.html)
-
- self.logDebug("Json data", data)
-
- if "error\":true" in self.html:
- self.offline()
- else:
- self.link = data['downloadlink']
-
- if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown"):
- #only use when name wasnt already set
- pyfile.name = self.getFilename(self.link)
-
-
- def checkFile(self):
- if self.checkDownload({"error": "<title>An error occurred while processing your request</title>"}):
- self.retry(wait_time=60, reason=_("An error occurred while generating link"))
-
- return super(FastixRu, self).checkFile()
-
-
-getInfo = create_getInfo(FastixRu)
diff --git a/module/plugins/hoster/FastshareCz.py b/module/plugins/hoster/FastshareCz.py
deleted file mode 100644
index 6fe871ad4..000000000
--- a/module/plugins/hoster/FastshareCz.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urlparse import urljoin
-
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class FastshareCz(SimpleHoster):
- __name__ = "FastshareCz"
- __type__ = "hoster"
- __version__ = "0.27"
-
- __pattern__ = r'http://(?:www\.)?fastshare\.cz/\d+/.+'
-
- __description__ = """FastShare.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
- URL_REPLACEMENTS = [("#.*", "")]
-
- COOKIES = [("fastshare.cz", "lang", "en")]
-
- INFO_PATTERN = r'<h1 class="dwp">(?P<N>[^<]+)</h1>\s*<div class="fileinfo">\s*Size\s*: (?P<S>\d+) (?P<U>[\w^_]+),'
- OFFLINE_PATTERN = r'>(The file has been deleted|Requested page not found)'
-
- LINK_FREE_PATTERN = r'action=(/free/.*?)>\s*<img src="([^"]*)"><br'
- LINK_PREMIUM_PATTERN = r'(http://data\d+\.fastshare\.cz/download\.php\?id=\d+&)'
-
- SLOT_ERROR = "> 100% of FREE slots are full"
- CREDIT_ERROR = " credit for "
-
-
- def checkErrors(self):
- if self.SLOT_ERROR in self.html:
- errmsg = self.info['error'] = _("No free slots")
- self.retry(12, 60, errmsg)
-
- if self.CREDIT_ERROR in self.html:
- errmsg = self.info['error'] = _("Not enough traffic left")
- self.logWarning(errmsg)
- self.resetAccount()
-
- self.info.pop('error', None)
-
-
- def handleFree(self, pyfile):
- m = re.search(self.FREE_URL_PATTERN, self.html)
- if m:
- action, captcha_src = m.groups()
- else:
- self.error(_("FREE_URL_PATTERN not found"))
-
- baseurl = "http://www.fastshare.cz"
- captcha = self.decryptCaptcha(urljoin(baseurl, captcha_src))
- self.download(urljoin(baseurl, action), post={'code': captcha, 'btn.x': 77, 'btn.y': 18})
-
-
- def checkFile(self):
- check = self.checkDownload({
- 'paralell-dl' : re.compile(r"<title>FastShare.cz</title>|<script>alert\('Pres FREE muzete stahovat jen jeden soubor najednou.'\)"),
- 'wrong captcha': re.compile(r'Download for FREE'),
- 'credit' : re.compile(self.CREDIT_ERROR)
- })
-
- if check == "paralell-dl":
- self.retry(6, 10 * 60, _("Paralell download"))
-
- elif check == "wrong captcha":
- self.retry(max_tries=5, reason=_("Wrong captcha"))
-
- elif check == "credit":
- self.resetAccount()
-
- return super(FastshareCz, self).checkFile()
-
-
-getInfo = create_getInfo(FastshareCz)
diff --git a/module/plugins/hoster/FileApeCom.py b/module/plugins/hoster/FileApeCom.py
deleted file mode 100644
index 212e3ba9c..000000000
--- a/module/plugins/hoster/FileApeCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class FileApeCom(DeadHoster):
- __name__ = "FileApeCom"
- __type__ = "hoster"
- __version__ = "0.12"
-
- __pattern__ = r'http://(?:www\.)?fileape\.com/(index\.php\?act=download\&id=|dl/)\w+'
-
- __description__ = """FileApe.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("espes", "")]
-
-
-getInfo = create_getInfo(FileApeCom)
diff --git a/module/plugins/hoster/FileSharkPl.py b/module/plugins/hoster/FileSharkPl.py
deleted file mode 100644
index 29c95ee8f..000000000
--- a/module/plugins/hoster/FileSharkPl.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urlparse import urljoin
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class FileSharkPl(SimpleHoster):
- __name__ = "FileSharkPl"
- __type__ = "hoster"
- __version__ = "0.07"
-
- __pattern__ = r'http://(?:www\.)?fileshark\.pl/pobierz/\d+/\w+'
-
- __description__ = """FileShark.pl hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("prOq", ""),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- NAME_PATTERN = r'<h2 class="name-file">(?P<N>.+)</h2>'
- SIZE_PATTERN = r'<p class="size-file">(.*?)<strong>(?P<S>\d+\.?\d*)\s(?P<U>\w+)</strong></p>'
-
- OFFLINE_PATTERN = '(P|p)lik zosta. (usuni.ty|przeniesiony)'
-
- LINK_FREE_PATTERN = r'<a href="(.*?)" class="btn-upload-free">'
- LINK_PREMIUM_PATTERN = r'<a href="(.*?)" class="btn-upload-premium">'
-
- WAIT_PATTERN = r'var timeToDownload = (\d+);'
- ERROR_PATTERN = r'<p class="lead text-center alert alert-warning">(.*?)</p>'
- IP_ERROR_PATTERN = r'Strona jest dost.pna wy..cznie dla u.ytkownik.w znajduj.cych si. na terenie Polski'
- SLOT_ERROR_PATTERN = r'Osi.gni.to maksymaln. liczb. .ci.ganych jednocze.nie plik.w\.'
-
- CAPTCHA_PATTERN = '<img src="data:image/jpeg;base64,(.*?)" title="captcha"'
- TOKEN_PATTERN = r'name="form\[_token\]" value="(.*?)" />'
-
-
- def setup(self):
- self.resumeDownload = True
-
- if self.premium:
- self.multiDL = True
- self.limitDL = 20
- else:
- self.multiDL = False
-
-
- def checkErrors(self):
- # check if file is now available for download (-> file name can be found in html body)
- m = re.search(self.WAIT_PATTERN, self.html)
- if m:
- errmsg = self.info['error'] = _("Another download already run")
- self.retry(15, int(m.group(1)), errmsg)
-
- m = re.search(self.ERROR_PATTERN, self.html)
- if m:
- alert = m.group(1)
-
- if re.match(self.IP_ERROR_PATTERN, alert):
- self.fail(_("Only connections from Polish IP are allowed"))
-
- elif re.match(self.SLOT_ERROR_PATTERN, alert):
- errmsg = self.info['error'] = _("No free download slots available")
- self.logWarning(errmsg)
- self.retry(10, 30 * 60, _("Still no free download slots available"))
-
- else:
- self.info['error'] = alert
- self.retry(10, 10 * 60, _("Try again later"))
-
- self.info.pop('error', None)
-
-
- def handleFree(self, pyfile):
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("Download url not found"))
-
- link = urljoin("http://fileshark.pl", m.group(1))
-
- m = re.search(self.WAIT_PATTERN, self.html)
- if m:
- seconds = int(m.group(1))
- self.logDebug("Wait %s seconds" % seconds)
- self.wait(seconds)
-
- action, inputs = self.parseHtmlForm('action=""')
-
- m = re.search(self.TOKEN_PATTERN, self.html)
- if m is None:
- self.retry(reason=_("Captcha form not found"))
-
- inputs['form[_token]'] = m.group(1)
-
- m = re.search(self.CAPTCHA_PATTERN, self.html)
- if m is None:
- self.retry(reason=_("Captcha image not found"))
-
- tmp_load = self.load
- self.load = self._decode64 #: work-around: injects decode64 inside decryptCaptcha
-
- inputs['form[captcha]'] = self.decryptCaptcha(m.group(1), imgtype='jpeg')
- inputs['form[start]'] = ""
-
- self.load = tmp_load
-
- self.download(link, post=inputs, cookies=True, disposition=True)
-
-
- def checkFile(self):
- check = self.checkDownload({'wrong_captcha': re.compile(r'<label for="form_captcha" generated="true" class="error">(.*?)</label>'),
- 'wait_pattern' : re.compile(self.SECONDS_PATTERN),
- 'DL-found' : re.compile('<a href="(.*)">')})
- if check == "DL-found":
- self.correctCaptcha()
-
- elif check == "wrong_captcha":
- self.invalidCaptcha()
- self.retry(10, 1, _("Wrong captcha solution"))
-
- elif check == "wait_pattern":
- self.retry()
-
- return super(FileSharkPl, self).checkFile()
-
-
- def _decode64(self, data, *args, **kwargs):
- return data.decode('base64')
-
-
-getInfo = create_getInfo(FileSharkPl)
diff --git a/module/plugins/hoster/FileStoreTo.py b/module/plugins/hoster/FileStoreTo.py
deleted file mode 100644
index 8a5171219..000000000
--- a/module/plugins/hoster/FileStoreTo.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class FileStoreTo(SimpleHoster):
- __name__ = "FileStoreTo"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'http://(?:www\.)?filestore\.to/\?d=(?P<ID>\w+)'
-
- __description__ = """FileStore.to hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
- INFO_PATTERN = r'File: <span.*?>(?P<N>.+?)<.*>Size: (?P<S>[\d.,]+) (?P<U>[\w^_]+)'
- OFFLINE_PATTERN = r'>Download-Datei wurde nicht gefunden<'
- TEMP_OFFLINE_PATTERN = r'>Der Download ist nicht bereit !<'
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = True
-
-
- def handleFree(self, pyfile):
- self.wait(10)
- self.link = self.load("http://filestore.to/ajax/download.php",
- get={'D': re.search(r'"D=(\w+)', self.html).group(1)})
-
-
-getInfo = create_getInfo(FileStoreTo)
diff --git a/module/plugins/hoster/FilebeerInfo.py b/module/plugins/hoster/FilebeerInfo.py
deleted file mode 100644
index 51a0137a0..000000000
--- a/module/plugins/hoster/FilebeerInfo.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class FilebeerInfo(DeadHoster):
- __name__ = "FilebeerInfo"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?filebeer\.info/(?!\d*~f)(?P<ID>\w+)'
-
- __description__ = """Filebeer.info plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(FilebeerInfo)
diff --git a/module/plugins/hoster/FilecloudIo.py b/module/plugins/hoster/FilecloudIo.py
deleted file mode 100644
index 6fb153658..000000000
--- a/module/plugins/hoster/FilecloudIo.py
+++ /dev/null
@@ -1,126 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.utils import json_loads
-from pyload.plugin.internal.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class FilecloudIo(SimpleHoster):
- __name__ = "FilecloudIo"
- __type__ = "hoster"
- __version__ = "0.08"
-
- __pattern__ = r'http://(?:www\.)?(?:filecloud\.io|ifile\.it|mihd\.net)/(?P<ID>\w+)'
-
- __description__ = """Filecloud.io hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
- LOGIN_ACCOUNT = True
-
- NAME_PATTERN = r'id="aliasSpan">(?P<N>.*?)&nbsp;&nbsp;<'
- SIZE_PATTERN = r'{var __ab1 = (?P<S>\d+);}'
- OFFLINE_PATTERN = r'l10n\.(FILES__DOESNT_EXIST|REMOVED)'
- TEMP_OFFLINE_PATTERN = r'l10n\.FILES__WARNING'
-
- UKEY_PATTERN = r'\'ukey\'\s*:\'(\w+)'
- AB1_PATTERN = r'if\( __ab1 == \'(\w+)\' \)'
-
- ERROR_MSG_PATTERN = r'var __error_msg\s*=\s*l10n\.(.*?);'
-
- RECAPTCHA_PATTERN = r'var __recaptcha_public\s*=\s*\'(.+?)\';'
-
- LINK_FREE_PATTERN = r'"(http://s\d+\.filecloud\.io/%s/\d+/.*?)"'
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = True
- self.chunkLimit = 1
-
-
- def handleFree(self, pyfile):
- data = {"ukey": self.info['pattern']['ID']}
-
- m = re.search(self.AB1_PATTERN, self.html)
- if m is None:
- self.error(_("__AB1"))
- data['__ab1'] = m.group(1)
-
- recaptcha = ReCaptcha(self)
-
- m = re.search(self.RECAPTCHA_PATTERN, self.html)
- captcha_key = m.group(1) if m else recaptcha.detect_key()
-
- if captcha_key is None:
- self.error(_("ReCaptcha key not found"))
-
- response, challenge = recaptcha.challenge(captcha_key)
- self.account.form_data = {"recaptcha_challenge_field": challenge,
- "recaptcha_response_field" : response}
- self.account.relogin(self.user)
- self.retry(2)
-
- json_url = "http://filecloud.io/download-request.json"
- res = self.load(json_url, post=data)
- self.logDebug(res)
- res = json_loads(res)
-
- if "error" in res and res['error']:
- self.fail(res)
-
- self.logDebug(res)
- if res['captcha']:
- data['ctype'] = "recaptcha"
-
- for _i in xrange(5):
- data['recaptcha_response'], data['recaptcha_challenge'] = recaptcha.challenge(captcha_key)
-
- json_url = "http://filecloud.io/download-request.json"
- res = self.load(json_url, post=data)
- self.logDebug(res)
- res = json_loads(res)
-
- if "retry" in res and res['retry']:
- self.invalidCaptcha()
- else:
- self.correctCaptcha()
- break
- else:
- self.fail(_("Incorrect captcha"))
-
- if res['dl']:
- self.html = self.load('http://filecloud.io/download.html')
-
- m = re.search(self.LINK_FREE_PATTERN % self.info['pattern']['ID'], self.html)
- if m is None:
- self.error(_("LINK_FREE_PATTERN not found"))
-
- if "size" in self.info and self.info['size']:
- self.check_data = {"size": int(self.info['size'])}
-
- download_url = m.group(1)
- self.download(download_url)
- else:
- self.fail(_("Unexpected server response"))
-
-
- def handlePremium(self, pyfile):
- akey = self.account.getAccountData(self.user)['akey']
- ukey = self.info['pattern']['ID']
- self.logDebug("Akey: %s | Ukey: %s" % (akey, ukey))
- rep = self.load("http://api.filecloud.io/api-fetch_download_url.api",
- post={"akey": akey, "ukey": ukey})
- self.logDebug("FetchDownloadUrl: " + rep)
- rep = json_loads(rep)
- if rep['status'] == 'ok':
- self.link = rep['download_url']
- else:
- self.fail(rep['message'])
-
-
-getInfo = create_getInfo(FilecloudIo)
diff --git a/module/plugins/hoster/FileomCom.py b/module/plugins/hoster/FileomCom.py
deleted file mode 100644
index 23f059546..000000000
--- a/module/plugins/hoster/FileomCom.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# http://fileom.com/gycaytyzdw3g/random.bin.html
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class FileomCom(XFSHoster):
- __name__ = "FileomCom"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'https?://(?:www\.)?fileom\.com/\w{12}'
-
- __description__ = """Fileom.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- NAME_PATTERN = r'Filename: <span>(?P<N>.+?)<'
- SIZE_PATTERN = r'File Size: <span class="size">(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
-
- LINK_PATTERN = r'var url2 = \'(.+?)\';'
-
-
- def setup(self):
- self.multiDL = True
- self.chunkLimit = 1
- self.resumeDownload = self.premium
-
-
-getInfo = create_getInfo(FileomCom)
diff --git a/module/plugins/hoster/FilepostCom.py b/module/plugins/hoster/FilepostCom.py
deleted file mode 100644
index 89f7fe9a4..000000000
--- a/module/plugins/hoster/FilepostCom.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from time import time
-
-from pyload.utils import json_loads
-from pyload.plugin.internal.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class FilepostCom(SimpleHoster):
- __name__ = "FilepostCom"
- __type__ = "hoster"
- __version__ = "0.33"
-
- __pattern__ = r'https?://(?:www\.)?(?:filepost\.com/files|fp\.io)/(?P<ID>[^/]+)'
-
- __description__ = """Filepost.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- INFO_PATTERN = r'<input type="text" id="url" value=\'<a href[^>]*>(?P<N>[^>]+?) - (?P<S>[\d.,]+) (?P<U>[\w^_]+)</a>\' class="inp_text"/>'
- OFFLINE_PATTERN = r'class="error_msg_title"> Invalid or Deleted File. </div>|<div class="file_info file_info_deleted">'
-
- PREMIUM_ONLY_PATTERN = r'members only. Please upgrade to premium|a premium membership is required to download this file'
- RECAPTCHA_PATTERN = r'Captcha.init\({\s*key:\s*\'(.+?)\''
- FLP_TOKEN_PATTERN = r'set_store_options\({token: \'(.+?)\''
-
-
- def handleFree(self, pyfile):
- m = re.search(self.FLP_TOKEN_PATTERN, self.html)
- if m is None:
- self.error(_("Token"))
- flp_token = m.group(1)
-
- m = re.search(self.RECAPTCHA_PATTERN, self.html)
- if m is None:
- self.error(_("Captcha key"))
- captcha_key = m.group(1)
-
- # Get wait time
- get_dict = {'SID': self.req.cj.getCookie('SID'), 'JsHttpRequest': str(int(time() * 10000)) + '-xml'}
- post_dict = {'action': 'set_download', 'token': flp_token, 'code': self.info['pattern']['ID']}
- wait_time = int(self.getJsonResponse(get_dict, post_dict, 'wait_time'))
-
- if wait_time > 0:
- self.wait(wait_time)
-
- post_dict = {"token": flp_token, "code": self.info['pattern']['ID'], "file_pass": ''}
-
- if 'var is_pass_exists = true;' in self.html:
- # Solve password
- password = self.getPassword()
-
- if password:
- self.logInfo(_("Password protected link, trying ") + file_pass)
-
- get_dict['JsHttpRequest'] = str(int(time() * 10000)) + '-xml'
- post_dict['file_pass'] = file_pass
-
- self.link = self.getJsonResponse(get_dict, post_dict, 'link')
-
- if not self.link:
- self.fail(_("Incorrect password"))
- else:
- self.fail(_("No password found"))
-
- else:
- # Solve recaptcha
- recaptcha = ReCaptcha(self)
-
- for i in xrange(5):
- get_dict['JsHttpRequest'] = str(int(time() * 10000)) + '-xml'
- if i:
- post_dict['recaptcha_response_field'], post_dict['recaptcha_challenge_field'] = recaptcha.challenge(
- captcha_key)
- self.logDebug(u"RECAPTCHA: %s : %s : %s" % (
- captcha_key, post_dict['recaptcha_challenge_field'], post_dict['recaptcha_response_field']))
-
- download_url = self.getJsonResponse(get_dict, post_dict, 'link')
- if download_url:
- if i:
- self.correctCaptcha()
- break
- elif i:
- self.invalidCaptcha()
-
- else:
- self.fail(_("Invalid captcha"))
-
- # Download
- self.download(download_url)
-
-
- def getJsonResponse(self, get_dict, post_dict, field):
- res = json_loads(self.load('https://filepost.com/files/get/', get=get_dict, post=post_dict))
-
- self.logDebug(res)
-
- if not 'js' in res:
- self.error(_("JSON %s 1") % field)
-
- # i changed js_answer to res['js'] since js_answer is nowhere set.
- # i don't know the JSON-HTTP specs in detail, but the previous author
- # accessed res['js']['error'] as well as js_answer['error'].
- # see the two lines commented out with "# ~?".
- if 'error' in res['js']:
-
- if res['js']['error'] == 'download_delay':
- self.retry(wait_time=res['js']['params']['next_download'])
- # ~? self.retry(wait_time=js_answer['params']['next_download'])
-
- elif 'Wrong file password' in res['js']['error'] \
- or 'You entered a wrong CAPTCHA code' in res['js']['error'] \
- or 'CAPTCHA Code nicht korrekt' in res['js']['error']:
- return None
-
- elif 'CAPTCHA' in res['js']['error']:
- self.logDebug("Error response is unknown, but mentions CAPTCHA")
- return None
-
- else:
- self.fail(res['js']['error'])
-
- if not 'answer' in res['js'] or not field in res['js']['answer']:
- self.error(_("JSON %s 2") % field)
-
- return res['js']['answer'][field]
-
-
-getInfo = create_getInfo(FilepostCom)
diff --git a/module/plugins/hoster/FilepupNet.py b/module/plugins/hoster/FilepupNet.py
deleted file mode 100644
index 6ac9994cc..000000000
--- a/module/plugins/hoster/FilepupNet.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# http://www.filepup.net/files/k5w4ZVoF1410184283.html
-# http://www.filepup.net/files/R4GBq9XH1410186553.html
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class FilepupNet(SimpleHoster):
- __name__ = "FilepupNet"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?filepup\.net/files/\w+'
-
- __description__ = """Filepup.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- NAME_PATTERN = r'>(?P<N>.+?)</h1>'
- SIZE_PATTERN = r'class="fa fa-archive"></i> \((?P<S>[\d.,]+) (?P<U>[\w^_]+)'
-
- OFFLINE_PATTERN = r'>This file has been deleted'
-
- LINK_FREE_PATTERN = r'(http://www\.filepup\.net/get/.+?)\''
-
-
- def setup(self):
- self.multiDL = False
- self.chunkLimit = 1
-
-
- def handleFree(self, pyfile):
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("Download link not found"))
-
- dl_link = m.group(1)
- self.download(dl_link, post={'task': "download"})
-
-
-getInfo = create_getInfo(FilepupNet)
diff --git a/module/plugins/hoster/FilerNet.py b/module/plugins/hoster/FilerNet.py
deleted file mode 100644
index 85ff7da33..000000000
--- a/module/plugins/hoster/FilerNet.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# http://filer.net/get/ivgf5ztw53et3ogd
-# http://filer.net/get/hgo14gzcng3scbvv
-
-import pycurl
-import re
-
-from urlparse import urljoin
-
-from pyload.plugin.internal.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class FilerNet(SimpleHoster):
- __name__ = "FilerNet"
- __type__ = "hoster"
- __version__ = "0.16"
-
- __pattern__ = r'https?://(?:www\.)?filer\.net/get/\w+'
-
- __description__ = """Filer.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- INFO_PATTERN = r'<h1 class="page-header">Free Download (?P<N>\S+) <small>(?P<S>[\w.]+) (?P<U>[\w^_]+)</small></h1>'
- OFFLINE_PATTERN = r'Nicht gefunden'
-
- LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'href="([^"]+)">Get download</a>'
-
-
- def checkErrors(self):
- # Wait between downloads
- m = re.search(r'musst du <span id="time">(\d+)</span> Sekunden warten', self.html)
- if m:
- errmsg = self.info['error'] = _("Wait between free downloads")
- self.retry(wait_time=int(m.group(1)), reason=errmsg)
-
- self.info.pop('error', None)
-
-
- def handleFree(self, pyfile):
- inputs = self.parseHtmlForm(input_names={'token': re.compile(r'.+')})[1]
- if 'token' not in inputs:
- self.error(_("Unable to detect token"))
-
- self.html = self.load(pyfile.url, post={'token': inputs['token']}, decode=True)
-
- inputs = self.parseHtmlForm(input_names={'hash': re.compile(r'.+')})[1]
- if 'hash' not in inputs:
- self.error(_("Unable to detect hash"))
-
- recaptcha = ReCaptcha(self)
- response, challenge = recaptcha.challenge()
-
- #@NOTE: Work-around for v0.4.9 just_header issue
- #@TODO: Check for v0.4.10
- self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 0)
- self.load(pyfile.url, post={'recaptcha_challenge_field': challenge,
- 'recaptcha_response_field' : response,
- 'hash' : inputs['hash']})
- self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 1)
-
- if 'location' in self.req.http.header.lower():
- self.link = re.search(r'location: (\S+)', self.req.http.header, re.I).group(1)
- self.correctCaptcha()
- else:
- self.invalidCaptcha()
-
-
-getInfo = create_getInfo(FilerNet)
diff --git a/module/plugins/hoster/FilerioCom.py b/module/plugins/hoster/FilerioCom.py
deleted file mode 100644
index 12b7e7705..000000000
--- a/module/plugins/hoster/FilerioCom.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class FilerioCom(XFSHoster):
- __name__ = "FilerioCom"
- __type__ = "hoster"
- __version__ = "0.07"
-
- __pattern__ = r'http://(?:www\.)?(filerio\.(in|com)|filekeen\.com)/\w{12}'
-
- __description__ = """FileRio.in hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- URL_REPLACEMENTS = [(r'filekeen\.com', "filerio.in")]
-
- OFFLINE_PATTERN = r'>&quot;File Not Found|File has been removed'
-
-
-getInfo = create_getInfo(FilerioCom)
diff --git a/module/plugins/hoster/FileserveCom.py b/module/plugins/hoster/FileserveCom.py
deleted file mode 100644
index cc977ac25..000000000
--- a/module/plugins/hoster/FileserveCom.py
+++ /dev/null
@@ -1,216 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.common.json_layer import json_loads
-from module.network.RequestFactory import getURL
-from module.plugins.Hoster import Hoster
-from module.plugins.Plugin import chunks
-from module.plugins.internal.CaptchaService import ReCaptcha
-from module.plugins.internal.SimpleHoster import secondsToMidnight
-from module.utils import parseFileSize
-
-
-def checkFile(plugin, urls):
- html = getURL(plugin.URLS[1], post={"urls": "\n".join(urls)}, decode=True)
-
- file_info = []
- for li in re.finditer(plugin.LINKCHECK_TR, html, re.S):
- try:
- cols = re.findall(plugin.LINKCHECK_TD, li.group(1))
- if cols:
- file_info.append((
- cols[1] if cols[1] != '--' else cols[0],
- parseFileSize(cols[2]) if cols[2] != '--' else 0,
- 2 if cols[3].startswith('Available') else 1,
- cols[0]))
- except Exception, e:
- continue
-
- return file_info
-
-
-class FileserveCom(Hoster):
- __name__ = "FileserveCom"
- __type__ = "hoster"
- __version__ = "0.54"
-
- __pattern__ = r'http://(?:www\.)?fileserve\.com/file/(?P<ID>[^/]+)'
-
- __description__ = """Fileserve.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("jeix", "jeix@hasnomail.de"),
- ("mkaay", "mkaay@mkaay.de"),
- ("Paul King", ""),
- ("zoidberg", "zoidberg@mujmail.cz")]
-
-
- URLS = ["http://www.fileserve.com/file/", "http://www.fileserve.com/link-checker.php",
- "http://www.fileserve.com/checkReCaptcha.php"]
- LINKCHECK_TR = r'<tr>\s*(<td>http://www\.fileserve\.com/file/.*?)</tr>'
- LINKCHECK_TD = r'<td>(?:<[^>]*>|&nbsp;)*([^<]*)'
-
- CAPTCHA_KEY_PATTERN = r'var reCAPTCHA_publickey=\'(.+?)\''
- LONG_WAIT_PATTERN = r'<li class="title">You need to wait (\d+) (\w+) to start another download\.</li>'
- LINK_EXPIRED_PATTERN = r'Your download link has expired'
- DAILY_LIMIT_PATTERN = r'Your daily download limit has been reached'
- NOT_LOGGED_IN_PATTERN = r'<form (name="loginDialogBoxForm"|id="login_form")|<li><a href="/login\.php">Login</a></li>'
-
-
- def setup(self):
- self.resumeDownload = self.multiDL = self.premium
- self.file_id = re.match(self.__pattern__, self.pyfile.url).group('ID')
- self.url = "%s%s" % (self.URLS[0], self.file_id)
-
- self.logDebug("File ID: %s URL: %s" % (self.file_id, self.url))
-
-
- def process(self, pyfile):
- pyfile.name, pyfile.size, status, self.url = checkFile(self, [self.url])[0]
- if status != 2:
- self.offline()
- self.logDebug("File Name: %s Size: %d" % (pyfile.name, pyfile.size))
-
- if self.premium:
- self.handlePremium()
- else:
- self.handleFree()
-
-
- def handleFree(self):
- self.html = self.load(self.url)
- action = self.load(self.url, post={"checkDownload": "check"}, decode=True)
- action = json_loads(action)
- self.logDebug(action)
-
- if "fail" in action:
- if action['fail'] == "timeLimit":
- self.html = self.load(self.url, post={"checkDownload": "showError", "errorType": "timeLimit"},
- decode=True)
-
- self.doLongWait(re.search(self.LONG_WAIT_PATTERN, self.html))
-
- elif action['fail'] == "parallelDownload":
- self.logWarning(_("Parallel download error, now waiting 60s"))
- self.retry(wait_time=60, reason=_("parallelDownload"))
-
- else:
- self.fail(_("Download check returned: %s") % action['fail'])
-
- elif "success" in action:
- if action['success'] == "showCaptcha":
- self.doCaptcha()
- self.doTimmer()
- elif action['success'] == "showTimmer":
- self.doTimmer()
-
- else:
- self.error(_("Unknown server response"))
-
- # show download link
- res = self.load(self.url, post={"downloadLink": "show"}, decode=True)
- self.logDebug("Show downloadLink response: %s" % res)
- if "fail" in res:
- self.error(_("Couldn't retrieve download url"))
-
- # this may either download our file or forward us to an error page
- self.download(self.url, post={"download": "normal"})
- self.logDebug(self.req.http.lastEffectiveURL)
-
- check = self.checkDownload({"expired": self.LINK_EXPIRED_PATTERN,
- "wait" : re.compile(self.LONG_WAIT_PATTERN),
- "limit" : self.DAILY_LIMIT_PATTERN})
-
- if check == "expired":
- self.logDebug("Download link was expired")
- self.retry()
-
- elif check == "wait":
- self.doLongWait(self.lastCheck)
-
- elif check == "limit":
- self.logWarning(_("Download limited reached for today"))
- self.setWait(secondsToMidnight(gmt=2), True)
- self.wait()
- self.retry()
-
- self.thread.m.reconnecting.wait(3) # Ease issue with later downloads appearing to be in parallel
-
-
- def doTimmer(self):
- res = self.load(self.url, post={"downloadLink": "wait"}, decode=True)
- self.logDebug("Wait response: %s" % res[:80])
-
- if "fail" in res:
- self.fail(_("Failed getting wait time"))
-
- if self.__name__ == "FilejungleCom":
- m = re.search(r'"waitTime":(\d+)', res)
- if m is None:
- self.fail(_("Cannot get wait time"))
- wait_time = int(m.group(1))
- else:
- wait_time = int(res) + 3
-
- self.setWait(wait_time)
- self.wait()
-
-
- def doCaptcha(self):
- captcha_key = re.search(self.CAPTCHA_KEY_PATTERN, self.html).group(1)
- recaptcha = ReCaptcha(self)
-
- for _i in xrange(5):
- response, challenge = recaptcha.challenge(captcha_key)
- res = json_loads(self.load(self.URLS[2],
- post={'recaptcha_challenge_field' : challenge,
- 'recaptcha_response_field' : response,
- 'recaptcha_shortencode_field': self.file_id}))
- if not res['success']:
- self.invalidCaptcha()
- else:
- self.correctCaptcha()
- break
- else:
- self.fail(_("Invalid captcha"))
-
-
- def doLongWait(self, m):
- wait_time = (int(m.group(1)) * {'seconds': 1, 'minutes': 60, 'hours': 3600}[m.group(2)]) if m else 12 * 60
- self.setWait(wait_time, True)
- self.wait()
- self.retry()
-
-
- def handlePremium(self):
- premium_url = None
- if self.__name__ == "FileserveCom":
- #try api download
- res = self.load("http://app.fileserve.com/api/download/premium/",
- post={"username": self.user,
- "password": self.account.getAccountData(self.user)['password'],
- "shorten": self.file_id},
- decode=True)
- if res:
- res = json_loads(res)
- if res['error_code'] == "302":
- premium_url = res['next']
- elif res['error_code'] in ["305", "500"]:
- self.tempOffline()
- elif res['error_code'] in ["403", "605"]:
- self.resetAccount()
- elif res['error_code'] in ["606", "607", "608"]:
- self.offline()
- else:
- self.logError(res['error_code'], res['error_message'])
-
- self.download(premium_url or self.pyfile.url)
-
- if not premium_url and self.checkDownload({"login": re.compile(self.NOT_LOGGED_IN_PATTERN)}):
- self.account.relogin(self.user)
- self.retry(reason=_("Not logged in"))
-
-
-def getInfo(urls):
- for chunk in chunks(urls, 100):
- yield checkFile(FileserveCom, chunk)
diff --git a/module/plugins/hoster/FileshareInUa.py b/module/plugins/hoster/FileshareInUa.py
deleted file mode 100644
index 5f5089e54..000000000
--- a/module/plugins/hoster/FileshareInUa.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class FileshareInUa(DeadHoster):
- __name__ = "FileshareInUa"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'https?://(?:www\.)?fileshare\.in\.ua/\w{7}'
-
- __description__ = """Fileshare.in.ua hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("fwannmacher", "felipe@warhammerproject.com")]
-
-
-getInfo = create_getInfo(FileshareInUa)
diff --git a/module/plugins/hoster/FilesonicCom.py b/module/plugins/hoster/FilesonicCom.py
deleted file mode 100644
index c2b87d4d7..000000000
--- a/module/plugins/hoster/FilesonicCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class FilesonicCom(DeadHoster):
- __name__ = "FilesonicCom"
- __type__ = "hoster"
- __version__ = "0.35"
-
- __pattern__ = r'http://(?:www\.)?filesonic\.com/file/\w+'
-
- __description__ = """Filesonic.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("jeix", "jeix@hasnomail.de"),
- ("paulking", "")]
-
-
-getInfo = create_getInfo(FilesonicCom)
diff --git a/module/plugins/hoster/FilezyNet.py b/module/plugins/hoster/FilezyNet.py
deleted file mode 100644
index 1fcc9363d..000000000
--- a/module/plugins/hoster/FilezyNet.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class FilezyNet(DeadHoster):
- __name__ = "FilezyNet"
- __type__ = "hoster"
- __version__ = "0.20"
-
- __pattern__ = r'http://(?:www\.)?filezy\.net/\w{12}'
-
- __description__ = """Filezy.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = []
-
-
-getInfo = create_getInfo(FilezyNet)
diff --git a/module/plugins/hoster/FiredriveCom.py b/module/plugins/hoster/FiredriveCom.py
deleted file mode 100644
index 3395fc261..000000000
--- a/module/plugins/hoster/FiredriveCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class FiredriveCom(DeadHoster):
- __name__ = "FiredriveCom"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'https?://(?:www\.)?(firedrive|putlocker)\.com/(mobile/)?(file|embed)/(?P<ID>\w+)'
-
- __description__ = """Firedrive.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
-getInfo = create_getInfo(FiredriveCom)
diff --git a/module/plugins/hoster/FourSharedCom.py b/module/plugins/hoster/FourSharedCom.py
deleted file mode 100644
index 8d13ea0b7..000000000
--- a/module/plugins/hoster/FourSharedCom.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class FourSharedCom(SimpleHoster):
- __name__ = "FourSharedCom"
- __type__ = "hoster"
- __version__ = "0.31"
-
- __pattern__ = r'https?://(?:www\.)?4shared(\-china)?\.com/(account/)?(download|get|file|document|photo|video|audio|mp3|office|rar|zip|archive|music)/.+'
-
- __description__ = """4Shared.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("jeix", "jeix@hasnomail.de"),
- ("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<meta name="title" content="(?P<N>.+?)"'
- SIZE_PATTERN = r'<span title="Size: (?P<S>[\d.,]+) (?P<U>[\w^_]+)">'
- OFFLINE_PATTERN = r'The file link that you requested is not valid\.|This file was deleted.'
-
- NAME_REPLACEMENTS = [(r"&#(\d+).", lambda m: unichr(int(m.group(1))))]
- SIZE_REPLACEMENTS = [(",", "")]
-
- DIRECT_LINK = False
- LOGIN_ACCOUNT = True
-
- LINK_FREE_PATTERN = r'name="d3link" value="(.*?)"'
- LINK_BTN_PATTERN = r'id="btnLink" href="(.*?)"'
-
- ID_PATTERN = r'name="d3fid" value="(.*?)"'
-
-
- def handleFree(self, pyfile):
- m = re.search(self.LINK_BTN_PATTERN, self.html)
- if m:
- link = m.group(1)
- else:
- link = re.sub(r'/(download|get|file|document|photo|video|audio)/', r'/get/', pyfile.url)
-
- self.html = self.load(link)
-
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("Download link"))
-
- self.link = m.group(1)
-
- try:
- m = re.search(self.ID_PATTERN, self.html)
- res = self.load('http://www.4shared.com/web/d2/getFreeDownloadLimitInfo?fileId=%s' % m.group(1))
- self.logDebug(res)
- except Exception:
- pass
-
- self.wait(20)
-
-
-getInfo = create_getInfo(FourSharedCom)
diff --git a/module/plugins/hoster/FreakshareCom.py b/module/plugins/hoster/FreakshareCom.py
deleted file mode 100644
index 9a11f933d..000000000
--- a/module/plugins/hoster/FreakshareCom.py
+++ /dev/null
@@ -1,180 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.Hoster import Hoster
-from module.plugins.internal.CaptchaService import ReCaptcha
-from module.plugins.internal.SimpleHoster import secondsToMidnight
-
-
-class FreakshareCom(Hoster):
- __name__ = "FreakshareCom"
- __type__ = "hoster"
- __version__ = "0.40"
-
- __pattern__ = r'http://(?:www\.)?freakshare\.(net|com)/files/\S*?/'
-
- __description__ = """Freakshare.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("sitacuisses", "sitacuisses@yahoo.de"),
- ("spoob", "spoob@pyload.org"),
- ("mkaay", "mkaay@mkaay.de"),
- ("Toilal", "toilal.dev@gmail.com")]
-
-
- def setup(self):
- self.multiDL = False
- self.req_opts = []
-
-
- def process(self, pyfile):
- self.pyfile = pyfile
-
- pyfile.url = pyfile.url.replace("freakshare.net/", "freakshare.com/")
-
- if self.account:
- self.html = self.load(pyfile.url, cookies=False)
- pyfile.name = self.get_file_name()
- self.download(pyfile.url)
-
- else:
- self.prepare()
- self.get_file_url()
-
- self.download(pyfile.url, post=self.req_opts)
-
- check = self.checkDownload({"bad" : "bad try",
- "paralell" : "> Sorry, you cant download more then 1 files at time. <",
- "empty" : "Warning: Unknown: Filename cannot be empty",
- "wrong_captcha" : "Wrong Captcha!",
- "downloadserver": "No Downloadserver. Please try again later!"})
-
- if check == "bad":
- self.fail(_("Bad Try"))
-
- elif check == "paralell":
- self.setWait(300, True)
- self.wait()
- self.retry()
-
- elif check == "empty":
- self.fail(_("File not downloadable"))
-
- elif check == "wrong_captcha":
- self.invalidCaptcha()
- self.retry()
-
- elif check == "downloadserver":
- self.retry(5, 15 * 60, _("No Download server"))
-
-
- def prepare(self):
- pyfile = self.pyfile
-
- self.download_html()
-
- if not self.file_exists():
- self.offline()
-
- self.setWait(self.get_waiting_time())
-
- pyfile.name = self.get_file_name()
- pyfile.size = self.get_file_size()
-
- self.wait()
-
- return True
-
-
- def download_html(self):
- self.load("http://freakshare.com/index.php", {"language": "EN"}) # Set english language in server session
- self.html = self.load(self.pyfile.url)
-
-
- def get_file_url(self):
- """ returns the absolute downloadable filepath
- """
- if not self.html:
- self.download_html()
- if not self.wantReconnect:
- self.req_opts = self.get_download_options() # get the Post options for the Request
- #file_url = self.pyfile.url
- #return file_url
- else:
- self.offline()
-
-
- def get_file_name(self):
- if not self.html:
- self.download_html()
- if not self.wantReconnect:
- file_name = re.search(r"<h1\sclass=\"box_heading\"\sstyle=\"text-align:center;\">([^ ]+)", self.html)
- if file_name is not None:
- file_name = file_name.group(1)
- else:
- file_name = self.pyfile.url
- return file_name
- else:
- return self.pyfile.url
-
-
- def get_file_size(self):
- size = 0
- if not self.html:
- self.download_html()
- if not self.wantReconnect:
- file_size_check = re.search(
- r"<h1\sclass=\"box_heading\"\sstyle=\"text-align:center;\">[^ ]+ - ([^ ]+) (\w\w)yte", self.html)
- if file_size_check is not None:
- units = float(file_size_check.group(1).replace(",", ""))
- pow = {'KB': 1, 'MB': 2, 'GB': 3}[file_size_check.group(2)]
- size = int(units * 1024 ** pow)
-
- return size
-
-
- def get_waiting_time(self):
- if not self.html:
- self.download_html()
-
- if "Your Traffic is used up for today" in self.html:
- self.wantReconnect = True
- return secondsToMidnight(gmt=2)
-
- timestring = re.search('\s*var\s(?:downloadWait|time)\s=\s(\d*)[\d.]*;', self.html)
- if timestring:
- return int(timestring.group(1))
- else:
- return 60
-
-
- def file_exists(self):
- """ returns True or False
- """
- if not self.html:
- self.download_html()
- if re.search(r"This file does not exist!", self.html) is not None:
- return False
- else:
- return True
-
-
- def get_download_options(self):
- re_envelope = re.search(r".*?value=\"Free\sDownload\".*?\n*?(.*?<.*?>\n*)*?\n*\s*?</form>",
- self.html).group(0) # get the whole request
- to_sort = re.findall(r"<input\stype=\"hidden\"\svalue=\"(.*?)\"\sname=\"(.*?)\"\s\/>", re_envelope)
- request_options = dict((n, v) for (v, n) in to_sort)
-
- herewego = self.load(self.pyfile.url, None, request_options) # the actual download-Page
-
- to_sort = re.findall(r"<input\stype=\".*?\"\svalue=\"(\S*?)\".*?name=\"(\S*?)\"\s.*?\/>", herewego)
- request_options = dict((n, v) for (v, n) in to_sort)
-
- challenge = re.search(r"http://api\.recaptcha\.net/challenge\?k=(\w+)", herewego)
-
- if challenge:
- re_captcha = ReCaptcha(self)
- (request_options['recaptcha_challenge_field'],
- request_options['recaptcha_response_field']) = re_captcha.challenge(challenge.group(1))
-
- return request_options
diff --git a/module/plugins/hoster/FreeWayMe.py b/module/plugins/hoster/FreeWayMe.py
deleted file mode 100644
index 76ffca505..000000000
--- a/module/plugins/hoster/FreeWayMe.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-
-
-class FreeWayMe(MultiHoster):
- __name__ = "FreeWayMe"
- __type__ = "hoster"
- __version__ = "0.16"
-
- __pattern__ = r'https://(?:www\.)?free-way\.me/.+'
-
- __description__ = """FreeWayMe multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Nicolas Giese", "james@free-way.me")]
-
-
- def setup(self):
- self.resumeDownload = False
- self.multiDL = self.premium
- self.chunkLimit = 1
-
-
- def handlePremium(self, pyfile):
- user, data = self.account.selectAccount()
-
- for _i in xrange(5):
- # try it five times
- header = self.load("https://www.free-way.me/load.php",
- get={'multiget': 7,
- 'url' : pyfile.url,
- 'user' : user,
- 'pw' : self.account.getAccountData(user)['password'],
- 'json' : ""},
- just_header=True)
-
- if 'location' in header:
- headers = self.load(header['location'], just_header=True)
- if headers['code'] == 500:
- # error on 2nd stage
- self.logError(_("Error [stage2]"))
- else:
- # seems to work..
- self.download(header['location'])
- break
- else:
- # error page first stage
- self.logError(_("Error [stage1]"))
-
- #@TODO: handle errors
-
-
-getInfo = create_getInfo(FreeWayMe)
diff --git a/module/plugins/hoster/FreevideoCz.py b/module/plugins/hoster/FreevideoCz.py
deleted file mode 100644
index 86c30e64c..000000000
--- a/module/plugins/hoster/FreevideoCz.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class FreevideoCz(DeadHoster):
- __name__ = "FreevideoCz"
- __type__ = "hoster"
- __version__ = "0.30"
-
- __pattern__ = r'http://(?:www\.)?freevideo\.cz/vase-videa/.+'
-
- __description__ = """Freevideo.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(FreevideoCz) \ No newline at end of file
diff --git a/module/plugins/hoster/GigapetaCom.py b/module/plugins/hoster/GigapetaCom.py
deleted file mode 100644
index d12084d42..000000000
--- a/module/plugins/hoster/GigapetaCom.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from random import randint
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class GigapetaCom(SimpleHoster):
- __name__ = "GigapetaCom"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?gigapeta\.com/dl/\w+'
-
- __description__ = """GigaPeta.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<img src=".*" alt="file" />-->\s*(?P<N>.*?)\s*</td>'
- SIZE_PATTERN = r'<th>\s*Size\s*</th>\s*<td>\s*(?P<S>.*?)\s*</td>'
- OFFLINE_PATTERN = r'<div id="page_error">'
-
- COOKIES = [("gigapeta.com", "lang", "us")]
-
-
- def handleFree(self, pyfile):
- captcha_key = str(randint(1, 100000000))
- captcha_url = "http://gigapeta.com/img/captcha.gif?x=%s" % captcha_key
-
- for _i in xrange(5):
- self.checkErrors()
-
- captcha = self.decryptCaptcha(captcha_url)
- self.html = self.load(pyfile.url,
- post={'captcha_key': captcha_key,
- 'captcha' : captcha,
- 'download' : "Download"},
- follow_location=False)
-
- m = re.search(r'Location\s*:\s*(.+)', self.req.http.header, re.I)
- if m:
- download_url = m.group(1)
- break
- elif "Entered figures don&#96;t coincide with the picture" in self.html:
- self.invalidCaptcha()
- else:
- self.fail(_("No valid captcha code entered"))
-
- self.download(download_url)
-
-
- def checkErrors(self):
- if "All threads for IP" in self.html:
- self.logDebug("Your IP is already downloading a file")
- self.wait(5 * 60, True)
- self.retry()
-
- self.info.pop('error', None)
-
-
-getInfo = create_getInfo(GigapetaCom)
diff --git a/module/plugins/hoster/GooIm.py b/module/plugins/hoster/GooIm.py
deleted file mode 100644
index 331d63a99..000000000
--- a/module/plugins/hoster/GooIm.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# https://goo.im/devs/liquidsmooth/3.x/codina/Nightly/LS-KK-v3.2-2014-08-01-codina.zip
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class GooIm(SimpleHoster):
- __name__ = "GooIm"
- __type__ = "hoster"
- __version__ = "0.04"
-
- __pattern__ = r'https?://(?:www\.)?goo\.im/.+'
-
- __description__ = """Goo.im hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
-
-
- NAME_PATTERN = r'You will be redirected to .*(?P<N>[^/ ]+) in'
- OFFLINE_PATTERN = r'The file you requested was not found'
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = True
-
-
- def handleFree(self, pyfile):
- self.wait(10)
- self.download(pyfile.url, cookies=True)
-
-
-getInfo = create_getInfo(GooIm)
diff --git a/module/plugins/hoster/GoogledriveCom.py b/module/plugins/hoster/GoogledriveCom.py
deleted file mode 100644
index 0c8ca9c52..000000000
--- a/module/plugins/hoster/GoogledriveCom.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# -*- coding: utf-8 -*
-#
-# Test links:
-# https://drive.google.com/file/d/0B6RNTe4ygItBQm15RnJiTmMyckU/view?pli=1
-
-import re
-
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
-from module.utils import html_unescape
-
-
-class GoogledriveCom(SimpleHoster):
- __name__ = "GoogledriveCom"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'https?://(?:www\.)?drive\.google\.com/file/.+'
-
- __description__ = """Drive.google.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
-
-
- DISPOSITION = False
-
- NAME_PATTERN = r'"og:title" content="(?P<N>.*?)">'
- OFFLINE_PATTERN = r'align="center"><p class="errorMessage"'
-
-
- def setup(self):
- self.multiDL = True
- self.resumeDownload = True
- self.chunkLimit = 1
-
-
- def handleFree(self, pyfile):
- try:
- link1 = re.search(r'"(https://docs.google.com/uc\?id.*?export=download)",',
- self.html.decode('unicode-escape')).group(1)
-
- except AttributeError:
- self.error(_("Hop #1 not found"))
-
- else:
- self.logDebug("Next hop: %s" % link1)
-
- self.html = self.load(link1).decode('unicode-escape')
-
- try:
- link2 = html_unescape(re.search(r'href="(/uc\?export=download.*?)">',
- self.html).group(1))
-
- except AttributeError:
- self.error(_("Hop #2 not found"))
-
- else:
- self.logDebug("Next hop: %s" % link2)
-
- link3 = self.load("https://docs.google.com" + link2, just_header=True)
- self.logDebug("DL-Link: %s" % link3['location'])
-
- self.link = link3['location']
-
-
-getInfo = create_getInfo(GoogledriveCom)
diff --git a/module/plugins/hoster/HellshareCz.py b/module/plugins/hoster/HellshareCz.py
deleted file mode 100644
index 8a00e01b0..000000000
--- a/module/plugins/hoster/HellshareCz.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from urlparse import urljoin
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class HellshareCz(SimpleHoster):
- __name__ = "HellshareCz"
- __type__ = "hoster"
- __version__ = "0.85"
-
- __pattern__ = r'http://(?:www\.)?hellshare\.(?:cz|com|sk|hu|pl)/[^?]*/\d+'
-
- __description__ = """Hellshare.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- CHECK_TRAFFIC = True
- LOGIN_ACCOUNT = True
-
- NAME_PATTERN = r'<h1 id="filename"[^>]*>(?P<N>[^<]+)</h1>'
- SIZE_PATTERN = r'<strong id="FileSize_master">(?P<S>[\d.,]+)&nbsp;(?P<U>[\w^_]+)</strong>'
- OFFLINE_PATTERN = r'<h1>File not found.</h1>'
-
- LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'<a href="([^?]+/(\d+)/\?do=(fileDownloadButton|relatedFileDownloadButton-\2)-showDownloadWindow)"'
-
-
- def setup(self):
- self.resumeDownload = self.multiDL = bool(self.account)
- self.chunkLimit = 1
-
-
-getInfo = create_getInfo(HellshareCz)
diff --git a/module/plugins/hoster/HellspyCz.py b/module/plugins/hoster/HellspyCz.py
deleted file mode 100644
index 0d33b35b9..000000000
--- a/module/plugins/hoster/HellspyCz.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class HellspyCz(DeadHoster):
- __name__ = "HellspyCz"
- __type__ = "hoster"
- __version__ = "0.28"
-
- __pattern__ = r'http://(?:www\.)?(?:hellspy\.(?:cz|com|sk|hu|pl)|sciagaj\.pl)(/\S+/\d+)'
-
- __description__ = """HellSpy.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(HellspyCz)
diff --git a/module/plugins/hoster/HotfileCom.py b/module/plugins/hoster/HotfileCom.py
deleted file mode 100644
index b64bb5fd7..000000000
--- a/module/plugins/hoster/HotfileCom.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class HotfileCom(DeadHoster):
- __name__ = "HotfileCom"
- __type__ = "hoster"
- __version__ = "0.37"
-
- __pattern__ = r'https?://(?:www\.)?hotfile\.com/dl/\d+/\w+'
-
- __description__ = """Hotfile.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("sitacuisses", "sitacuisses@yhoo.de"),
- ("spoob", "spoob@pyload.org"),
- ("mkaay", "mkaay@mkaay.de"),
- ("JoKoT3", "jokot3@gmail.com")]
-
-
-getInfo = create_getInfo(HotfileCom)
diff --git a/module/plugins/hoster/HugefilesNet.py b/module/plugins/hoster/HugefilesNet.py
deleted file mode 100644
index f5085c8c3..000000000
--- a/module/plugins/hoster/HugefilesNet.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class HugefilesNet(XFSHoster):
- __name__ = "HugefilesNet"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'http://(?:www\.)?hugefiles\.net/\w{12}'
-
- __description__ = """Hugefiles.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- SIZE_PATTERN = r'File Size:</span>\s*<span[^>]*>(?P<S>[^<]+)</span></div>'
-
- FORM_INPUTS_MAP = {'ctype': re.compile(r'\d+')}
-
-
-getInfo = create_getInfo(HugefilesNet)
diff --git a/module/plugins/hoster/HundredEightyUploadCom.py b/module/plugins/hoster/HundredEightyUploadCom.py
deleted file mode 100644
index 2edb6310d..000000000
--- a/module/plugins/hoster/HundredEightyUploadCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class HundredEightyUploadCom(XFSHoster):
- __name__ = "HundredEightyUploadCom"
- __type__ = "hoster"
- __version__ = "0.04"
-
- __pattern__ = r'http://(?:www\.)?180upload\.com/\w{12}'
-
- __description__ = """180upload.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
-
-getInfo = create_getInfo(HundredEightyUploadCom)
diff --git a/module/plugins/hoster/IFileWs.py b/module/plugins/hoster/IFileWs.py
deleted file mode 100644
index 59d9c7f40..000000000
--- a/module/plugins/hoster/IFileWs.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class IFileWs(DeadHoster):
- __name__ = "IFileWs"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?ifile\.ws/\w{12}'
-
- __description__ = """Ifile.ws hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("z00nx", "z00nx0@gmail.com")]
-
-
-getInfo = create_getInfo(IFileWs)
diff --git a/module/plugins/hoster/IcyFilesCom.py b/module/plugins/hoster/IcyFilesCom.py
deleted file mode 100644
index 201626fa5..000000000
--- a/module/plugins/hoster/IcyFilesCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class IcyFilesCom(DeadHoster):
- __name__ = "IcyFilesCom"
- __type__ = "hoster"
- __version__ = "0.06"
-
- __pattern__ = r'http://(?:www\.)?icyfiles\.com/(.+)'
-
- __description__ = """IcyFiles.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("godofdream", "soilfiction@gmail.com")]
-
-
-getInfo = create_getInfo(IcyFilesCom)
diff --git a/module/plugins/hoster/IfileIt.py b/module/plugins/hoster/IfileIt.py
deleted file mode 100644
index 056b05a65..000000000
--- a/module/plugins/hoster/IfileIt.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class IfileIt(DeadHoster):
- __name__ = "IfileIt"
- __type__ = "hoster"
- __version__ = "0.29"
-
- __pattern__ = r'^unmatchable$'
-
- __description__ = """Ifile.it"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(IfileIt)
diff --git a/module/plugins/hoster/IfolderRu.py b/module/plugins/hoster/IfolderRu.py
deleted file mode 100644
index 33da64ba2..000000000
--- a/module/plugins/hoster/IfolderRu.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class IfolderRu(SimpleHoster):
- __name__ = "IfolderRu"
- __type__ = "hoster"
- __version__ = "0.39"
-
- __pattern__ = r'http://(?:www\.)?(?:ifolder\.ru|rusfolder\.(?:com|net|ru))/(?:files/)?(?P<ID>\d+)'
-
- __description__ = """Ifolder.ru hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- SIZE_REPLACEMENTS = [(u'Кб', 'KB'), (u'Мб', 'MB'), (u'Гб', 'GB')]
-
- NAME_PATTERN = ur'(?:<div><span>)?НазваМОе:(?:</span>)? <b>(?P<N>[^<]+)</b><(?:/div|br)>'
- SIZE_PATTERN = ur'(?:<div><span>)?РазЌер:(?:</span>)? <b>(?P<S>[^<]+)</b><(?:/div|br)>'
- OFFLINE_PATTERN = ur'<p>Ѐайл МПЌер <b>[^<]*</b> (Ме МайЎеМ|уЎалеМ) !!!</p>'
-
- SESSION_ID_PATTERN = r'<a href=(http://ints\.(?:rusfolder\.com|ifolder\.ru)/ints/sponsor/\?bi=\d*&session=([^&]+)&u=[^>]+)>'
- INTS_SESSION_PATTERN = r'\(\'ints_session\'\);\s*if\(tag\)\{tag\.value = "([^"]+)";\}'
- HIDDEN_INPUT_PATTERN = r'var v = .*?name=\'(.+?)\' value=\'1\''
-
- LINK_FREE_PATTERN = r'<a id="download_file_href" href="([^"]+)"'
-
- WRONG_CAPTCHA_PATTERN = ur'<font color=Red>МеверМый кПЎ,<br>ввеЎОте еще раз</font><br>'
-
-
- def setup(self):
- self.resumeDownload = self.multiDL = bool(self.account)
- self.chunkLimit = 1
-
-
- def handleFree(self, pyfile):
- self.html = self.load("http://rusfolder.com/%s" % self.info['pattern']['ID'], cookies=True, decode=True)
- self.getFileInfo()
-
- url = re.search(r"location\.href = '(http://ints\..*?=)'", self.html).group(1)
- self.html = self.load(url, cookies=True, decode=True)
-
- url, session_id = re.search(self.SESSION_ID_PATTERN, self.html).groups()
- self.html = self.load(url, cookies=True, decode=True)
-
- url = "http://ints.rusfolder.com/ints/frame/?session=%s" % session_id
- self.html = self.load(url, cookies=True)
-
- self.wait(31, False)
-
- captcha_url = "http://ints.rusfolder.com/random/images/?session=%s" % session_id
- for _i in xrange(5):
- self.html = self.load(url, cookies=True)
- action, inputs = self.parseHtmlForm('ID="Form1"')
- inputs['ints_session'] = re.search(self.INTS_SESSION_PATTERN, self.html).group(1)
- inputs[re.search(self.HIDDEN_INPUT_PATTERN, self.html).group(1)] = '1'
- inputs['confirmed_number'] = self.decryptCaptcha(captcha_url, cookies=True)
- inputs['action'] = '1'
- self.logDebug(inputs)
-
- self.html = self.load(url, decode=True, cookies=True, post=inputs)
- if self.WRONG_CAPTCHA_PATTERN in self.html:
- self.invalidCaptcha()
- else:
- break
- else:
- self.fail(_("Invalid captcha"))
-
- self.link = re.search(self.LINK_PATTERN, self.html).group(1)
-
-
-getInfo = create_getInfo(IfolderRu)
diff --git a/module/plugins/hoster/JumbofilesCom.py b/module/plugins/hoster/JumbofilesCom.py
deleted file mode 100644
index 2331179bc..000000000
--- a/module/plugins/hoster/JumbofilesCom.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class JumbofilesCom(SimpleHoster):
- __name__ = "JumbofilesCom"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?jumbofiles\.com/(?P<ID>\w{12})'
-
- __description__ = """JumboFiles.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("godofdream", "soilfiction@gmail.com")]
-
-
- INFO_PATTERN = r'<TR><TD>(?P<N>[^<]+?)\s*<small>\((?P<S>[\d.,]+)\s*(?P<U>[\w^_]+)'
- OFFLINE_PATTERN = r'Not Found or Deleted / Disabled due to inactivity or DMCA'
- LINK_FREE_PATTERN = r'<meta http-equiv="refresh" content="10;url=(.+)">'
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = True
-
-
- def handleFree(self, pyfile):
- post_data = {"id": self.info['pattern']['ID'], "op": "download3", "rand": ""}
- html = self.load(self.pyfile.url, post=post_data, decode=True)
- self.link = re.search(self.LINK_FREE_PATTERN, html).group(1)
-
-
-getInfo = create_getInfo(JumbofilesCom)
diff --git a/module/plugins/hoster/JunocloudMe.py b/module/plugins/hoster/JunocloudMe.py
deleted file mode 100644
index ad37b01e4..000000000
--- a/module/plugins/hoster/JunocloudMe.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class JunocloudMe(XFSHoster):
- __name__ = "JunocloudMe"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'http://(?:\w+\.)?junocloud\.me/\w{12}'
-
- __description__ = """Junocloud.me hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("guidobelix", "guidobelix@hotmail.it")]
-
-
- URL_REPLACEMENTS = [(r'//(www\.)?junocloud', "//dl3.junocloud")]
-
- OFFLINE_PATTERN = r'>No such file with this filename<'
- TEMP_OFFLINE_PATTERN = r'The page may have been renamed, removed or be temporarily unavailable.<'
-
-
-getInfo = create_getInfo(JunocloudMe)
diff --git a/module/plugins/hoster/Keep2ShareCc.py b/module/plugins/hoster/Keep2ShareCc.py
deleted file mode 100644
index 3ed11aa13..000000000
--- a/module/plugins/hoster/Keep2ShareCc.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urlparse import urljoin
-
-from module.plugins.internal.CaptchaService import ReCaptcha
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class Keep2ShareCc(SimpleHoster):
- __name__ = "Keep2ShareCc"
- __type__ = "hoster"
- __version__ = "0.21"
-
- __pattern__ = r'https?://(?:www\.)?(keep2share|k2s|keep2s)\.cc/file/(?P<ID>\w+)'
-
- __description__ = """Keep2Share.cc hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- URL_REPLACEMENTS = [(__pattern__ + ".*", "http://k2s.cc/file/\g<ID>")]
-
- NAME_PATTERN = r'File: <span>(?P<N>.+)</span>'
- SIZE_PATTERN = r'Size: (?P<S>[^<]+)</div>'
-
- OFFLINE_PATTERN = r'File not found or deleted|Sorry, this file is blocked or deleted|Error 404'
- TEMP_OFFLINE_PATTERN = r'Downloading blocked due to'
-
- LINK_FREE_PATTERN = r'"([^"]+url.html?file=.+?)"|window\.location\.href = \'(.+?)\';'
- LINK_PREMIUM_PATTERN = r'window\.location\.href = \'(.+?)\';'
-
- CAPTCHA_PATTERN = r'src="(/file/captcha\.html.+?)"'
-
- WAIT_PATTERN = r'Please wait ([\d:]+) to download this file'
- TEMP_ERROR_PATTERN = r'>\s*(Download count files exceed|Traffic limit exceed|Free account does not allow to download more than one file at the same time)'
- ERROR_PATTERN = r'>\s*(Free user can\'t download large files|You no can access to this file|This download available only for premium users|This is private file)'
-
-
- def checkErrors(self):
- m = re.search(self.TEMP_ERROR_PATTERN, self.html)
- if m:
- self.info['error'] = m.group(1)
- self.wantReconnect = True
- self.retry(wait_time=30 * 60, reason=m.group(0))
-
- m = re.search(self.ERROR_PATTERN, self.html)
- if m:
- errmsg = self.info['error'] = m.group(1)
- self.error(errmsg)
-
- m = re.search(self.WAIT_PATTERN, self.html)
- if m:
- self.logDebug("Hoster told us to wait for %s" % m.group(1))
-
- # string to time convert courtesy of https://stackoverflow.com/questions/10663720
- ftr = [3600, 60, 1]
- wait_time = sum(a * b for a, b in zip(ftr, map(int, m.group(1).split(':'))))
-
- self.wantReconnect = True
- self.retry(wait_time=wait_time, reason="Please wait to download this file")
-
- self.info.pop('error', None)
-
-
- def handleFree(self, pyfile):
- self.fid = re.search(r'<input type="hidden" name="slow_id" value="([^"]+)">', self.html).group(1)
- self.html = self.load(pyfile.url, post={'yt0': '', 'slow_id': self.fid})
-
- self.checkErrors()
-
- m = re.search(self.LINK_FREE_PATTERN, self.html)
-
- if m is None:
- self.handleCaptcha()
-
- self.wait(30)
-
- self.html = self.load(pyfile.url)
-
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("Free download link not found"))
-
- self.link = m.group(1)
- def handleCaptcha(self):
- recaptcha = ReCaptcha(self)
- post_data = {'free' : 1,
- 'freeDownloadRequest': 1,
- 'uniqueId' : self.fid,
- 'yt0' : ''}
-
- m = re.search(self.CAPTCHA_PATTERN, self.html)
- if m:
- captcha_url = urljoin("http://k2s.cc/", m.group(1))
- post_data['CaptchaForm[code]'] = self.decryptCaptcha(captcha_url)
- else:
- response, challenge = recaptcha.challenge()
- post_data.update({'recaptcha_challenge_field': challenge,
- 'recaptcha_response_field' : response})
-
- self.html = self.load(self.pyfile.url, post=post_data)
-
- if 'verification code is incorrect' not in self.html:
- self.correctCaptcha()
- else:
- self.invalidCaptcha()
-
-
-getInfo = create_getInfo(Keep2ShareCc)
diff --git a/module/plugins/hoster/KickloadCom.py b/module/plugins/hoster/KickloadCom.py
deleted file mode 100644
index 1f0c41f3d..000000000
--- a/module/plugins/hoster/KickloadCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class KickloadCom(DeadHoster):
- __name__ = "KickloadCom"
- __type__ = "hoster"
- __version__ = "0.21"
-
- __pattern__ = r'http://(?:www\.)?kickload\.com/get/.+'
-
- __description__ = """Kickload.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("mkaay", "mkaay@mkaay.de")]
-
-
-getInfo = create_getInfo(KickloadCom)
diff --git a/module/plugins/hoster/KingfilesNet.py b/module/plugins/hoster/KingfilesNet.py
deleted file mode 100644
index 73fa494b0..000000000
--- a/module/plugins/hoster/KingfilesNet.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.captcha import SolveMedia
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class KingfilesNet(SimpleHoster):
- __name__ = "KingfilesNet"
- __type__ = "hoster"
- __version__ = "0.07"
-
- __pattern__ = r'http://(?:www\.)?kingfiles\.net/(?P<ID>\w{12})'
-
- __description__ = """Kingfiles.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- NAME_PATTERN = r'name="fname" value="(?P<N>.+?)">'
- SIZE_PATTERN = r'>Size: .+?">(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
-
- OFFLINE_PATTERN = r'>(File Not Found</b><br><br>|File Not Found</h2>)'
-
- RAND_ID_PATTERN = r'type=\"hidden\" name=\"rand\" value=\"(.+)\">'
-
- LINK_FREE_PATTERN = r'var download_url = \'(.+)\';'
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = True
-
-
- def handleFree(self, pyfile):
- # Click the free user button
- post_data = {'op' : "download1",
- 'usr_login' : "",
- 'id' : self.info['pattern']['ID'],
- 'fname' : pyfile.name,
- 'referer' : "",
- 'method_free': "+"}
-
- self.html = self.load(pyfile.url, post=post_data, cookies=True, decode=True)
-
- solvemedia = SolveMedia(self)
- response, challenge = solvemedia.challenge()
-
- # Make the downloadlink appear and load the file
- m = re.search(self.RAND_ID_PATTERN, self.html)
- if m is None:
- self.error(_("Random key not found"))
-
- rand = m.group(1)
- self.logDebug("rand = ", rand)
-
- post_data = {'op' : "download2",
- 'id' : self.info['pattern']['ID'],
- 'rand' : rand,
- 'referer' : pyfile.url,
- 'method_free' : "+",
- 'method_premium' : "",
- 'adcopy_response' : response,
- 'adcopy_challenge': challenge,
- 'down_direct' : "1"}
-
- self.html = self.load(pyfile.url, post=post_data, cookies=True, decode=True)
-
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("Download url not found"))
-
- self.link = m.group(1)
-
-
-getInfo = create_getInfo(KingfilesNet)
diff --git a/module/plugins/hoster/LemUploadsCom.py b/module/plugins/hoster/LemUploadsCom.py
deleted file mode 100644
index 822670348..000000000
--- a/module/plugins/hoster/LemUploadsCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class LemUploadsCom(DeadHoster):
- __name__ = "LemUploadsCom"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'https?://(?:www\.)?lemuploads\.com/\w{12}'
-
- __description__ = """LemUploads.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("t4skforce", "t4skforce1337[AT]gmail[DOT]com")]
-
-
-getInfo = create_getInfo(LemUploadsCom)
diff --git a/module/plugins/hoster/LetitbitNet.py b/module/plugins/hoster/LetitbitNet.py
deleted file mode 100644
index 2c725427d..000000000
--- a/module/plugins/hoster/LetitbitNet.py
+++ /dev/null
@@ -1,155 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# API Documentation:
-# http://api.letitbit.net/reg/static/api.pdf
-#
-# Test links:
-# http://letitbit.net/download/07874.0b5709a7d3beee2408bb1f2eefce/random.bin.html
-
-import re
-
-from urlparse import urljoin
-
-from module.common.json_layer import json_loads, json_dumps
-from module.network.RequestFactory import getURL
-from module.plugins.internal.CaptchaService import ReCaptcha
-from module.plugins.internal.SimpleHoster import SimpleHoster, secondsToMidnight
-
-
-def api_response(url):
- json_data = ["yw7XQy2v9", ["download/info", {"link": url}]]
- api_rep = getURL("http://api.letitbit.net/json",
- post={'r': json_dumps(json_data)})
- return json_loads(api_rep)
-
-
-def getInfo(urls):
- for url in urls:
- api_rep = api_response(url)
- if api_rep['status'] == 'OK':
- info = api_rep['data'][0]
- yield (info['name'], info['size'], 2, url)
- else:
- yield (url, 0, 1, url)
-
-
-class LetitbitNet(SimpleHoster):
- __name__ = "LetitbitNet"
- __type__ = "hoster"
- __version__ = "0.30"
-
- __pattern__ = r'https?://(?:www\.)?(letitbit|shareflare)\.net/download/.+'
-
- __description__ = """Letitbit.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
- ("z00nx", "z00nx0@gmail.com")]
-
-
- URL_REPLACEMENTS = [(r"(?<=http://)([^/]+)", "letitbit.net")]
-
- SECONDS_PATTERN = r'seconds\s*=\s*(\d+);'
- CAPTCHA_CONTROL_FIELD = r'recaptcha_control_field\s=\s\'(.+?)\''
-
-
- def setup(self):
- self.resumeDownload = True
-
-
- def getFileInfo(self):
- api_rep = api_response(self.pyfile.url)
- if api_rep['status'] == 'OK':
- self.api_data = api_rep['data'][0]
- self.pyfile.name = self.api_data['name']
- self.pyfile.size = self.api_data['size']
- else:
- self.offline()
-
-
- def handleFree(self, pyfile):
- action, inputs = self.parseHtmlForm('id="ifree_form"')
- if not action:
- self.error(_("ifree_form"))
-
- pyfile.size = float(inputs['sssize'])
- self.logDebug(action, inputs)
- inputs['desc'] = ""
-
- self.html = self.load(urljoin("http://letitbit.net/", action), post=inputs, cookies=True)
-
- m = re.search(self.SECONDS_PATTERN, self.html)
- seconds = int(m.group(1)) if m else 60
-
- self.logDebug("Seconds found", seconds)
-
- m = re.search(self.CAPTCHA_CONTROL_FIELD, self.html)
- recaptcha_control_field = m.group(1)
-
- self.logDebug("ReCaptcha control field found", recaptcha_control_field)
-
- self.wait(seconds)
-
- res = self.load("http://letitbit.net/ajax/download3.php", post=" ", cookies=True)
- if res != '1':
- self.error(_("Unknown response - ajax_check_url"))
-
- self.logDebug(res)
-
- recaptcha = ReCaptcha(self)
- response, challenge = recaptcha.challenge()
-
- post_data = {"recaptcha_challenge_field": challenge,
- "recaptcha_response_field": response,
- "recaptcha_control_field": recaptcha_control_field}
-
- self.logDebug("Post data to send", post_data)
-
- res = self.load("http://letitbit.net/ajax/check_recaptcha.php", post=post_data, cookies=True)
-
- self.logDebug(res)
-
- if not res:
- self.invalidCaptcha()
-
- if res == "error_free_download_blocked":
- self.logWarning(_("Daily limit reached"))
- self.wait(secondsToMidnight(gmt=2), True)
-
- if res == "error_wrong_captcha":
- self.invalidCaptcha()
- self.retry()
-
- elif res.startswith('['):
- urls = json_loads(res)
-
- elif res.startswith('http://'):
- urls = [res]
-
- else:
- self.error(_("Unknown response - captcha check"))
-
- self.correctCaptcha()
-
- for download_url in urls:
- try:
- self.download(download_url)
- break
- except Exception, e:
- self.logError(e)
- else:
- self.fail(_("Download did not finish correctly"))
-
-
- def handlePremium(self, pyfile):
- api_key = self.user
- premium_key = self.account.getAccountData(self.user)['password']
-
- json_data = [api_key, ["download/direct_links", {"pass": premium_key, "link": pyfile.url}]]
- api_rep = self.load('http://api.letitbit.net/json', post={'r': json_dumps(json_data)})
- self.logDebug("API Data: " + api_rep)
- api_rep = json_loads(api_rep)
-
- if api_rep['status'] == 'FAIL':
- self.fail(api_rep['data'])
-
- self.link = api_rep['data'][0][0]
diff --git a/module/plugins/hoster/LinksnappyCom.py b/module/plugins/hoster/LinksnappyCom.py
deleted file mode 100644
index 5b0fab43a..000000000
--- a/module/plugins/hoster/LinksnappyCom.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urlparse import urlsplit
-
-from module.common.json_layer import json_loads, json_dumps
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-
-
-class LinksnappyCom(MultiHoster):
- __name__ = "LinksnappyCom"
- __type__ = "hoster"
- __version__ = "0.08"
-
- __pattern__ = r'https?://(?:[^/]+\.)?linksnappy\.com'
-
- __description__ = """Linksnappy.com multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- SINGLE_CHUNK_HOSTERS = ["easybytez.com"]
-
-
- def handlePremium(self, pyfile):
- host = self._get_host(pyfile.url)
- json_params = json_dumps({'link' : pyfile.url,
- 'type' : host,
- 'username': self.user,
- 'password': self.account.getAccountData(self.user)['password']})
-
- r = self.load("http://gen.linksnappy.com/genAPI.php",
- post={'genLinks': json_params})
-
- self.logDebug("JSON data: " + r)
-
- j = json_loads(r)['links'][0]
-
- if j['error']:
- self.error(_("Error converting the link"))
-
- pyfile.name = j['filename']
- self.link = j['generated']
-
- if host in self.SINGLE_CHUNK_HOSTERS:
- self.chunkLimit = 1
- else:
- self.setup()
-
-
- @staticmethod
- def _get_host(url):
- host = urlsplit(url).netloc
- return re.search(r'[\w-]+\.\w+$', host).group(0)
-
-
-getInfo = create_getInfo(LinksnappyCom)
diff --git a/module/plugins/hoster/LoadTo.py b/module/plugins/hoster/LoadTo.py
deleted file mode 100644
index 0f344a88b..000000000
--- a/module/plugins/hoster/LoadTo.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# http://www.load.to/JWydcofUY6/random.bin
-# http://www.load.to/oeSmrfkXE/random100.bin
-
-import re
-
-from pyload.plugin.internal.captcha import SolveMedia
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class LoadTo(SimpleHoster):
- __name__ = "LoadTo"
- __type__ = "hoster"
- __version__ = "0.22"
-
- __pattern__ = r'http://(?:www\.)?load\.to/\w+'
-
- __description__ = """Load.to hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("halfman", "Pulpan3@gmail.com"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
- NAME_PATTERN = r'<h1>(?P<N>.+)</h1>'
- SIZE_PATTERN = r'Size: (?P<S>[\d.,]+) (?P<U>[\w^_]+)'
- OFFLINE_PATTERN = r'>Can\'t find file'
-
- LINK_FREE_PATTERN = r'<form method="post" action="(.+?)"'
- WAIT_PATTERN = r'type="submit" value="Download \((\d+)\)"'
-
- URL_REPLACEMENTS = [(r'(\w)$', r'\1/')]
-
-
- def setup(self):
- self.multiDL = True
- self.chunkLimit = 1
-
-
- def handleFree(self, pyfile):
- # Search for Download URL
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("LINK_FREE_PATTERN not found"))
-
- download_url = m.group(1)
-
- # Set Timer - may be obsolete
- m = re.search(self.WAIT_PATTERN, self.html)
- if m:
- self.wait(m.group(1))
-
- # Load.to is using solvemedia captchas since ~july 2014:
- solvemedia = SolveMedia(self)
- captcha_key = solvemedia.detect_key()
-
- if captcha_key is None:
- self.download(download_url)
- else:
- response, challenge = solvemedia.challenge(captcha_key)
- self.download(download_url,
- post={'adcopy_challenge': challenge,
- 'adcopy_response' : response,
- 'returnUrl' : pyfile.url})
-
-
-getInfo = create_getInfo(LoadTo)
diff --git a/module/plugins/hoster/LomafileCom.py b/module/plugins/hoster/LomafileCom.py
deleted file mode 100644
index 475cdacaa..000000000
--- a/module/plugins/hoster/LomafileCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class LomafileCom(DeadHoster):
- __name__ = "LomafileCom"
- __type__ = "hoster"
- __version__ = "0.52"
-
- __pattern__ = r'http://lomafile\.com/\w{12}'
-
- __description__ = """Lomafile.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("nath_schwarz", "nathan.notwhite@gmail.com"),
- ("guidobelix", "guidobelix@hotmail.it")]
-
-
-getInfo = create_getInfo(LomafileCom)
diff --git a/module/plugins/hoster/LuckyShareNet.py b/module/plugins/hoster/LuckyShareNet.py
deleted file mode 100644
index 33f8ab393..000000000
--- a/module/plugins/hoster/LuckyShareNet.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from bottle import json_loads
-
-from pyload.plugin.internal.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class LuckyShareNet(SimpleHoster):
- __name__ = "LuckyShareNet"
- __type__ = "hoster"
- __version__ = "0.06"
-
- __pattern__ = r'https?://(?:www\.)?luckyshare\.net/(?P<ID>\d{10,})'
-
- __description__ = """LuckyShare.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- INFO_PATTERN = r'<h1 class=\'file_name\'>(?P<N>\S+)</h1>\s*<span class=\'file_size\'>Filesize: (?P<S>[\d.,]+)(?P<U>[\w^_]+)</span>'
- OFFLINE_PATTERN = r'There is no such file available'
-
-
- def parseJson(self, rep):
- if 'AJAX Error' in rep:
- html = self.load(self.pyfile.url, decode=True)
- m = re.search(r"waitingtime = (\d+);", html)
- if m:
- seconds = int(m.group(1))
- self.logDebug("You have to wait %d seconds between free downloads" % seconds)
- self.retry(wait_time=seconds)
- else:
- self.error(_("Unable to detect wait time between free downloads"))
- elif 'Hash expired' in rep:
- self.retry(reason=_("Hash expired"))
- return json_loads(rep)
-
-
- # TODO: There should be a filesize limit for free downloads
- # TODO: Some files could not be downloaded in free mode
- def handleFree(self, pyfile):
- rep = self.load(r"http://luckyshare.net/download/request/type/time/file/" + self.info['pattern']['ID'], decode=True)
-
- self.logDebug("JSON: " + rep)
-
- json = self.parseJson(rep)
- self.wait(json['time'])
-
- recaptcha = ReCaptcha(self)
-
- for _i in xrange(5):
- response, challenge = recaptcha.challenge()
- rep = self.load(r"http://luckyshare.net/download/verify/challenge/%s/response/%s/hash/%s" %
- (challenge, response, json['hash']), decode=True)
- self.logDebug("JSON: " + rep)
- if 'link' in rep:
- json.update(self.parseJson(rep))
- self.correctCaptcha()
- break
- elif 'Verification failed' in rep:
- self.invalidCaptcha()
- else:
- self.error(_("Unable to get downlaod link"))
-
- if not json['link']:
- self.fail(_("No Download url retrieved/all captcha attempts failed"))
-
- self.download(json['link'])
-
-
-getInfo = create_getInfo(LuckyShareNet)
diff --git a/module/plugins/hoster/MegaCoNz.py b/module/plugins/hoster/MegaCoNz.py
deleted file mode 100644
index 4ad20b265..000000000
--- a/module/plugins/hoster/MegaCoNz.py
+++ /dev/null
@@ -1,217 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import os
-import random
-import re
-
-from array import array
-from base64 import standard_b64decode
-
-from Crypto.Cipher import AES
-from Crypto.Util import Counter
-# from pycurl import SSL_CIPHER_LIST
-
-from module.common.json_layer import json_loads, json_dumps
-from module.plugins.Hoster import Hoster
-from module.utils import decode, fs_decode, fs_encode
-
-
-############################ General errors ###################################
-# EINTERNAL (-1): An internal error has occurred. Please submit a bug report, detailing the exact circumstances in which this error occurred
-# EARGS (-2): You have passed invalid arguments to this command
-# EAGAIN (-3): (always at the request level) A temporary congestion or server malfunction prevented your request from being processed. No data was altered. Retry. Retries must be spaced with exponential backoff
-# ERATELIMIT (-4): You have exceeded your command weight per time quota. Please wait a few seconds, then try again (this should never happen in sane real-life applications)
-#
-############################ Upload errors ####################################
-# EFAILED (-5): The upload failed. Please restart it from scratch
-# ETOOMANY (-6): Too many concurrent IP addresses are accessing this upload target URL
-# ERANGE (-7): The upload file packet is out of range or not starting and ending on a chunk boundary
-# EEXPIRED (-8): The upload target URL you are trying to access has expired. Please request a fresh one
-#
-############################ Stream/System errors #############################
-# ENOENT (-9): Object (typically, node or user) not found
-# ECIRCULAR (-10): Circular linkage attempted
-# EACCESS (-11): Access violation (e.g., trying to write to a read-only share)
-# EEXIST (-12): Trying to create an object that already exists
-# EINCOMPLETE (-13): Trying to access an incomplete resource
-# EKEY (-14): A decryption operation failed (never returned by the API)
-# ESID (-15): Invalid or expired user session, please relogin
-# EBLOCKED (-16): User blocked
-# EOVERQUOTA (-17): Request over quota
-# ETEMPUNAVAIL (-18): Resource temporarily not available, please try again later
-# ETOOMANYCONNECTIONS (-19): Too many connections on this resource
-# EWRITE (-20): Write failed
-# EREAD (-21): Read failed
-# EAPPKEY (-22): Invalid application key; request not processed
-
-
-class MegaCoNz(Hoster):
- __name__ = "MegaCoNz"
- __type__ = "hoster"
- __version__ = "0.26"
-
- __pattern__ = r'(?:https?://(?:www\.)?mega\.co\.nz/|mega:|chrome:.+?)#(?P<TYPE>N|)!(?P<ID>[\w^_]+)!(?P<KEY>[\w,\\-]+)'
-
- __description__ = """Mega.co.nz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "ranan@pyload.org"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- API_URL = "https://eu.api.mega.co.nz/cs"
- FILE_SUFFIX = ".crypted"
-
-
- def b64_decode(self, data):
- data = data.replace("-", "+").replace("_", "/")
- return standard_b64decode(data + '=' * (-len(data) % 4))
-
-
- def getCipherKey(self, key):
- """ Construct the cipher key from the given data """
- a = array("I", self.b64_decode(key))
-
- k = array("I", (a[0] ^ a[4], a[1] ^ a[5], a[2] ^ a[6], a[3] ^ a[7]))
- iv = a[4:6] + array("I", (0, 0))
- meta_mac = a[6:8]
-
- return k, iv, meta_mac
-
-
- def api_response(self, **kwargs):
- """ Dispatch a call to the api, see https://mega.co.nz/#developers """
-
- # generate a session id, no idea where to obtain elsewhere
- uid = random.randint(10 << 9, 10 ** 10)
-
- res = self.load(self.API_URL, get={'id': uid}, post=json_dumps([kwargs]))
- self.logDebug("Api Response: " + res)
- return json_loads(res)
-
-
- def decryptAttr(self, data, key):
- k, iv, meta_mac = self.getCipherKey(key)
- cbc = AES.new(k, AES.MODE_CBC, "\0" * 16)
- attr = decode(cbc.decrypt(self.b64_decode(data)))
-
- self.logDebug("Decrypted Attr: %s" % attr)
- if not attr.startswith("MEGA"):
- self.fail(_("Decryption failed"))
-
- # Data is padded, 0-bytes must be stripped
- return json_loads(re.search(r'{.+?}', attr).group(0))
-
-
- def decryptFile(self, key):
- """ Decrypts the file at lastDownload` """
-
- # upper 64 bit of counter start
- n = self.b64_decode(key)[16:24]
-
- # convert counter to long and shift bytes
- k, iv, meta_mac = self.getCipherKey(key)
- ctr = Counter.new(128, initial_value=long(n.encode("hex"), 16) << 64)
- cipher = AES.new(k, AES.MODE_CTR, counter=ctr)
-
- self.pyfile.setStatus("decrypting")
- self.pyfile.setProgress(0)
-
- file_crypted = fs_encode(self.lastDownload)
- file_decrypted = file_crypted.rsplit(self.FILE_SUFFIX)[0]
-
- try:
- f = open(file_crypted, "rb")
- df = open(file_decrypted, "wb")
-
- except IOError, e:
- self.fail(e)
-
- chunk_size = 2 ** 15 # buffer size, 32k
- # file_mac = [0, 0, 0, 0] # calculate CBC-MAC for checksum
-
- chunks = os.path.getsize(file_crypted) / chunk_size + 1
- for i in xrange(chunks):
- buf = f.read(chunk_size)
- if not buf:
- break
-
- chunk = cipher.decrypt(buf)
- df.write(chunk)
-
- self.pyfile.setProgress(int((100.0 / chunks) * i))
-
- # chunk_mac = [iv[0], iv[1], iv[0], iv[1]]
- # for i in xrange(0, chunk_size, 16):
- # block = chunk[i:i+16]
- # if len(block) % 16:
- # block += '=' * (16 - (len(block) % 16))
- # block = array("I", block)
-
- # chunk_mac = [chunk_mac[0] ^ a_[0], chunk_mac[1] ^ block[1], chunk_mac[2] ^ block[2], chunk_mac[3] ^ block[3]]
- # chunk_mac = aes_cbc_encrypt_a32(chunk_mac, k)
-
- # file_mac = [file_mac[0] ^ chunk_mac[0], file_mac[1] ^ chunk_mac[1], file_mac[2] ^ chunk_mac[2], file_mac[3] ^ chunk_mac[3]]
- # file_mac = aes_cbc_encrypt_a32(file_mac, k)
-
- self.pyfile.setProgress(100)
-
- f.close()
- df.close()
-
- # if file_mac[0] ^ file_mac[1], file_mac[2] ^ file_mac[3] != meta_mac:
- # os.remove(file_decrypted)
- # self.fail(_("Checksum mismatch"))
-
- os.remove(file_crypted)
- self.lastDownload = fs_decode(file_decrypted)
-
-
- def checkError(self, code):
- ecode = abs(code)
-
- if ecode in (9, 16, 21):
- self.offline()
-
- elif ecode in (3, 13, 17, 18, 19):
- self.tempOffline()
-
- elif ecode in (1, 4, 6, 10, 15, 21):
- self.retry(5, 30, _("Error code: [%s]") % -ecode)
-
- else:
- self.fail(_("Error code: [%s]") % -ecode)
-
-
- def process(self, pyfile):
- pattern = re.match(self.__pattern__, pyfile.url).groupdict()
- id = pattern['ID']
- key = pattern['KEY']
- public = pattern['TYPE'] == ''
-
- self.logDebug("ID: %s" % id, "Key: %s" % key, "Type: %s" % ("public" if public else "node"))
-
- # g is for requesting a download url
- # this is similar to the calls in the mega js app, documentation is very bad
- if public:
- mega = self.api_response(a="g", g=1, p=id, ssl=1)[0]
- else:
- mega = self.api_response(a="g", g=1, n=id, ssl=1)[0]
-
- if isinstance(mega, int):
- self.checkError(mega)
- elif "e" in mega:
- self.checkError(mega['e'])
-
- attr = self.decryptAttr(mega['at'], key)
-
- pyfile.name = attr['n'] + self.FILE_SUFFIX
- pyfile.size = mega['s']
-
- # self.req.http.c.setopt(SSL_CIPHER_LIST, "RC4-MD5:DEFAULT")
-
- self.download(mega['g'])
-
- self.decryptFile(key)
-
- # Everything is finished and final name can be set
- pyfile.name = attr['n']
diff --git a/module/plugins/hoster/MegaDebridEu.py b/module/plugins/hoster/MegaDebridEu.py
deleted file mode 100644
index b42362800..000000000
--- a/module/plugins/hoster/MegaDebridEu.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urllib import unquote_plus
-
-from module.common.json_layer import json_loads
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-
-
-class MegaDebridEu(MultiHoster):
- __name__ = "MegaDebridEu"
- __type__ = "hoster"
- __version__ = "0.46"
-
- __pattern__ = r'http://((?:www\d+\.|s\d+\.)?mega-debrid\.eu|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/download/file/[\w^_]+'
-
- __description__ = """mega-debrid.eu multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("D.Ducatel", "dducatel@je-geek.fr")]
-
-
- API_URL = "https://www.mega-debrid.eu/api.php"
-
-
- def getFilename(self, url):
- try:
- return unquote_plus(url.rsplit("/", 1)[1])
- except IndexError:
- return ""
-
-
- def handlePremium(self, pyfile):
- if not self.api_load():
- self.exitOnFail("Unable to connect to Mega-debrid.eu")
-
- self.link = self.debridLink(pyfile.url)
-
- filename = self.getFilename(self.link)
- if filename:
- pyfile.name = filename
-
-
- def api_load(self):
- """
- Connexion to the mega-debrid API
- Return True if succeed
- """
- user, data = self.account.selectAccount()
- jsonResponse = self.load(self.API_URL,
- get={'action': 'connectUser', 'login': user, 'password': data['password']})
- res = json_loads(jsonResponse)
-
- if res['response_code'] == "ok":
- self.token = res['token']
- return True
- else:
- return False
-
-
- def debridLink(self, linkToDebrid):
- """
- Debrid a link
- Return The debrided link if succeed or original link if fail
- """
- jsonResponse = self.load(self.API_URL, get={'action': 'getLink', 'token': self.token},
- post={"link": linkToDebrid})
- res = json_loads(jsonResponse)
-
- if res['response_code'] == "ok":
- debridedLink = res['debridLink'][1:-1]
- return debridedLink
- else:
- self.exitOnFail("Unable to debrid %s" % linkToDebrid)
-
-
- def exitOnFail(self, msg):
- """
- exit the plugin on fail case
- And display the reason of this failure
- """
- if self.getConfig("unloadFailing"):
- self.logError(_(msg))
- self.resetAccount()
- else:
- self.fail(_(msg))
-
-
-getInfo = create_getInfo(MegaDebridEu)
diff --git a/module/plugins/hoster/MegaFilesSe.py b/module/plugins/hoster/MegaFilesSe.py
deleted file mode 100644
index 4120e17d6..000000000
--- a/module/plugins/hoster/MegaFilesSe.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class MegaFilesSe(DeadHoster):
- __name__ = "MegaFilesSe"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?megafiles\.se/\w{12}'
-
- __description__ = """MegaFiles.se hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("t4skforce", "t4skforce1337[AT]gmail[DOT]com")]
-
-
-getInfo = create_getInfo(MegaFilesSe)
diff --git a/module/plugins/hoster/MegaRapidCz.py b/module/plugins/hoster/MegaRapidCz.py
deleted file mode 100644
index 7d8a25c03..000000000
--- a/module/plugins/hoster/MegaRapidCz.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pycurl import HTTPHEADER
-
-from module.network.HTTPRequest import BadHeader
-from module.network.RequestFactory import getRequest
-from module.plugins.internal.SimpleHoster import SimpleHoster, parseFileInfo
-
-
-def getInfo(urls):
- h = getRequest()
- h.c.setopt(HTTPHEADER,
- ["Accept: text/html",
- "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0"])
-
- for url in urls:
- html = h.load(url, decode=True)
- yield parseFileInfo(MegaRapidCz, url, html)
-
-
-class MegaRapidCz(SimpleHoster):
- __name__ = "MegaRapidCz"
- __type__ = "hoster"
- __version__ = "0.56"
-
- __pattern__ = r'http://(?:www\.)?(share|mega)rapid\.cz/soubor/\d+/.+'
-
- __description__ = """MegaRapid.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("MikyWoW", "mikywow@seznam.cz"),
- ("zoidberg", "zoidberg@mujmail.cz"),
- ("stickell", "l.stickell@yahoo.it"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- NAME_PATTERN = r'<h1[^>]*><span[^>]*>(?:<a[^>]*>)?(?P<N>[^<]+)'
- SIZE_PATTERN = r'<td class="i">Velikost:</td>\s*<td class="h"><strong>\s*(?P<S>[\d.,]+) (?P<U>[\w^_]+)</strong></td>'
- OFFLINE_PATTERN = ur'Nastala chyba 404|Soubor byl smazán'
-
- CHECK_TRAFFIC = True
-
- LINK_PREMIUM_PATTERN = r'<a href="([^"]+)" title="Stahnout">([^<]+)</a>'
-
- ERR_LOGIN_PATTERN = ur'<div class="error_div"><strong>Stahování je přístupné pouze přihlášenÃœm uÅŸivatelům'
- ERR_CREDIT_PATTERN = ur'<div class="error_div"><strong>Stahování zdarma je moÅŸné jen přes náš'
-
-
- def setup(self):
- self.chunkLimit = 1
-
-
- def handlePremium(self, pyfile):
- m = re.search(self.LINK_PREMIUM_PATTERN, self.html)
- if m:
- self.link = m.group(1)
- else:
- if re.search(self.ERR_LOGIN_PATTERN, self.html):
- self.relogin(self.user)
- self.retry(wait_time=60, reason=_("User login failed"))
- elif re.search(self.ERR_CREDIT_PATTERN, self.html):
- self.fail(_("Not enough credit left"))
- else:
- self.fail(_("Download link not found"))
diff --git a/module/plugins/hoster/MegareleaseOrg.py b/module/plugins/hoster/MegareleaseOrg.py
deleted file mode 100644
index 6eacbd6e0..000000000
--- a/module/plugins/hoster/MegareleaseOrg.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class MegareleaseOrg(DeadHoster):
- __name__ = "MegareleaseOrg"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'https?://(?:www\.)?megarelease\.org/\w{12}'
-
- __description__ = """Megarelease.org hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("derek3x", "derek3x@vmail.me"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
-getInfo = create_getInfo(MegareleaseOrg)
diff --git a/module/plugins/hoster/MegasharesCom.py b/module/plugins/hoster/MegasharesCom.py
deleted file mode 100644
index 84777adeb..000000000
--- a/module/plugins/hoster/MegasharesCom.py
+++ /dev/null
@@ -1,113 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from time import time
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class MegasharesCom(SimpleHoster):
- __name__ = "MegasharesCom"
- __type__ = "hoster"
- __version__ = "0.28"
-
- __pattern__ = r'http://(?:www\.)?(d\d{2}\.)?megashares\.com/((index\.php)?\?d\d{2}=|dl/)\w+'
-
- __description__ = """Megashares.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- NAME_PATTERN = r'<h1 class="black xxl"[^>]*title="(?P<N>[^"]+)">'
- SIZE_PATTERN = r'<strong><span class="black">Filesize:</span></strong> (?P<S>[\d.,]+) (?P<U>[\w^_]+)'
- OFFLINE_PATTERN = r'<dd class="red">(Invalid Link Request|Link has been deleted|Invalid link)'
-
- LINK_PATTERN = r'<div id="show_download_button_%d"[^>]*>\s*<a href="([^"]+)">'
-
- PASSPORT_LEFT_PATTERN = r'Your Download Passport is: <[^>]*>(\w+).*?You have.*?<[^>]*>.*?([\d.]+) (\w+)'
- PASSPORT_RENEW_PATTERN = r'(\d+):<strong>(\d+)</strong>:<strong>(\d+)</strong>'
- REACTIVATE_NUM_PATTERN = r'<input[^>]*id="random_num" value="(\d+)" />'
- REACTIVATE_PASSPORT_PATTERN = r'<input[^>]*id="passport_num" value="(\w+)" />'
- REQUEST_URI_PATTERN = r'var request_uri = "([^"]+)";'
- NO_SLOTS_PATTERN = r'<dd class="red">All download slots for this link are currently filled'
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = self.premium
-
-
- def handlePremium(self, pyfile):
- self.handleDownload(True)
-
-
- def handleFree(self, pyfile):
- if self.NO_SLOTS_PATTERN in self.html:
- self.retry(wait_time=5 * 60)
-
- m = re.search(self.REACTIVATE_PASSPORT_PATTERN, self.html)
- if m:
- passport_num = m.group(1)
- request_uri = re.search(self.REQUEST_URI_PATTERN, self.html).group(1)
-
- for _i in xrange(5):
- random_num = re.search(self.REACTIVATE_NUM_PATTERN, self.html).group(1)
-
- verifyinput = self.decryptCaptcha("http://d01.megashares.com/index.php",
- get={'secgfx': "gfx", 'random_num': random_num})
-
- self.logInfo(_("Reactivating passport %s: %s %s") % (passport_num, random_num, verifyinput))
-
- res = self.load("http://d01.megashares.com%s" % request_uri,
- get={'rs' : "check_passport_renewal",
- 'rsargs[]': verifyinput,
- 'rsargs[]': random_num,
- 'rsargs[]': passport_num,
- 'rsargs[]': "replace_sec_pprenewal",
- 'rsrnd[]' : str(int(time() * 1000))})
-
- if 'Thank you for reactivating your passport.' in res:
- self.correctCaptcha()
- self.retry()
- else:
- self.invalidCaptcha()
- else:
- self.fail(_("Failed to reactivate passport"))
-
- m = re.search(self.PASSPORT_RENEW_PATTERN, self.html)
- if m:
- time = [int(x) for x in m.groups()]
- renew = time[0] + (time[1] * 60) + (time[2] * 60)
- self.logDebug("Waiting %d seconds for a new passport" % renew)
- self.retry(wait_time=renew, reason=_("Passport renewal"))
-
- # Check traffic left on passport
- m = re.search(self.PASSPORT_LEFT_PATTERN, self.html, re.M | re.S)
- if m is None:
- self.fail(_("Passport not found"))
-
- self.logInfo(_("Download passport: %s") % m.group(1))
- data_left = float(m.group(2)) * 1024 ** {'B': 0, 'KB': 1, 'MB': 2, 'GB': 3}[m.group(3)]
- self.logInfo(_("Data left: %s %s (%d MB needed)") % (m.group(2), m.group(3), self.pyfile.size / 1048576))
-
- if not data_left:
- self.retry(wait_time=600, reason=_("Passport renewal"))
-
- self.handleDownload(False)
-
-
- def handleDownload(self, premium=False):
- # Find download link;
- m = re.search(self.LINK_PATTERN % (1 if premium else 2), self.html)
- msg = _('%s download URL' % ('Premium' if premium else 'Free'))
- if m is None:
- self.error(msg)
-
- download_url = m.group(1)
- self.logDebug("%s: %s" % (msg, download_url))
- self.download(download_url)
-
-
-getInfo = create_getInfo(MegasharesCom)
diff --git a/module/plugins/hoster/MegauploadCom.py b/module/plugins/hoster/MegauploadCom.py
deleted file mode 100644
index 7896dabfb..000000000
--- a/module/plugins/hoster/MegauploadCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class MegauploadCom(DeadHoster):
- __name__ = "MegauploadCom"
- __type__ = "hoster"
- __version__ = "0.31"
-
- __pattern__ = r'http://(?:www\.)?megaupload\.com/\?.*&?(d|v)=\w+'
-
- __description__ = """Megaupload.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("spoob", "spoob@pyload.org")]
-
-
-getInfo = create_getInfo(MegauploadCom)
diff --git a/module/plugins/hoster/MegavideoCom.py b/module/plugins/hoster/MegavideoCom.py
deleted file mode 100644
index 02054fecb..000000000
--- a/module/plugins/hoster/MegavideoCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class MegavideoCom(DeadHoster):
- __name__ = "MegavideoCom"
- __type__ = "hoster"
- __version__ = "0.21"
-
- __pattern__ = r'http://(?:www\.)?megavideo\.com/\?.*&?(d|v)=\w+'
-
- __description__ = """Megavideo.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("jeix", "jeix@hasnomail.de"),
- ("mkaay", "mkaay@mkaay.de")]
-
-
-getInfo = create_getInfo(MegavideoCom)
diff --git a/module/plugins/hoster/MovReelCom.py b/module/plugins/hoster/MovReelCom.py
deleted file mode 100644
index 3e18a8960..000000000
--- a/module/plugins/hoster/MovReelCom.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class MovReelCom(XFSHoster):
- __name__ = "MovReelCom"
- __type__ = "hoster"
- __version__ = "1.24"
-
- __pattern__ = r'http://(?:www\.)?movreel\.com/\w{12}'
-
- __description__ = """MovReel.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("JorisV83", "jorisv83-pyload@yahoo.com")]
-
-
- LINK_PATTERN = r'<a href="([^"]+)">Download Link'
-
-
-getInfo = create_getInfo(MovReelCom)
diff --git a/module/plugins/hoster/MultihostersCom.py b/module/plugins/hoster/MultihostersCom.py
deleted file mode 100644
index bcd7c6237..000000000
--- a/module/plugins/hoster/MultihostersCom.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.hoster.ZeveraCom import ZeveraCom
-
-
-class MultihostersCom(ZeveraCom):
- __name__ = "MultihostersCom"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'https?://(?:www\.)multihosters\.com/(getFiles\.ashx|Members/download\.ashx)\?.*ourl=.+'
-
- __description__ = """Multihosters.com multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("tjeh", "tjeh@gmx.net")]
diff --git a/module/plugins/hoster/MultishareCz.py b/module/plugins/hoster/MultishareCz.py
deleted file mode 100644
index ca626a833..000000000
--- a/module/plugins/hoster/MultishareCz.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from random import random
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class MultishareCz(SimpleHoster):
- __name__ = "MultishareCz"
- __type__ = "hoster"
- __version__ = "0.40"
-
- __pattern__ = r'http://(?:www\.)?multishare\.cz/stahnout/(?P<ID>\d+)'
-
- __description__ = """MultiShare.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- SIZE_REPLACEMENTS = [('&nbsp;', '')]
-
- CHECK_TRAFFIC = True
- MULTI_HOSTER = True
-
- INFO_PATTERN = ur'(?:<li>Název|Soubor): <strong>(?P<N>[^<]+)</strong><(?:/li><li|br)>Velikost: <strong>(?P<S>[^<]+)</strong>'
- OFFLINE_PATTERN = ur'<h1>Stáhnout soubor</h1><p><strong>PoşadovanÜ soubor neexistuje.</strong></p>'
-
-
- def handleFree(self, pyfile):
- self.download("http://www.multishare.cz/html/download_free.php", get={'ID': self.info['pattern']['ID']})
-
-
- def handlePremium(self, pyfile):
- self.download("http://www.multishare.cz/html/download_premium.php", get={'ID': self.info['pattern']['ID']})
-
-
- def handleMulti(self, pyfile):
- self.html = self.load('http://www.multishare.cz/html/mms_ajax.php', post={"link": pyfile.url}, decode=True)
-
- self.checkInfo()
-
- if not self.checkTrafficLeft():
- self.fail(_("Not enough credit left to download file"))
-
- self.download("http://dl%d.mms.multishare.cz/html/mms_process.php" % round(random() * 10000 * random()),
- get={'u_ID' : self.acc_info['u_ID'],
- 'u_hash': self.acc_info['u_hash'],
- 'link' : pyfile.url},
- disposition=True)
-
-
-getInfo = create_getInfo(MultishareCz)
diff --git a/module/plugins/hoster/MyfastfileCom.py b/module/plugins/hoster/MyfastfileCom.py
deleted file mode 100644
index 3862bfe32..000000000
--- a/module/plugins/hoster/MyfastfileCom.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.common.json_layer import json_loads
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-
-
-class MyfastfileCom(MultiHoster):
- __name__ = "MyfastfileCom"
- __type__ = "hoster"
- __version__ = "0.08"
-
- __pattern__ = r'http://\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/dl/'
-
- __description__ = """Myfastfile.com multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
-
- def setup(self):
- self.chunkLimit = -1
-
-
- def handlePremium(self, pyfile):
- self.html = self.load('http://myfastfile.com/api.php',
- get={'user': self.user, 'pass': self.account.getAccountData(self.user)['password'],
- 'link': pyfile.url})
- self.logDebug("JSON data: " + self.html)
-
- self.html = json_loads(self.html)
- if self.html['status'] != 'ok':
- self.fail(_("Unable to unrestrict link"))
-
- self.link = self.html['link']
-
-
-getInfo = create_getInfo(MyfastfileCom)
diff --git a/module/plugins/hoster/MystoreTo.py b/module/plugins/hoster/MystoreTo.py
deleted file mode 100644
index 3bb424d4d..000000000
--- a/module/plugins/hoster/MystoreTo.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test link:
-# http://mystore.to/dl/mxcA50jKfP
-
-import re
-
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class MystoreTo(SimpleHoster):
- __name__ = "MystoreTo"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'https?://(?:www\.)?mystore\.to/dl/.+'
-
- __description__ = """Mystore.to hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "")]
-
-
- NAME_PATTERN = r'<h1>(?P<N>.+?)<'
- SIZE_PATTERN = r'FILESIZE: (?P<S>[\d\.,]+) (?P<U>[\w^_]+)'
- OFFLINE_PATTERN = r'>file not found<'
-
-
- def setup(self):
- self.chunkLimit = 1
- self.resumeDownload = True
- self.multiDL = True
-
-
- def handleFree(self, pyfile):
- try:
- fid = re.search(r'wert="(.+?)"', self.html).group(1)
-
- except AttributeError:
- self.error(_("File-ID not found"))
-
- self.link = self.load("http://mystore.to/api/download",
- post={'FID': fid})
-
-
-getInfo = create_getInfo(MystoreTo)
diff --git a/module/plugins/hoster/NahrajCz.py b/module/plugins/hoster/NahrajCz.py
deleted file mode 100644
index 5c5c71ae6..000000000
--- a/module/plugins/hoster/NahrajCz.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class NahrajCz(DeadHoster):
- __name__ = "NahrajCz"
- __type__ = "hoster"
- __version__ = "0.21"
-
- __pattern__ = r'http://(?:www\.)?nahraj\.cz/content/download/.+'
-
- __description__ = """Nahraj.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(NahrajCz)
diff --git a/module/plugins/hoster/NarodRu.py b/module/plugins/hoster/NarodRu.py
deleted file mode 100644
index 1738d9724..000000000
--- a/module/plugins/hoster/NarodRu.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from random import random
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class NarodRu(SimpleHoster):
- __name__ = "NarodRu"
- __type__ = "hoster"
- __version__ = "0.12"
-
- __pattern__ = r'http://(?:www\.)?narod(\.yandex)?\.ru/(disk|start/\d+\.\w+-narod\.yandex\.ru)/(?P<ID>\d+)/.+'
-
- __description__ = """Narod.ru hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<dt class="name">(?:<[^<]*>)*(?P<N>[^<]+)</dt>'
- SIZE_PATTERN = r'<dd class="size">(?P<S>\d[^<]*)</dd>'
- OFFLINE_PATTERN = r'<title>404</title>|Ѐайл уЎалеМ с сервОса|ЗакПМчОлся срПк храМеМОя файла\.'
-
- SIZE_REPLACEMENTS = [(u'КБ', 'KB'), (u'МБ', 'MB'), (u'ГБ', 'GB')]
- URL_REPLACEMENTS = [("narod.yandex.ru/", "narod.ru/"),
- (r"/start/\d+\.\w+-narod\.yandex\.ru/(\d{6,15})/\w+/(\w+)", r"/disk/\1/\2")]
-
- CAPTCHA_PATTERN = r'<number url="(.*?)">(\w+)</number>'
- LINK_FREE_PATTERN = r'<a class="h-link" rel="yandex_bar" href="(.+?)">'
-
-
- def handleFree(self, pyfile):
- for _i in xrange(5):
- self.html = self.load('http://narod.ru/disk/getcapchaxml/?rnd=%d' % int(random() * 777))
-
- m = re.search(self.CAPTCHA_PATTERN, self.html)
- if m is None:
- self.error(_("Captcha"))
-
- post_data = {"action": "sendcapcha"}
- captcha_url, post_data['key'] = m.groups()
- post_data['rep'] = self.decryptCaptcha(captcha_url)
-
- self.html = self.load(pyfile.url, post=post_data, decode=True)
-
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m:
- url = 'http://narod.ru' + m.group(1)
- self.correctCaptcha()
- break
-
- elif u'<b class="error-msg"><strong>ОшОблОсь?</strong>' in self.html:
- self.invalidCaptcha()
-
- else:
- self.error(_("Download link"))
-
- else:
- self.fail(_("No valid captcha code entered"))
-
- self.download(url)
-
-
-getInfo = create_getInfo(NarodRu)
diff --git a/module/plugins/hoster/NitroflareCom.py b/module/plugins/hoster/NitroflareCom.py
deleted file mode 100644
index 5bbef64de..000000000
--- a/module/plugins/hoster/NitroflareCom.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Note:
-# Right now premium support is not added
-# Thus, any file that require premium support
-# cannot be downloaded. Only the file that is free to
-# download can be downloaded.
-
-import re
-
-from module.common.json_layer import json_loads
-from module.plugins.internal.CaptchaService import ReCaptcha
-from module.plugins.internal.SimpleHoster import SimpleHoster
-
-
-class NitroflareCom(SimpleHoster):
- __name__ = "NitroflareCom"
- __type__ = "hoster"
- __version__ = "0.08"
-
- __pattern__ = r'https?://(?:www\.)?nitroflare\.com/view/(?P<ID>[\w^_]+)'
-
- __description__ = """Nitroflare.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("sahil", "sahilshekhawat01@gmail.com"),
- ("Walter Purcaro", "vuolter@gmail.com"),
- ("Stickell", "l.stickell@yahoo.it")]
-
- # URL_REPLACEMENTS = [("http://", "https://")]
-
- INFO_PATTERN = r'title="(?P<N>.+?)".+>(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
- OFFLINE_PATTERN = r'>File doesn\'t exist'
-
- LINK_FREE_PATTERN = r'(https?://[\w\-]+\.nitroflare\.com/.+?)"'
-
- RECAPTCHA_KEY = "6Lenx_USAAAAAF5L1pmTWvWcH73dipAEzNnmNLgy"
-
- PREMIUM_ONLY_PATTERN = r'This file is available with Premium only'
- WAIT_PATTERN = r'You have to wait .+'
- ERROR_PATTERN = r'downloading is not possible'
-
-
- def checkErrors(self):
- if not self.html:
- return
-
- if not self.premium and re.search(self.PREMIUM_ONLY_PATTERN, self.html):
- self.fail(_("Link require a premium account to be handled"))
-
- elif hasattr(self, 'WAIT_PATTERN'):
- m = re.search(self.WAIT_PATTERN, self.html)
- if m:
- wait_time = sum(int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1}[u.lower()] for v, u in
- re.findall(r'(\d+)\s*(hr|hour|min|sec)', m.group(0), re.I))
- self.wait(wait_time, wait_time > 300)
- return
-
- elif hasattr(self, 'ERROR_PATTERN'):
- m = re.search(self.ERROR_PATTERN, self.html)
- if m:
- errmsg = self.info['error'] = m.group(1)
- self.error(errmsg)
-
- self.info.pop('error', None)
-
-
- def handleFree(self, pyfile):
- # used here to load the cookies which will be required later
- self.load(pyfile.url, post={'goToFreePage': ""})
-
- self.load("https://www.nitroflare.com/ajax/setCookie.php", post={'fileId': self.info['pattern']['ID']})
- self.html = self.load("https://www.nitroflare.com/ajax/freeDownload.php",
- post={'method': "startTimer", 'fileId': self.info['pattern']['ID']})
-
- self.checkErrors()
-
- try:
- js_file = self.load("http://nitroflare.com/js/downloadFree.js?v=1.0.1")
- var_time = re.search("var time = (\\d+);", js_file)
- wait_time = int(var_time.groups()[0])
-
- except Exception:
- wait_time = 60
-
- self.wait(wait_time)
-
- recaptcha = ReCaptcha(self)
- response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY)
-
- self.html = self.load("https://www.nitroflare.com/ajax/freeDownload.php",
- post={'method' : "fetchDownload",
- 'recaptcha_challenge_field': challenge,
- 'recaptcha_response_field' : response})
-
- if "The captcha wasn't entered correctly" in self.html:
- self.logWarning("The captcha wasn't entered correctly")
- return
-
- if "You have to fill the captcha" in self.html:
- self.logWarning("Captcha unfilled")
- return
-
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m:
- self.link = m.group(1)
- else:
- self.logError("Unable to detect direct link")
diff --git a/module/plugins/hoster/NoPremiumPl.py b/module/plugins/hoster/NoPremiumPl.py
deleted file mode 100644
index 43ae8b3cc..000000000
--- a/module/plugins/hoster/NoPremiumPl.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.common.json_layer import json_loads
-from module.plugins.internal.MultiHoster import MultiHoster
-
-
-class NoPremiumPl(MultiHoster):
- __name__ = "NoPremiumPl"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'https?://direct\.nopremium\.pl.+'
-
- __description__ = """NoPremium.pl multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("goddie", "dev@nopremium.pl")]
-
-
- API_URL = "http://crypt.nopremium.pl"
-
- API_QUERY = {'site' : "nopremium",
- 'output' : "json",
- 'username': "",
- 'password': "",
- 'url' : ""}
-
- ERROR_CODES = {0 : "[%s] Incorrect login credentials",
- 1 : "[%s] Not enough transfer to download - top-up your account",
- 2 : "[%s] Incorrect / dead link",
- 3 : "[%s] Error connecting to hosting, try again later",
- 9 : "[%s] Premium account has expired",
- 15: "[%s] Hosting no longer supported",
- 80: "[%s] Too many incorrect login attempts, account blocked for 24h"}
-
-
- def prepare(self):
- super(NoPremiumPl, self).prepare()
-
- data = self.account.getAccountData(self.user)
-
- self.usr = data['usr']
- self.pwd = data['pwd']
-
-
- def runFileQuery(self, url, mode=None):
- query = self.API_QUERY.copy()
-
- query["username"] = self.usr
- query["password"] = self.pwd
- query["url"] = url
-
- if mode == "fileinfo":
- query['check'] = 2
- query['loc'] = 1
-
- self.logDebug(query)
-
- return self.load(self.API_URL, post=query)
-
-
- def handleFree(self, pyfile):
- try:
- data = self.runFileQuery(pyfile.url, 'fileinfo')
-
- except Exception:
- self.logDebug("runFileQuery error")
- self.tempOffline()
-
- try:
- parsed = json_loads(data)
-
- except Exception:
- self.logDebug("loads error")
- self.tempOffline()
-
- self.logDebug(parsed)
-
- if "errno" in parsed.keys():
- if parsed["errno"] in self.ERROR_CODES:
- # error code in known
- self.fail(self.ERROR_CODES[parsed["errno"]] % self.__name__)
- else:
- # error code isn't yet added to plugin
- self.fail(
- parsed["errstring"]
- or _("Unknown error (code: %s)") % parsed["errno"]
- )
-
- if "sdownload" in parsed:
- if parsed["sdownload"] == "1":
- self.fail(
- _("Download from %s is possible only using NoPremium.pl website \
- directly") % parsed["hosting"])
-
- pyfile.name = parsed["filename"]
- pyfile.size = parsed["filesize"]
-
- try:
- self.link = self.runFileQuery(pyfile.url, 'filedownload')
-
- except Exception:
- self.logDebug("runFileQuery error #2")
- self.tempOffline()
diff --git a/module/plugins/hoster/NosuploadCom.py b/module/plugins/hoster/NosuploadCom.py
deleted file mode 100644
index 842481a60..000000000
--- a/module/plugins/hoster/NosuploadCom.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class NosuploadCom(XFSHoster):
- __name__ = "NosuploadCom"
- __type__ = "hoster"
- __version__ = "0.31"
-
- __pattern__ = r'http://(?:www\.)?nosupload\.com/\?d=\w{12}'
-
- __description__ = """Nosupload.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("igel", "igelkun@myopera.com")]
-
-
- SIZE_PATTERN = r'<p><strong>Size:</strong> (?P<S>[\d.,]+) (?P<U>[\w^_]+)</p>'
- LINK_PATTERN = r'<a class="select" href="(http://.+?)">Download</a>'
-
- WAIT_PATTERN = r'Please wait.*?>(\d+)</span>'
-
-
- def getDownloadLink(self):
- # stage1: press the "Free Download" button
- data = self.getPostParameters()
- self.html = self.load(self.pyfile.url, post=data, ref=True, decode=True)
-
- # stage2: wait some time and press the "Download File" button
- data = self.getPostParameters()
- wait_time = re.search(self.WAIT_PATTERN, self.html, re.M | re.S).group(1)
- self.logDebug("Hoster told us to wait %s seconds" % wait_time)
- self.wait(wait_time)
- self.html = self.load(self.pyfile.url, post=data, ref=True, decode=True)
-
- # stage3: get the download link
- return re.search(self.LINK_PATTERN, self.html, re.S).group(1)
-
-
-getInfo = create_getInfo(NosuploadCom)
diff --git a/module/plugins/hoster/NovafileCom.py b/module/plugins/hoster/NovafileCom.py
deleted file mode 100644
index f73570ec2..000000000
--- a/module/plugins/hoster/NovafileCom.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# http://novafile.com/vfun4z6o2cit
-# http://novafile.com/s6zrr5wemuz4
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class NovafileCom(XFSHoster):
- __name__ = "NovafileCom"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'http://(?:www\.)?novafile\.com/\w{12}'
-
- __description__ = """Novafile.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
- ERROR_PATTERN = r'class="alert[^"]*alert-separate"[^>]*>\s*(?:<p>)?(.*?)\s*</'
- WAIT_PATTERN = r'<p>Please wait <span id="count"[^>]*>(\d+)</span> seconds</p>'
-
- LINK_PATTERN = r'<a href="(http://s\d+\.novafile\.com/.*?)" class="btn btn-green">Download File</a>'
-
-
-getInfo = create_getInfo(NovafileCom)
diff --git a/module/plugins/hoster/NowDownloadSx.py b/module/plugins/hoster/NowDownloadSx.py
deleted file mode 100644
index 44a24471b..000000000
--- a/module/plugins/hoster/NowDownloadSx.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-from pyload.utils import fixup
-
-
-class NowDownloadSx(SimpleHoster):
- __name__ = "NowDownloadSx"
- __type__ = "hoster"
- __version__ = "0.07"
-
- __pattern__ = r'http://(?:www\.)?(nowdownload\.(at|ch|co|eu|sx)/(dl/|download\.php\?id=)|likeupload\.org/)\w+'
-
- __description__ = """NowDownload.sx hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("godofdream", "soilfiction@gmail.com"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- INFO_PATTERN = r'Downloading</span> <br> (?P<N>.*) (?P<S>[\d.,]+) (?P<U>[\w^_]+) </h4>'
- OFFLINE_PATTERN = r'>This file does not exist'
-
- TOKEN_PATTERN = r'"(/api/token\.php\?token=\w+)"'
- CONTINUE_PATTERN = r'"(/dl2/\w+/\w+)"'
- WAIT_PATTERN = r'\.countdown\(\{until: \+(\d+),'
- LINK_FREE_PATTERN = r'(http://s\d+\.coolcdn\.info/nowdownload/.+?)["\']'
-
- NAME_REPLACEMENTS = [("&#?\w+;", fixup), (r'<[^>]*>', '')]
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = True
- self.chunkLimit = -1
-
-
- def handleFree(self, pyfile):
- tokenlink = re.search(self.TOKEN_PATTERN, self.html)
- continuelink = re.search(self.CONTINUE_PATTERN, self.html)
- if tokenlink is None or continuelink is None:
- self.error()
-
- m = re.search(self.WAIT_PATTERN, self.html)
- if m:
- wait = int(m.group(1))
- else:
- wait = 60
-
- baseurl = "http://www.nowdownload.at"
- self.html = self.load(baseurl + str(tokenlink.group(1)))
- self.wait(wait)
-
- self.html = self.load(baseurl + str(continuelink.group(1)))
-
- url = re.search(self.LINK_FREE_PATTERN, self.html)
- if url is None:
- self.error(_("Download link not found"))
-
- self.download(str(url.group(1)))
-
-
-getInfo = create_getInfo(NowDownloadSx)
diff --git a/module/plugins/hoster/NowVideoSx.py b/module/plugins/hoster/NowVideoSx.py
deleted file mode 100644
index fc1d06d19..000000000
--- a/module/plugins/hoster/NowVideoSx.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class NowVideoSx(SimpleHoster):
- __name__ = "NowVideoSx"
- __type__ = "hoster"
- __version__ = "0.10"
-
- __pattern__ = r'http://(?:www\.)?nowvideo\.(at|ch|co|eu|li|sx)/(video|mobile/#/videos)/(?P<ID>\w+)'
-
- __description__ = """NowVideo.sx hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- URL_REPLACEMENTS = [(__pattern__ + ".*", r'http://www.nowvideo.sx/video/\g<ID>')]
-
- NAME_PATTERN = r'<h4>(?P<N>.+?)<'
- OFFLINE_PATTERN = r'>This file no longer exists'
-
- LINK_FREE_PATTERN = r'<source src="(.+?)"'
- LINK_PREMIUM_PATTERN = r'<div id="content_player" >\s*<a href="(.+?)"'
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = True
-
-
- def handleFree(self, pyfile):
- self.html = self.load("http://www.nowvideo.sx/mobile/video.php", get={'id': self.info['pattern']['ID']})
-
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("Free download link not found"))
-
- self.download(m.group(1))
-
-
-getInfo = create_getInfo(NowVideoSx)
diff --git a/module/plugins/hoster/OneFichierCom.py b/module/plugins/hoster/OneFichierCom.py
deleted file mode 100644
index 5be05ea17..000000000
--- a/module/plugins/hoster/OneFichierCom.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class OneFichierCom(SimpleHoster):
- __name__ = "OneFichierCom"
- __type__ = "hoster"
- __version__ = "0.78"
-
- __pattern__ = r'https?://(?:www\.)?(?:(?P<ID1>\w+)\.)?(?P<HOST>1fichier\.com|alterupload\.com|cjoint\.net|d(es)?fichiers\.com|dl4free\.com|megadl\.fr|mesfichiers\.org|piecejointe\.net|pjointe\.com|tenvoi\.com)(?:/\?(?P<ID2>\w+))?'
-
- __description__ = """1fichier.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("fragonib", "fragonib[AT]yahoo[DOT]es"),
- ("the-razer", "daniel_ AT gmx DOT net"),
- ("zoidberg", "zoidberg@mujmail.cz"),
- ("imclem", ""),
- ("stickell", "l.stickell@yahoo.it"),
- ("Elrick69", "elrick69[AT]rocketmail[DOT]com"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- NAME_PATTERN = r'>FileName :</td>\s*<td.*>(?P<N>.+?)<'
- SIZE_PATTERN = r'>Size :</td>\s*<td.*>(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
-
- OFFLINE_PATTERN = r'File not found !\s*<'
-
- COOKIES = [("1fichier.com", "LG", "en")]
- DISPOSITION = False #: Remove in 0.4.10
-
- WAIT_PATTERN = r'>You must wait (\d+) minutes'
-
-
- def setup(self):
- self.multiDL = self.premium
- self.resumeDownload = True
-
-
- def handleFree(self, pyfile):
- id = self.info['pattern']['ID1'] or self.info['pattern']['ID2']
- url, inputs = self.parseHtmlForm('action="https://1fichier.com/\?%s' % id)
-
- if not url:
- self.fail(_("Download link not found"))
-
- if "pass" in inputs:
- inputs['pass'] = self.getPassword()
-
- inputs['submit'] = "Download"
-
- self.download(url, post=inputs)
-
-
- def handlePremium(self, pyfile):
- self.download(pyfile.url, post={'dl': "Download", 'did': 0})
-
-
-getInfo = create_getInfo(OneFichierCom)
diff --git a/module/plugins/hoster/OronCom.py b/module/plugins/hoster/OronCom.py
deleted file mode 100644
index cbbaedae0..000000000
--- a/module/plugins/hoster/OronCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class OronCom(DeadHoster):
- __name__ = "OronCom"
- __type__ = "hoster"
- __version__ = "0.14"
-
- __pattern__ = r'https?://(?:www\.)?oron\.com/\w{12}'
-
- __description__ = """Oron.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("chrox", "chrox@pyload.org"),
- ("DHMH", "DHMH@pyload.org")]
-
-
-getInfo = create_getInfo(OronCom)
diff --git a/module/plugins/hoster/OverLoadMe.py b/module/plugins/hoster/OverLoadMe.py
deleted file mode 100644
index 67563ca3d..000000000
--- a/module/plugins/hoster/OverLoadMe.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from random import randrange
-from urllib import unquote
-
-from module.common.json_layer import json_loads
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-from module.utils import parseFileSize
-
-
-class OverLoadMe(MultiHoster):
- __name__ = "OverLoadMe"
- __type__ = "hoster"
- __version__ = "0.09"
-
- __pattern__ = r'https?://.*overload\.me/.+'
-
- __description__ = """Over-Load.me multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("marley", "marley@over-load.me")]
-
-
- def getFilename(self, url):
- try:
- name = unquote(url.rsplit("/", 1)[1])
- except IndexError:
- name = "Unknown_Filename..."
-
- if name.endswith("..."): #: incomplete filename, append random stuff
- name += "%s.tmp" % randrange(100, 999)
-
- return name
-
-
- def setup(self):
- self.chunkLimit = 5
-
-
- def handlePremium(self, pyfile):
- https = "https" if self.getConfig("ssl") else "http"
- data = self.account.getAccountData(self.user)
- page = self.load(https + "://api.over-load.me/getdownload.php",
- get={'auth': data['password'],
- 'link': pyfile.url})
-
- data = json_loads(page)
-
- self.logDebug(data)
-
- if data['error'] == 1:
- self.logWarning(data['msg'])
- self.tempOffline()
- else:
- if pyfile.name is not None and pyfile.name.endswith('.tmp') and data['filename']:
- pyfile.name = data['filename']
- pyfile.size = parseFileSize(data['filesize'])
-
- http_repl = ["http://", "https://"]
- self.link = data['downloadlink'].replace(*http_repl if self.getConfig("ssl") else *http_repl[::-1])
-
- if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown") or pyfile.name.endswith('..'):
- # only use when name wasn't already set
- pyfile.name = self.getFilename(self.link)
-
-
- def checkFile(self):
- if self.checkDownload({"error": "<title>An error occured while processing your request</title>"})
- # usual this download can safely be retried
- self.retry(wait_time=60, reason=_("An error occured while generating link."))
-
- return super(OverLoadMe, self).checkFile()
-
-
-getInfo = create_getInfo(OverLoadMe)
diff --git a/module/plugins/hoster/PandaplaNet.py b/module/plugins/hoster/PandaplaNet.py
deleted file mode 100644
index a078ca3c9..000000000
--- a/module/plugins/hoster/PandaplaNet.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class PandaplaNet(DeadHoster):
- __name__ = "PandaplaNet"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?pandapla\.net/\w{12}'
-
- __description__ = """Pandapla.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("t4skforce", "t4skforce1337[AT]gmail[DOT]com")]
-
-
-getInfo = create_getInfo(PandaplaNet)
diff --git a/module/plugins/hoster/PotloadCom.py b/module/plugins/hoster/PotloadCom.py
deleted file mode 100644
index bcbcb57d0..000000000
--- a/module/plugins/hoster/PotloadCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class PotloadCom(DeadHoster):
- __name__ = "PotloadCom"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?potload\.com/\w{12}'
-
- __description__ = """Potload.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
-getInfo = create_getInfo(PotloadCom)
diff --git a/module/plugins/hoster/PremiumTo.py b/module/plugins/hoster/PremiumTo.py
deleted file mode 100644
index b66b9a505..000000000
--- a/module/plugins/hoster/PremiumTo.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-from os import remove
-
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-from module.utils import fs_encode
-
-
-class PremiumTo(MultiHoster):
- __name__ = "PremiumTo"
- __type__ = "hoster"
- __version__ = "0.21"
-
- __pattern__ = r'^unmatchable$'
-
- __description__ = """Premium.to multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("zoidberg", "zoidberg@mujmail.cz"),
- ("stickell", "l.stickell@yahoo.it")]
-
-
- CHECK_TRAFFIC = True
-
-
- def handlePremium(self, pyfile):
- #raise timeout to 2min
- self.download("http://premium.to/api/getfile.php",
- get={'username': self.account.username,
- 'password': self.account.password,
- 'link' : pyfile.url},
- disposition=True)
-
-
- def checkFile(self):
- if self.checkDownload({'nopremium': "No premium account available"}):
- self.retry(60, 5 * 60, "No premium account available")
-
- err = ''
- if self.req.http.code == '420':
- # Custom error code send - fail
- file = fs_encode(self.lastDownload)
- with open(file, "rb") as f:
- err = f.read(256).strip()
- remove(file)
-
- if err:
- self.fail(err)
-
- return super(PremiumTo, self).checkFile()
-
-
-getInfo = create_getInfo(PremiumTo)
diff --git a/module/plugins/hoster/PremiumizeMe.py b/module/plugins/hoster/PremiumizeMe.py
deleted file mode 100644
index 3d19c88ac..000000000
--- a/module/plugins/hoster/PremiumizeMe.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.common.json_layer import json_loads
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-
-
-class PremiumizeMe(MultiHoster):
- __name__ = "PremiumizeMe"
- __type__ = "hoster"
- __version__ = "0.16"
-
- __pattern__ = r'^unmatchable$' #: Since we want to allow the user to specify the list of hoster to use we let MultiHoster.coreReady
-
- __description__ = """Premiumize.me multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Florian Franzen", "FlorianFranzen@gmail.com")]
-
-
- def handlePremium(self, pyfile):
- # In some cases hostsers do not supply us with a filename at download, so we
- # are going to set a fall back filename (e.g. for freakshare or xfileshare)
- pyfile.name = pyfile.name.split('/').pop() # Remove everthing before last slash
-
- # Correction for automatic assigned filename: Removing html at end if needed
- suffix_to_remove = ["html", "htm", "php", "php3", "asp", "shtm", "shtml", "cfml", "cfm"]
- temp = pyfile.name.split('.')
- if temp.pop() in suffix_to_remove:
- pyfile.name = ".".join(temp)
-
- # Get account data
- user, data = self.account.selectAccount()
-
- # Get rewritten link using the premiumize.me api v1 (see https://secure.premiumize.me/?show=api)
- data = json_loads(self.load("https://api.premiumize.me/pm-api/v1.php",
- get={'method' : "directdownloadlink",
- 'params[login]': user,
- 'params[pass]' : data['password'],
- 'params[link]' : pyfile.url}))
-
- # Check status and decide what to do
- status = data['status']
-
- if status == 200:
- self.link = data['result']['location']
- return
-
- elif status == 400:
- self.fail(_("Invalid link"))
-
- elif status == 404:
- self.offline()
-
- elif status >= 500:
- self.tempOffline()
-
- else:
- self.fail(data['statusmessage'])
-
-
-getInfo = create_getInfo(PremiumizeMe)
diff --git a/module/plugins/hoster/PromptfileCom.py b/module/plugins/hoster/PromptfileCom.py
deleted file mode 100644
index 2aaf14736..000000000
--- a/module/plugins/hoster/PromptfileCom.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class PromptfileCom(SimpleHoster):
- __name__ = "PromptfileCom"
- __type__ = "hoster"
- __version__ = "0.13"
-
- __pattern__ = r'https?://(?:www\.)?promptfile\.com/'
-
- __description__ = """Promptfile.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("igel", "igelkun@myopera.com")]
-
-
- INFO_PATTERN = r'<span style="[^"]*" title="[^"]*">(?P<N>.*?) \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)</span>'
- OFFLINE_PATTERN = r'<span style="[^"]*" title="File Not Found">File Not Found</span>'
-
- CHASH_PATTERN = r'<input type="hidden" name="chash" value="([^"]*)" />'
- LINK_FREE_PATTERN = r'<a href=\"(.+)\" target=\"_blank\" class=\"view_dl_link\">Download File</a>'
-
-
- def handleFree(self, pyfile):
- # STAGE 1: get link to continue
- m = re.search(self.CHASH_PATTERN, self.html)
- if m is None:
- self.error(_("CHASH_PATTERN not found"))
- chash = m.group(1)
- self.logDebug("Read chash %s" % chash)
- # continue to stage2
- self.html = self.load(pyfile.url, decode=True, post={'chash': chash})
-
- # STAGE 2: get the direct link
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("LINK_FREE_PATTERN not found"))
-
- self.link = m.group(1)
-
-
-getInfo = create_getInfo(PromptfileCom)
diff --git a/module/plugins/hoster/PrzeklejPl.py b/module/plugins/hoster/PrzeklejPl.py
deleted file mode 100644
index ff19c770e..000000000
--- a/module/plugins/hoster/PrzeklejPl.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class PrzeklejPl(DeadHoster):
- __name__ = "PrzeklejPl"
- __type__ = "hoster"
- __version__ = "0.11"
-
- __pattern__ = r'http://(?:www\.)?przeklej\.pl/plik/.+'
-
- __description__ = """Przeklej.pl hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(PrzeklejPl)
diff --git a/module/plugins/hoster/PutdriveCom.py b/module/plugins/hoster/PutdriveCom.py
deleted file mode 100644
index 7f4b7b6cc..000000000
--- a/module/plugins/hoster/PutdriveCom.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.hoster.ZeveraCom import ZeveraCom
-
-
-class PutdriveCom(ZeveraCom):
- __name__ = "PutdriveCom"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'https?://(?:www\.)putdrive\.com/(getFiles\.ashx|Members/download\.ashx)\?.*ourl=.+'
-
- __description__ = """Multihosters.com multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
diff --git a/module/plugins/hoster/QuickshareCz.py b/module/plugins/hoster/QuickshareCz.py
deleted file mode 100644
index 5a3fd871b..000000000
--- a/module/plugins/hoster/QuickshareCz.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class QuickshareCz(SimpleHoster):
- __name__ = "QuickshareCz"
- __type__ = "hoster"
- __version__ = "0.56"
-
- __pattern__ = r'http://(?:[^/]*\.)?quickshare\.cz/stahnout-soubor/.+'
-
- __description__ = """Quickshare.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<th width="145px">Název:</th>\s*<td style="word-wrap:break-word;">(?P<N>[^<]+)</td>'
- SIZE_PATTERN = r'<th>Velikost:</th>\s*<td>(?P<S>[\d.,]+) (?P<U>[\w^_]+)</td>'
- OFFLINE_PATTERN = r'<script type="text/javascript">location\.href=\'/chyba\';</script>'
-
-
- def process(self, pyfile):
- self.html = self.load(pyfile.url, decode=True)
- self.getFileInfo()
-
- # parse js variables
- self.jsvars = dict((x, y.strip("'")) for x, y in re.findall(r"var (\w+) = ([\d.]+|'[^']*')", self.html))
- self.logDebug(self.jsvars)
- pyfile.name = self.jsvars['ID3']
-
- # determine download type - free or premium
- if self.premium:
- if 'UU_prihlasen' in self.jsvars:
- if self.jsvars['UU_prihlasen'] == '0':
- self.logWarning(_("User not logged in"))
- self.relogin(self.user)
- self.retry()
- elif float(self.jsvars['UU_kredit']) < float(self.jsvars['kredit_odecet']):
- self.logWarning(_("Not enough credit left"))
- self.premium = False
-
- if self.premium:
- self.handlePremium(pyfile)
- else:
- self.handleFree(pyfile)
-
- if self.checkDownload({"error": re.compile(r"\AChyba!")}, max_size=100):
- self.fail(_("File not m or plugin defect"))
-
-
- def handleFree(self, pyfile):
- # get download url
- download_url = '%s/download.php' % self.jsvars['server']
- data = dict((x, self.jsvars[x]) for x in self.jsvars if x in ("ID1", "ID2", "ID3", "ID4"))
- self.logDebug("FREE URL1:" + download_url, data)
-
- self.load(download_url, post=data, follow_location=False)
- self.header = self.req.http.header
-
- m = re.search(r'Location\s*:\s*(.+)', self.header, re.I)
- if m is None:
- self.fail(_("File not found"))
- download_url = m.group(1)
- self.logDebug("FREE URL2:" + download_url)
-
- # check errors
- m = re.search(r'/chyba/(\d+)', download_url)
- if m:
- if m.group(1) == '1':
- self.retry(60, 2 * 60, "This IP is already downloading")
- elif m.group(1) == '2':
- self.retry(60, 60, "No free slots available")
- else:
- self.fail(_("Error %d") % m.group(1))
-
- # download file
- self.download(download_url)
-
-
- def handlePremium(self, pyfile):
- download_url = '%s/download_premium.php' % self.jsvars['server']
- data = dict((x, self.jsvars[x]) for x in self.jsvars if x in ("ID1", "ID2", "ID4", "ID5"))
- self.download(download_url, get=data)
-
-
-getInfo = create_getInfo(QuickshareCz)
diff --git a/module/plugins/hoster/RPNetBiz.py b/module/plugins/hoster/RPNetBiz.py
deleted file mode 100644
index 8ab8cb7c4..000000000
--- a/module/plugins/hoster/RPNetBiz.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-from module.common.json_layer import json_loads
-
-
-class RPNetBiz(MultiHoster):
- __name__ = "RPNetBiz"
- __type__ = "hoster"
- __version__ = "0.14"
-
- __description__ = """RPNet.biz multi-hoster plugin"""
- __license__ = "GPLv3"
-
- __pattern__ = r'https?://.+rpnet\.biz'
- __authors__ = [("Dman", "dmanugm@gmail.com")]
-
-
- def setup(self):
- self.chunkLimit = -1
-
-
- def handlePremium(self, pyfile):
- user, data = self.account.selectAccount()
-
- # Get the download link
- res = self.load("https://premium.rpnet.biz/client_api.php",
- get={"username": user,
- "password": data['password'],
- "action" : "generate",
- "links" : pyfile.url})
-
- self.logDebug("JSON data: %s" % res)
- link_status = json_loads(res)['links'][0] # get the first link... since we only queried one
-
- # Check if we only have an id as a HDD link
- if 'id' in link_status:
- self.logDebug("Need to wait at least 30 seconds before requery")
- self.setWait(30) # wait for 30 seconds
- self.wait()
- # Lets query the server again asking for the status on the link,
- # we need to keep doing this until we reach 100
- max_tries = 30
- my_try = 0
- while (my_try <= max_tries):
- self.logDebug("Try: %d ; Max Tries: %d" % (my_try, max_tries))
- res = self.load("https://premium.rpnet.biz/client_api.php",
- get={"username": user,
- "password": data['password'],
- "action": "downloadInformation",
- "id": link_status['id']})
- self.logDebug("JSON data hdd query: %s" % res)
- download_status = json_loads(res)['download']
-
- if download_status['status'] == '100':
- link_status['generated'] = download_status['rpnet_link']
- self.logDebug("Successfully downloaded to rpnet HDD: %s" % link_status['generated'])
- break
- else:
- self.logDebug("At %s%% for the file download" % download_status['status'])
-
- self.setWait(30)
- self.wait()
- my_try += 1
-
- if my_try > max_tries: # We went over the limit!
- self.fail(_("Waited for about 15 minutes for download to finish but failed"))
-
- if 'generated' in link_status:
- self.link = link_status['generated']
- return
- elif 'error' in link_status:
- self.fail(link_status['error'])
- else:
- self.fail(_("Something went wrong, not supposed to enter here"))
-
-
-getInfo = create_getInfo(RPNetBiz)
diff --git a/module/plugins/hoster/RapideoPl.py b/module/plugins/hoster/RapideoPl.py
deleted file mode 100644
index 85591f51f..000000000
--- a/module/plugins/hoster/RapideoPl.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.common.json_layer import json_loads
-from module.plugins.internal.MultiHoster import MultiHoster
-
-
-class RapideoPl(MultiHoster):
- __name__ = "RapideoPl"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'^unmatchable$'
-
- __description__ = """Rapideo.pl multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("goddie", "dev@rapideo.pl")]
-
-
- API_URL = "http://enc.rapideo.pl"
-
- API_QUERY = {'site' : "newrd",
- 'output' : "json",
- 'username': "",
- 'password': "",
- 'url' : ""}
-
- ERROR_CODES = {0 : "[%s] Incorrect login credentials",
- 1 : "[%s] Not enough transfer to download - top-up your account",
- 2 : "[%s] Incorrect / dead link",
- 3 : "[%s] Error connecting to hosting, try again later",
- 9 : "[%s] Premium account has expired",
- 15: "[%s] Hosting no longer supported",
- 80: "[%s] Too many incorrect login attempts, account blocked for 24h"}
-
-
- def prepare(self):
- super(RapideoPl, self).prepare()
-
- data = self.account.getAccountData(self.user)
-
- self.usr = data['usr']
- self.pwd = data['pwd']
-
-
- def runFileQuery(self, url, mode=None):
- query = self.API_QUERY.copy()
-
- query["username"] = self.usr
- query["password"] = self.pwd
- query["url"] = url
-
- if mode == "fileinfo":
- query['check'] = 2
- query['loc'] = 1
-
- self.logDebug(query)
-
- return self.load(self.API_URL, post=query)
-
-
- def handleFree(self, pyfile):
- try:
- data = self.runFileQuery(pyfile.url, 'fileinfo')
-
- except Exception:
- self.logDebug("RunFileQuery error")
- self.tempOffline()
-
- try:
- parsed = json_loads(data)
-
- except Exception:
- self.logDebug("Loads error")
- self.tempOffline()
-
- self.logDebug(parsed)
-
- if "errno" in parsed.keys():
- if parsed["errno"] in self.ERROR_CODES:
- # error code in known
- self.fail(self.ERROR_CODES[parsed["errno"]] % self.__name__)
- else:
- # error code isn't yet added to plugin
- self.fail(
- parsed["errstring"]
- or _("Unknown error (code: %s)") % parsed["errno"]
- )
-
- if "sdownload" in parsed:
- if parsed["sdownload"] == "1":
- self.fail(
- _("Download from %s is possible only using Rapideo.pl website \
- directly") % parsed["hosting"])
-
- pyfile.name = parsed["filename"]
- pyfile.size = parsed["filesize"]
-
- try:
- self.link = self.runFileQuery(pyfile.url, 'filedownload')
-
- except Exception:
- self.logDebug("runFileQuery error #2")
- self.tempOffline()
diff --git a/module/plugins/hoster/RapidfileshareNet.py b/module/plugins/hoster/RapidfileshareNet.py
deleted file mode 100644
index 6d54f72f2..000000000
--- a/module/plugins/hoster/RapidfileshareNet.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class RapidfileshareNet(XFSHoster):
- __name__ = "RapidfileshareNet"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?rapidfileshare\.net/\w{12}'
-
- __description__ = """Rapidfileshare.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("guidobelix", "guidobelix@hotmail.it")]
-
-
- NAME_PATTERN = r'<input type="hidden" name="fname" value="(?P<N>.+?)">'
- SIZE_PATTERN = r'>http://www.rapidfileshare.net/\w+?</font> \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)</font>'
-
- OFFLINE_PATTERN = r'>No such file with this filename'
- TEMP_OFFLINE_PATTERN = r'The page may have been renamed, removed or be temporarily unavailable.<'
-
-
-getInfo = create_getInfo(RapidfileshareNet)
diff --git a/module/plugins/hoster/RapidgatorNet.py b/module/plugins/hoster/RapidgatorNet.py
deleted file mode 100644
index 2dfd8f59c..000000000
--- a/module/plugins/hoster/RapidgatorNet.py
+++ /dev/null
@@ -1,172 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pycurl import HTTPHEADER
-
-from module.common.json_layer import json_loads
-from module.network.HTTPRequest import BadHeader
-from module.plugins.internal.CaptchaService import AdsCaptcha, ReCaptcha, SolveMedia
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, secondsToMidnight
-
-
-class RapidgatorNet(SimpleHoster):
- __name__ = "RapidgatorNet"
- __type__ = "hoster"
- __version__ = "0.32"
-
- __pattern__ = r'http://(?:www\.)?(rapidgator\.net|rg\.to)/file/\w+'
-
- __description__ = """Rapidgator.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
- ("chrox", ""),
- ("stickell", "l.stickell@yahoo.it"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- API_URL = "http://rapidgator.net/api/file"
-
- COOKIES = [("rapidgator.net", "lang", "en")]
-
- NAME_PATTERN = r'<title>Download file (?P<N>.*)</title>'
- SIZE_PATTERN = r'File size:\s*<strong>(?P<S>[\d.,]+) (?P<U>[\w^_]+)</strong>'
- OFFLINE_PATTERN = r'>(File not found|Error 404)'
-
- JSVARS_PATTERN = r'\s+var\s*(startTimerUrl|getDownloadUrl|captchaUrl|fid|secs)\s*=\s*\'?(.*?)\'?;'
-
- PREMIUM_ONLY_PATTERN = r'You can download files up to|This file can be downloaded by premium only<'
- ERROR_PATTERN = r'You have reached your (daily|hourly) downloads limit'
- WAIT_PATTERN = r'(Delay between downloads must be not less than|Try again in).+'
-
- LINK_FREE_PATTERN = r'return \'(http://\w+.rapidgator.net/.*)\';'
-
- RECAPTCHA_PATTERN = r'"http://api\.recaptcha\.net/challenge\?k=(.*?)"'
- ADSCAPTCHA_PATTERN = r'(http://api\.adscaptcha\.com/Get\.aspx[^"\']*)'
- SOLVEMEDIA_PATTERN = r'http://api\.solvemedia\.com/papi/challenge\.script\?k=(.*?)"'
-
-
- def setup(self):
- if self.account:
- self.sid = self.account.getAccountInfo(self.user).get('sid', None)
- else:
- self.sid = None
-
- if self.sid:
- self.premium = True
-
- self.resumeDownload = self.multiDL = self.premium
- self.chunkLimit = 1
-
-
- def api_response(self, cmd):
- try:
- json = self.load('%s/%s' % (self.API_URL, cmd),
- get={'sid': self.sid,
- 'url': self.pyfile.url}, decode=True)
- self.logDebug("API:%s" % cmd, json, "SID: %s" % self.sid)
- json = json_loads(json)
- status = json['response_status']
- msg = json['response_details']
-
- except BadHeader, e:
- self.logError("API: %s" % cmd, e, "SID: %s" % self.sid)
- status = e.code
- msg = e
-
- if status == 200:
- return json['response']
-
- elif status == 423:
- self.account.empty(self.user)
- self.retry()
-
- else:
- self.account.relogin(self.user)
- self.retry(wait_time=60)
-
-
- def handlePremium(self, pyfile):
- self.api_data = self.api_response('info')
- self.api_data['md5'] = self.api_data['hash']
-
- pyfile.name = self.api_data['filename']
- pyfile.size = self.api_data['size']
-
- self.link = self.api_response('download')['url']
-
-
- def handleFree(self, pyfile):
- jsvars = dict(re.findall(self.JSVARS_PATTERN, self.html))
- self.logDebug(jsvars)
-
- self.req.http.lastURL = pyfile.url
- self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
-
- url = "http://rapidgator.net%s?fid=%s" % (
- jsvars.get('startTimerUrl', '/download/AjaxStartTimer'), jsvars['fid'])
- jsvars.update(self.getJsonResponse(url))
-
- self.wait(jsvars.get('secs', 45), False)
-
- url = "http://rapidgator.net%s?sid=%s" % (
- jsvars.get('getDownloadUrl', '/download/AjaxGetDownload'), jsvars['sid'])
- jsvars.update(self.getJsonResponse(url))
-
- self.req.http.lastURL = pyfile.url
- self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With:"])
-
- url = "http://rapidgator.net%s" % jsvars.get('captchaUrl', '/download/captcha')
- self.html = self.load(url)
-
- for _i in xrange(5):
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m:
- self.link = m.group(1)
- break
- else:
- captcha, captcha_key = self.handleCaptcha()
- response, challenge = captcha.challenge(captcha_key)
-
- self.html = self.load(url, post={'DownloadCaptchaForm[captcha]': "",
- 'adcopy_challenge' : challenge,
- 'adcopy_response' : response})
-
- if "The verification code is incorrect" in self.html:
- self.invalidCaptcha()
- else:
- self.correctCaptcha()
- else:
- self.error(_("Download link"))
-
-
- def handleCaptcha(self):
- m = re.search(self.ADSCAPTCHA_PATTERN, self.html)
- if m:
- captcha_key = m.group(1)
- captcha = AdsCaptcha(self)
- else:
- m = re.search(self.RECAPTCHA_PATTERN, self.html)
- if m:
- captcha_key = m.group(1)
- captcha = ReCaptcha(self)
- else:
- m = re.search(self.SOLVEMEDIA_PATTERN, self.html)
- if m:
- captcha_key = m.group(1)
- captcha = SolveMedia(self)
- else:
- self.error(_("Captcha"))
-
- return captcha, captcha_key
-
-
- def getJsonResponse(self, url):
- res = self.load(url, decode=True)
- if not res.startswith('{'):
- self.retry()
- self.logDebug(url, res)
- return json_loads(res)
-
-
-getInfo = create_getInfo(RapidgatorNet)
diff --git a/module/plugins/hoster/RapiduNet.py b/module/plugins/hoster/RapiduNet.py
deleted file mode 100644
index 5c12bf924..000000000
--- a/module/plugins/hoster/RapiduNet.py
+++ /dev/null
@@ -1,86 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pycurl import HTTPHEADER
-from time import time, altzone
-
-from pyload.utils import json_loads
-from pyload.plugin.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class RapiduNet(SimpleHoster):
- __name__ = "RapiduNet"
- __type__ = "hoster"
- __version__ = "0.07"
-
- __pattern__ = r'https?://(?:www\.)?rapidu\.net/(?P<ID>\d{10})'
-
- __description__ = """Rapidu.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("prOq", "")]
-
-
- COOKIES = [("rapidu.net", "rapidu_lang", "en")]
-
- INFO_PATTERN = r'<h1 title="(?P<N>.*)">.*</h1>\s*<small>(?P<S>\d+(\.\d+)?)\s(?P<U>\w+)</small>'
- OFFLINE_PATTERN = r'404 - File not found'
-
- ERROR_PATTERN = r'<div class="error">'
-
- RECAPTCHA_KEY = r'6Ld12ewSAAAAAHoE6WVP_pSfCdJcBQScVweQh8Io'
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = self.premium
-
-
- def handleFree(self, pyfile):
- self.req.http.lastURL = pyfile.url
- self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
-
- jsvars = self.getJsonResponse("https://rapidu.net/ajax.php",
- get={'a': "getLoadTimeToDownload"},
- post={'_go': ""},
- decode=True)
-
- if str(jsvars['timeToDownload']) is "stop":
- t = (24 * 60 * 60) - (int(time()) % (24 * 60 * 60)) + altzone
-
- self.logInfo("You've reach your daily download transfer")
-
- self.retry(10, 10 if t < 1 else None, _("Try tomorrow again")) #@NOTE: check t in case of not synchronised clock
-
- else:
- self.wait(int(jsvars['timeToDownload']) - int(time()))
-
- recaptcha = ReCaptcha(self)
-
- for _i in xrange(10):
- response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY)
-
- jsvars = self.getJsonResponse("https://rapidu.net/ajax.php",
- get={'a': "getCheckCaptcha"},
- post={'_go' : "",
- 'captcha1': challenge,
- 'captcha2': response,
- 'fileId' : self.info['pattern']['ID']},
- decode=True)
- if jsvars['message'] == 'success':
- self.download(jsvars['url'])
- break
-
-
- def getJsonResponse(self, *args, **kwargs):
- res = self.load(*args, **kwargs)
- if not res.startswith('{'):
- self.retry()
-
- self.logDebug(res)
-
- return json_loads(res)
-
-
-getInfo = create_getInfo(RapiduNet)
diff --git a/module/plugins/hoster/RarefileNet.py b/module/plugins/hoster/RarefileNet.py
deleted file mode 100644
index 8f0bf8834..000000000
--- a/module/plugins/hoster/RarefileNet.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class RarefileNet(XFSHoster):
- __name__ = "RarefileNet"
- __type__ = "hoster"
- __version__ = "0.09"
-
- __pattern__ = r'http://(?:www\.)?rarefile\.net/\w{12}'
-
- __description__ = """Rarefile.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- LINK_PATTERN = r'<a href="(.+?)">\1</a>'
-
-
-getInfo = create_getInfo(RarefileNet)
diff --git a/module/plugins/hoster/RealdebridCom.py b/module/plugins/hoster/RealdebridCom.py
deleted file mode 100644
index d0010b3bd..000000000
--- a/module/plugins/hoster/RealdebridCom.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from random import randrange
-from urllib import unquote
-from time import time
-
-from module.common.json_layer import json_loads
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-from module.utils import parseFileSize
-
-
-class RealdebridCom(MultiHoster):
- __name__ = "RealdebridCom"
- __type__ = "hoster"
- __version__ = "0.64"
-
- __pattern__ = r'https?://((?:www\.|s\d+\.)?real-debrid\.com/dl/|[\w^_]\.rdb\.so/d/)[\w^_]+'
-
- __description__ = """Real-Debrid.com multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Devirex Hazzard", "naibaf_11@yahoo.de")]
-
-
- def getFilename(self, url):
- try:
- name = unquote(url.rsplit("/", 1)[1])
- except IndexError:
- name = "Unknown_Filename..."
- if not name or name.endswith(".."): #: incomplete filename, append random stuff
- name += "%s.tmp" % randrange(100, 999)
- return name
-
-
- def setup(self):
- self.chunkLimit = 3
-
-
- def handlePremium(self, pyfile):
- data = json_loads(self.load("https://real-debrid.com/ajax/unrestrict.php",
- get={'lang' : "en",
- 'link' : pyfile.url,
- 'password': self.getPassword(),
- 'time' : int(time() * 1000)}))
-
- self.logDebug("Returned Data: %s" % data)
-
- if data['error'] != 0:
- if data['message'] == "Your file is unavailable on the hoster.":
- self.offline()
- else:
- self.logWarning(data['message'])
- self.tempOffline()
- else:
- if pyfile.name is not None and pyfile.name.endswith('.tmp') and data['file_name']:
- pyfile.name = data['file_name']
- pyfile.size = parseFileSize(data['file_size'])
- self.link = data['generated_links'][0][-1]
-
- if self.getConfig("ssl"):
- self.link = self.link.replace("http://", "https://")
- else:
- self.link = self.link.replace("https://", "http://")
-
- if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown") or pyfile.name.endswith('..'):
- #only use when name wasnt already set
- pyfile.name = self.getFilename(self.link)
-
-
- def checkFile(self):
- if self.checkDownload({"error": "<title>An error occured while processing your request</title>"}):
- #usual this download can safely be retried
- self.retry(wait_time=60, reason=_("An error occured while generating link"))
-
- return super(RealdebridCom, self).checkFile()
-
-
-getInfo = create_getInfo(RealdebridCom)
diff --git a/module/plugins/hoster/RehostTo.py b/module/plugins/hoster/RehostTo.py
deleted file mode 100644
index 28de35d08..000000000
--- a/module/plugins/hoster/RehostTo.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from urllib import unquote
-
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-
-
-class RehostTo(MultiHoster):
- __name__ = "RehostTo"
- __type__ = "hoster"
- __version__ = "0.21"
-
- __pattern__ = r'https?://.*rehost\.to\..+'
-
- __description__ = """Rehost.com multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org")]
-
-
- def handlePremium(self, pyfile):
- self.download("http://rehost.to/process_download.php",
- get={'user': "cookie",
- 'pass': self.account.getAccountInfo(self.user)['session'],
- 'dl' : pyfile.url},
- disposition=True)
-
-
-getInfo = create_getInfo(RehostTo)
diff --git a/module/plugins/hoster/RemixshareCom.py b/module/plugins/hoster/RemixshareCom.py
deleted file mode 100644
index b1587ad6d..000000000
--- a/module/plugins/hoster/RemixshareCom.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# http://remixshare.com/download/p946u
-#
-# Note:
-# The remixshare.com website is very very slow, so
-# if your download not starts because of pycurl timeouts:
-# Adjust timeouts in /usr/share/pyload/pyload/network/HTTPRequest.py
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class RemixshareCom(SimpleHoster):
- __name__ = "RemixshareCom"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'https?://remixshare\.com/(download|dl)/\w+'
-
- __description__ = """Remixshare.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- INFO_PATTERN = r'title=\'.+?\'>(?P<N>.+?)</span><span class=\'light2\'>&nbsp;\((?P<S>\d+)&nbsp;(?P<U>[\w^_]+)\)<'
- OFFLINE_PATTERN = r'<h1>Ooops!<'
-
- LINK_FREE_PATTERN = r'(http://remixshare\.com/downloadfinal/.+?)"'
- TOKEN_PATTERN = r'var acc = (\d+)'
- WAIT_PATTERN = r'var XYZ = r"(\d+)"'
-
-
- def setup(self):
- self.multiDL = True
- self.chunkLimit = 1
-
-
- def handleFree(self, pyfile):
- b = re.search(self.LINK_FREE_PATTERN, self.html)
- if not b:
- self.error(_("Cannot parse download url"))
-
- c = re.search(self.TOKEN_PATTERN, self.html)
- if not c:
- self.error(_("Cannot parse file token"))
-
- self.link = b.group(1) + c.group(1)
-
- #Check if we have to wait
- seconds = re.search(self.WAIT_PATTERN, self.html)
- if seconds:
- self.logDebug("Wait " + seconds.group(1))
- self.wait(seconds.group(1))
-
-
-getInfo = create_getInfo(RemixshareCom)
diff --git a/module/plugins/hoster/RgHostNet.py b/module/plugins/hoster/RgHostNet.py
deleted file mode 100644
index 7a16598b2..000000000
--- a/module/plugins/hoster/RgHostNet.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class RgHostNet(SimpleHoster):
- __name__ = "RgHostNet"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?rghost\.net/\d+(?:r=\d+)?'
-
- __description__ = """RgHost.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("z00nx", "z00nx0@gmail.com")]
-
-
- INFO_PATTERN = r'<h1>\s+(<a[^>]+>)?(?P<N>[^<]+)(</a>)?\s+<small[^>]+>\s+\((?P<S>[^)]+)\)\s+</small>\s+</h1>'
- OFFLINE_PATTERN = r'File is deleted|this page is not found'
-
- LINK_FREE_PATTERN = r'<a\s+href="([^"]+)"\s+class="btn\s+large\s+download"[^>]+>Download</a>'
-
-
-getInfo = create_getInfo(RgHostNet)
diff --git a/module/plugins/hoster/SafesharingEu.py b/module/plugins/hoster/SafesharingEu.py
deleted file mode 100644
index c1fc9c68d..000000000
--- a/module/plugins/hoster/SafesharingEu.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class SafesharingEu(XFSHoster):
- __name__ = "SafesharingEu"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'https?://(?:www\.)?safesharing\.eu/\w{12}'
-
- __description__ = """Safesharing.eu hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
-
-
- ERROR_PATTERN = r'(?:<div class="alert alert-danger">)(.+?)(?:</div>)'
-
-
-getInfo = create_getInfo(SafesharingEu)
diff --git a/module/plugins/hoster/SecureUploadEu.py b/module/plugins/hoster/SecureUploadEu.py
deleted file mode 100644
index 0b2b603bf..000000000
--- a/module/plugins/hoster/SecureUploadEu.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class SecureUploadEu(XFSHoster):
- __name__ = "SecureUploadEu"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'https?://(?:www\.)?secureupload\.eu/\w{12}'
-
- __description__ = """SecureUpload.eu hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("z00nx", "z00nx0@gmail.com")]
-
-
- INFO_PATTERN = r'<h3>Downloading (?P<N>[^<]+) \((?P<S>[^<]+)\)</h3>'
-
-
-getInfo = create_getInfo(SecureUploadEu)
diff --git a/module/plugins/hoster/SendspaceCom.py b/module/plugins/hoster/SendspaceCom.py
deleted file mode 100644
index 5310051d1..000000000
--- a/module/plugins/hoster/SendspaceCom.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class SendspaceCom(SimpleHoster):
- __name__ = "SendspaceCom"
- __type__ = "hoster"
- __version__ = "0.17"
-
- __pattern__ = r'https?://(?:www\.)?sendspace\.com/file/\w+'
-
- __description__ = """Sendspace.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<h2 class="bgray">\s*<(?:b|strong)>(?P<N>[^<]+)</'
- SIZE_PATTERN = r'<div class="file_description reverse margin_center">\s*<b>File Size:</b>\s*(?P<S>[\d.,]+)(?P<U>[\w^_]+)\s*</div>'
- OFFLINE_PATTERN = r'<div class="msg error" style="cursor: default">Sorry, the file you requested is not available.</div>'
-
- LINK_FREE_PATTERN = r'<a id="download_button" href="([^"]+)"'
-
- CAPTCHA_PATTERN = r'<td><img src="(/captchas/captcha\.php?captcha=([^"]+))"></td>'
- USER_CAPTCHA_PATTERN = r'<td><img src="/captchas/captcha\.php?user=([^"]+))"></td>'
-
-
- def handleFree(self, pyfile):
- params = {}
- for _i in xrange(3):
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m:
- if 'captcha_hash' in params:
- self.correctCaptcha()
- download_url = m.group(1)
- break
-
- m = re.search(self.CAPTCHA_PATTERN, self.html)
- if m:
- if 'captcha_hash' in params:
- self.invalidCaptcha()
- captcha_url1 = "http://www.sendspace.com/" + m.group(1)
- m = re.search(self.USER_CAPTCHA_PATTERN, self.html)
- captcha_url2 = "http://www.sendspace.com/" + m.group(1)
- params = {'captcha_hash': m.group(2),
- 'captcha_submit': 'Verify',
- 'captcha_answer': self.decryptCaptcha(captcha_url1) + " " + self.decryptCaptcha(captcha_url2)}
- else:
- params = {'download': "Regular Download"}
-
- self.logDebug(params)
- self.html = self.load(pyfile.url, post=params)
- else:
- self.fail(_("Download link not found"))
-
- self.download(download_url)
-
-
-getInfo = create_getInfo(SendspaceCom)
diff --git a/module/plugins/hoster/Share4WebCom.py b/module/plugins/hoster/Share4WebCom.py
deleted file mode 100644
index 0c2ee358e..000000000
--- a/module/plugins/hoster/Share4WebCom.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.hoster.UnibytesCom import UnibytesCom
-from pyload.plugin.internal.SimpleHoster import create_getInfo
-
-
-class Share4WebCom(UnibytesCom):
- __name__ = "Share4WebCom"
- __type__ = "hoster"
- __version__ = "0.11"
-
- __pattern__ = r'https?://(?:www\.)?share4web\.com/get/\w+'
-
- __description__ = """Share4web.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- HOSTER_DOMAIN = "share4web.com"
-
-
-getInfo = create_getInfo(Share4WebCom)
diff --git a/module/plugins/hoster/Share76Com.py b/module/plugins/hoster/Share76Com.py
deleted file mode 100644
index 7f2cea757..000000000
--- a/module/plugins/hoster/Share76Com.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class Share76Com(DeadHoster):
- __name__ = "Share76Com"
- __type__ = "hoster"
- __version__ = "0.04"
-
- __pattern__ = r'http://(?:www\.)?share76\.com/\w{12}'
-
- __description__ = """Share76.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = []
-
-
-getInfo = create_getInfo(Share76Com)
diff --git a/module/plugins/hoster/ShareFilesCo.py b/module/plugins/hoster/ShareFilesCo.py
deleted file mode 100644
index dd5c9b85d..000000000
--- a/module/plugins/hoster/ShareFilesCo.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class ShareFilesCo(DeadHoster):
- __name__ = "ShareFilesCo"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?sharefiles\.co/\w{12}'
-
- __description__ = """Sharefiles.co hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
-getInfo = create_getInfo(ShareFilesCo)
diff --git a/module/plugins/hoster/SharebeesCom.py b/module/plugins/hoster/SharebeesCom.py
deleted file mode 100644
index 3843a352b..000000000
--- a/module/plugins/hoster/SharebeesCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class SharebeesCom(DeadHoster):
- __name__ = "SharebeesCom"
- __type__ = "hoster"
- __version__ = "0.02"
-
- __pattern__ = r'http://(?:www\.)?sharebees\.com/\w{12}'
-
- __description__ = """ShareBees hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(SharebeesCom)
diff --git a/module/plugins/hoster/ShareonlineBiz.py b/module/plugins/hoster/ShareonlineBiz.py
deleted file mode 100644
index b37b4b0bc..000000000
--- a/module/plugins/hoster/ShareonlineBiz.py
+++ /dev/null
@@ -1,187 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from time import time
-from urllib import unquote
-from urlparse import urlparse
-
-from pyload.network.RequestFactory import getURL
-from pyload.plugin.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class ShareonlineBiz(SimpleHoster):
- __name__ = "ShareonlineBiz"
- __type__ = "hoster"
- __version__ = "0.48"
-
- __pattern__ = r'https?://(?:www\.)?(share-online\.biz|egoshare\.com)/(download\.php\?id=|dl/)(?P<ID>\w+)'
-
- __description__ = """Shareonline.biz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("spoob", "spoob@pyload.org"),
- ("mkaay", "mkaay@mkaay.de"),
- ("zoidberg", "zoidberg@mujmail.cz"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- URL_REPLACEMENTS = [(__pattern__ + ".*", "http://www.share-online.biz/dl/\g<ID>")]
-
- CHECK_TRAFFIC = True
-
- RECAPTCHA_KEY = "6LdatrsSAAAAAHZrB70txiV5p-8Iv8BtVxlTtjKX"
-
- ERROR_PATTERN = r'<p class="b">Information:</p>\s*<div>\s*<strong>(.*?)</strong>'
-
-
- @classmethod
- def getInfo(cls, url="", html=""):
- info = {'name': urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 3 if url else 1, 'url': url}
-
- if url:
- info['pattern'] = re.match(cls.__pattern__, url).groupdict()
-
- field = getURL("http://api.share-online.biz/linkcheck.php",
- get={'md5': "1"},
- post={'links': info['pattern']['ID']},
- decode=True).split(";")
-
- if field[1] == "OK":
- info['fileid'] = field[0]
- info['status'] = 2
- info['name'] = field[2]
- info['size'] = field[3] #: in bytes
- info['md5'] = field[4].strip().lower().replace("\n\n", "") #: md5
-
- elif field[1] in ("DELETED", "NOT FOUND"):
- info['status'] = 1
-
- return info
-
-
- def setup(self):
- self.resumeDownload = self.premium
- self.multiDL = False
-
-
- def handleCaptcha(self):
- recaptcha = ReCaptcha(self)
-
- for _i in xrange(5):
- response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY)
-
- m = re.search(r'var wait=(\d+);', self.html)
- self.setWait(int(m.group(1)) if m else 30)
-
- res = self.load("%s/free/captcha/%d" % (self.pyfile.url, int(time() * 1000)),
- post={'dl_free' : "1",
- 'recaptcha_challenge_field': challenge,
- 'recaptcha_response_field' : response})
- if not res == '0':
- self.correctCaptcha()
- return res
- else:
- self.invalidCaptcha()
- else:
- self.invalidCaptcha()
- self.fail(_("No valid captcha solution received"))
-
-
- def handleFree(self, pyfile):
- self.wait(3)
-
- self.html = self.load("%s/free/" % pyfile.url,
- post={'dl_free': "1", 'choice': "free"},
- decode=True)
-
- self.checkErrors()
-
- res = self.handleCaptcha()
- download_url = res.decode('base64')
-
- if not download_url.startswith("http://"):
- self.error(_("Wrong download url"))
-
- self.wait()
-
- self.download(download_url)
-
-
- def checkFile(self):
- check = self.checkDownload({'cookie': re.compile(r'<div id="dl_failure"'),
- 'fail' : re.compile(r"<title>Share-Online")})
-
- if check == "cookie":
- self.invalidCaptcha()
- self.retry(5, 60, _("Cookie failure"))
-
- elif check == "fail":
- self.invalidCaptcha()
- self.retry(5, 5 * 60, _("Download failed"))
-
- return super(ShareonlineBiz, self).checkFile()
-
-
- def handlePremium(self, pyfile): #: should be working better loading (account) api internally
- html = self.load("http://api.share-online.biz/account.php",
- get={'username': self.user,
- 'password': self.account.getAccountData(self.user)['password'],
- 'act' : "download",
- 'lid' : self.info['fileid']})
-
- self.api_data = dlinfo = {}
-
- for line in html.splitlines():
- key, value = line.split(": ")
- dlinfo[key.lower()] = value
-
- self.logDebug(dlinfo)
-
- if not dlinfo['status'] == "online":
- self.offline()
- else:
- pyfile.name = dlinfo['name']
- pyfile.size = int(dlinfo['size'])
-
- dlLink = dlinfo['url']
-
- if dlLink == "server_under_maintenance":
- self.tempOffline()
- else:
- self.multiDL = True
- self.download(dlLink)
-
-
- def checkErrors(self):
- m = re.search(r"/failure/(.*?)/1", self.req.lastEffectiveURL)
- if m is None:
- self.info.pop('error', None)
- return
-
- errmsg = m.group(1).lower()
-
- try:
- self.logError(errmsg, re.search(self.ERROR_PATTERN, self.html).group(1))
- except Exception:
- self.logError("Unknown error occurred", errmsg)
-
- if errmsg is "invalid":
- self.fail(_("File not available"))
-
- elif errmsg in ("freelimit", "size", "proxy"):
- self.fail(_("Premium account needed"))
-
- elif errmsg in ("expired", "server"):
- self.retry(wait_time=600, reason=errmsg)
-
- elif 'slot' in errmsg:
- self.wantReconnect = True
- self.retry(24, 3600, errmsg)
-
- else:
- self.wantReconnect = True
- self.retry(wait_time=60, reason=errmsg)
-
-
-getInfo = create_getInfo(ShareonlineBiz)
diff --git a/module/plugins/hoster/SharingmatrixCom.py b/module/plugins/hoster/SharingmatrixCom.py
deleted file mode 100644
index a20a36543..000000000
--- a/module/plugins/hoster/SharingmatrixCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class SharingmatrixCom(DeadHoster):
- __name__ = "SharingmatrixCom"
- __type__ = "hoster"
- __version__ = "0.01"
-
- __pattern__ = r'http://(?:www\.)?sharingmatrix\.com/file/\w+'
-
- __description__ = """Sharingmatrix.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("jeix", "jeix@hasnomail.de"),
- ("paulking", "")]
-
-
-getInfo = create_getInfo(SharingmatrixCom)
diff --git a/module/plugins/hoster/ShragleCom.py b/module/plugins/hoster/ShragleCom.py
deleted file mode 100644
index cf975b2f5..000000000
--- a/module/plugins/hoster/ShragleCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class ShragleCom(DeadHoster):
- __name__ = "ShragleCom"
- __type__ = "hoster"
- __version__ = "0.22"
-
- __pattern__ = r'http://(?:www\.)?(cloudnator|shragle)\.com/files/(?P<ID>.+?)/'
-
- __description__ = """Cloudnator.com (Shragle.com) hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(ShragleCom)
diff --git a/module/plugins/hoster/SimplyPremiumCom.py b/module/plugins/hoster/SimplyPremiumCom.py
deleted file mode 100644
index a87e7533f..000000000
--- a/module/plugins/hoster/SimplyPremiumCom.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from datetime import datetime, timedelta
-
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-from module.plugins.internal.SimpleHoster import secondsToMidnight
-
-
-class SimplyPremiumCom(MultiHoster):
- __name__ = "SimplyPremiumCom"
- __type__ = "hoster"
- __version__ = "0.08"
-
- __pattern__ = r'https?://.+simply-premium\.com'
-
- __description__ = """Simply-Premium.com multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("EvolutionClip", "evolutionclip@live.de")]
-
-
- def setup(self):
- self.chunkLimit = 16
-
-
- def checkErrors(self):
- if '<valid>0</valid>' in self.html or (
- "You are not allowed to download from this host" in self.html and self.premium):
- self.account.relogin(self.user)
- self.retry()
-
- elif "NOTFOUND" in self.html:
- self.offline()
-
- elif "downloadlimit" in self.html:
- self.logWarning(_("Reached maximum connctions"))
- self.retry(5, 60, _("Reached maximum connctions"))
-
- elif "trafficlimit" in self.html:
- self.logWarning(_("Reached daily limit for this host"))
- self.retry(wait_time=secondsToMidnight(gmt=2), reason="Daily limit for this host reached")
-
- elif "hostererror" in self.html:
- self.logWarning(_("Hoster temporarily unavailable, waiting 1 minute and retry"))
- self.retry(5, 60, _("Hoster is temporarily unavailable"))
-
-
- def handlePremium(self, pyfile):
- for i in xrange(5):
- self.html = self.load("http://www.simply-premium.com/premium.php", get={'info': "", 'link': self.pyfile.url})
-
- if self.html:
- self.logDebug("JSON data: " + self.html)
- break
- else:
- self.logInfo(_("Unable to get API data, waiting 1 minute and retry"))
- self.retry(5, 60, _("Unable to get API data"))
-
- self.checkErrors()
-
- try:
- self.pyfile.name = re.search(r'<name>([^<]+)</name>', self.html).group(1)
-
- except AttributeError:
- self.pyfile.name = ""
-
- try:
- self.pyfile.size = re.search(r'<size>(\d+)</size>', self.html).group(1)
-
- except AttributeError:
- self.pyfile.size = 0
-
- try:
- self.link = re.search(r'<download>([^<]+)</download>', self.html).group(1)
-
- except AttributeError:
- self.link = 'http://www.simply-premium.com/premium.php?link=' + self.pyfile.url
-
-
-getInfo = create_getInfo(SimplyPremiumCom)
diff --git a/module/plugins/hoster/SimplydebridCom.py b/module/plugins/hoster/SimplydebridCom.py
deleted file mode 100644
index 24811d6aa..000000000
--- a/module/plugins/hoster/SimplydebridCom.py
+++ /dev/null
@@ -1,48 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo, replace_patterns
-
-
-class SimplydebridCom(MultiHoster):
- __name__ = "SimplydebridCom"
- __type__ = "hoster"
- __version__ = "0.15"
-
- __pattern__ = r'http://\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/sd\.php'
-
- __description__ = """Simply-debrid.com multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Kagenoshin", "kagenoshin@gmx.ch")]
-
-
- def handlePremium(self, pyfile):
- #fix the links for simply-debrid.com!
- self.link = replace_patterns(pyfile.url, [("clz.to", "cloudzer.net/file")
- ("http://share-online", "http://www.share-online")
- ("ul.to", "uploaded.net/file")
- ("uploaded.com", "uploaded.net")
- ("filerio.com", "filerio.in")
- ("lumfile.com", "lumfile.se")]
-
- if 'fileparadox' in self.link:
- self.link = self.link.replace("http://", "https://")
-
- self.html = self.load("http://simply-debrid.com/api.php", get={'dl': self.link})
- if 'tiger Link' in self.html or 'Invalid Link' in self.html or ('API' in self.html and 'ERROR' in self.html):
- self.error(_("Unable to unrestrict link"))
-
- self.link = self.html
-
- self.wait(5)
-
-
- def checkFile(self):
- if self.checkDownload({"error": "No address associated with hostname"}):
- self.retry(24, 3 * 60, _("Bad file downloaded"))
-
- return super(SimplydebridCom, self).checkFile()
-
-
-getInfo = create_getInfo(SimplydebridCom)
diff --git a/module/plugins/hoster/SmoozedCom.py b/module/plugins/hoster/SmoozedCom.py
deleted file mode 100644
index bd653ff59..000000000
--- a/module/plugins/hoster/SmoozedCom.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.common.json_layer import json_loads
-from module.plugins.internal.MultiHoster import MultiHoster
-
-
-class SmoozedCom(MultiHoster):
- __name__ = "SmoozedCom"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'^unmatchable$' #: Since we want to allow the user to specify the list of hoster to use we let MultiHoster.coreReady
-
- __description__ = """Smoozed.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("", "")]
-
-
- def handlePremium(self, pyfile):
- # In some cases hostsers do not supply us with a filename at download, so we
- # are going to set a fall back filename (e.g. for freakshare or xfileshare)
- pyfile.name = pyfile.name.split('/').pop() # Remove everthing before last slash
-
- # Correction for automatic assigned filename: Removing html at end if needed
- suffix_to_remove = ["html", "htm", "php", "php3", "asp", "shtm", "shtml", "cfml", "cfm"]
- temp = pyfile.name.split('.')
-
- if temp.pop() in suffix_to_remove:
- pyfile.name = ".".join(temp)
-
- # Check the link
- get_data = {'session_key': self.account.getAccountInfo(self.user)['session'],
- 'url' : pyfile.url}
-
- data = json_loads(self.load("http://www2.smoozed.com/api/check", get=get_data))
-
- if data["state"] != "ok":
- self.fail(data["message"])
-
- if data["data"].get("state", "ok") != "ok":
- if data["data"] == "Offline":
- self.offline()
- else:
- self.fail(data["data"]["message"])
-
- pyfile.name = data["data"]["name"]
- pyfile.size = int(data["data"]["size"])
-
- # Start the download
- header = self.load("http://www2.smoozed.com/api/download", get=get_data, just_header=True)
-
- if not "location" in header:
- self.fail(_("Unable to initialize download"))
- else:
- self.link = header["location"][-1] if isinstance(header["location"], list) else header["location"]
-
-
- def checkFile(self):
- if self.checkDownload({'error': '{"state":"error"}',
- 'retry': '{"state":"retry"}'}):
- self.fail(_("Error response received"))
-
- return super(SmoozedCom, self).checkFile()
diff --git a/module/plugins/hoster/SockshareCom.py b/module/plugins/hoster/SockshareCom.py
deleted file mode 100644
index e85a74e49..000000000
--- a/module/plugins/hoster/SockshareCom.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class SockshareCom(DeadHoster):
- __name__ = "SockshareCom"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'http://(?:www\.)?sockshare\.com/(mobile/)?(file|embed)/(?P<ID>\w+)'
-
- __description__ = """Sockshare.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("jeix", "jeix@hasnomail.de"),
- ("stickell", "l.stickell@yahoo.it"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
-getInfo = create_getInfo(SockshareCom)
diff --git a/module/plugins/hoster/SpeedLoadOrg.py b/module/plugins/hoster/SpeedLoadOrg.py
deleted file mode 100644
index 588eb26a3..000000000
--- a/module/plugins/hoster/SpeedLoadOrg.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class SpeedLoadOrg(DeadHoster):
- __name__ = "SpeedLoadOrg"
- __type__ = "hoster"
- __version__ = "1.02"
-
- __pattern__ = r'http://(?:www\.)?speedload\.org/(?P<ID>\w+)'
-
- __description__ = """Speedload.org hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
-getInfo = create_getInfo(SpeedLoadOrg)
diff --git a/module/plugins/hoster/SpeedfileCz.py b/module/plugins/hoster/SpeedfileCz.py
deleted file mode 100644
index 3f17bbbe6..000000000
--- a/module/plugins/hoster/SpeedfileCz.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class SpeedfileCz(DeadHoster):
- __name__ = "SpeedFileCz"
- __type__ = "hoster"
- __version__ = "0.32"
-
- __pattern__ = r'http://(?:www\.)?speedfile\.cz/.+'
-
- __description__ = """Speedfile.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(SpeedfileCz)
diff --git a/module/plugins/hoster/SpeedyshareCom.py b/module/plugins/hoster/SpeedyshareCom.py
deleted file mode 100644
index 078cbf6c8..000000000
--- a/module/plugins/hoster/SpeedyshareCom.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# http://speedy.sh/ep2qY/Zapp-Brannigan.jpg
-
-import re
-
-from urlparse import urljoin
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class SpeedyshareCom(SimpleHoster):
- __name__ = "SpeedyshareCom"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'https?://(?:www\.)?(speedyshare\.com|speedy\.sh)/\w+'
-
- __description__ = """Speedyshare.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
-
-
- NAME_PATTERN = r'class=downloadfilename>(?P<N>.*)</span></td>'
- SIZE_PATTERN = r'class=sizetagtext>(?P<S>.*) (?P<U>[kKmM]?[iI]?[bB]?)</div>'
-
- OFFLINE_PATTERN = r'class=downloadfilenamenotfound>.*</span>'
-
- LINK_FREE_PATTERN = r'<a href=\'(.*)\'><img src=/gf/slowdownload\.png alt=\'Slow Download\' border=0'
-
-
- def setup(self):
- self.multiDL = False
- self.chunkLimit = 1
-
-
- def handleFree(self, pyfile):
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.link = m.group(1)
-
-
-getInfo = create_getInfo(SpeedyshareCom)
diff --git a/module/plugins/hoster/StorageTo.py b/module/plugins/hoster/StorageTo.py
deleted file mode 100644
index 4b18c69da..000000000
--- a/module/plugins/hoster/StorageTo.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class StorageTo(DeadHoster):
- __name__ = "StorageTo"
- __type__ = "hoster"
- __version__ = "0.01"
-
- __pattern__ = r'http://(?:www\.)?storage\.to/get/.+'
-
- __description__ = """Storage.to hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("mkaay", "mkaay@mkaay.de")]
-
-
-getInfo = create_getInfo(StorageTo)
diff --git a/module/plugins/hoster/StreamcloudEu.py b/module/plugins/hoster/StreamcloudEu.py
deleted file mode 100644
index c47c2c6a1..000000000
--- a/module/plugins/hoster/StreamcloudEu.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class StreamcloudEu(XFSHoster):
- __name__ = "StreamcloudEu"
- __type__ = "hoster"
- __version__ = "0.10"
-
- __pattern__ = r'http://(?:www\.)?streamcloud\.eu/\w{12}'
-
- __description__ = """Streamcloud.eu hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("seoester", "seoester@googlemail.com")]
-
-
- WAIT_PATTERN = r'var count = (\d+)'
-
- LINK_PATTERN = r'file: "(http://(stor|cdn)\d+\.streamcloud\.eu:?\d*/.*/video\.(mp4|flv))",'
-
-
- def setup(self):
- self.multiDL = True
- self.chunkLimit = 1
- self.resumeDownload = self.premium
-
-
-getInfo = create_getInfo(StreamcloudEu)
diff --git a/module/plugins/hoster/TurbobitNet.py b/module/plugins/hoster/TurbobitNet.py
deleted file mode 100644
index 811136405..000000000
--- a/module/plugins/hoster/TurbobitNet.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import random
-import re
-import time
-
-from Crypto.Cipher import ARC4
-from binascii import hexlify, unhexlify
-from pycurl import HTTPHEADER
-from urllib import quote
-
-from pyload.network.RequestFactory import getURL
-from pyload.plugin.internal.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp
-
-
-class TurbobitNet(SimpleHoster):
- __name__ = "TurbobitNet"
- __type__ = "hoster"
- __version__ = "0.19"
-
- __pattern__ = r'http://(?:www\.)?turbobit\.net/(?:download/free/)?(?P<ID>\w+)'
-
- __description__ = """Turbobit.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
- ("prOq", "")]
-
-
- URL_REPLACEMENTS = [(__pattern__ + ".*", "http://turbobit.net/\g<ID>.html")]
-
- COOKIES = [("turbobit.net", "user_lang", "en")]
-
- NAME_PATTERN = r'id="file-title">(?P<N>.+?)<'
- SIZE_PATTERN = r'class="file-size">(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
- OFFLINE_PATTERN = r'<h2>File Not Found</h2>|html\(\'File (?:was )?not found'
-
- LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'(/download/redirect/[^"\']+)'
-
- LIMIT_WAIT_PATTERN = r'<div id=\'timeout\'>(\d+)<'
- CAPTCHA_PATTERN = r'<img alt="Captcha" src="(.+?)"'
-
-
- def handleFree(self, pyfile):
- self.html = self.load("http://turbobit.net/download/free/%s" % self.info['pattern']['ID'],
- decode=True)
-
- rtUpdate = self.getRtUpdate()
-
- self.solveCaptcha()
-
- self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
-
- self.html = self.load(self.getDownloadUrl(rtUpdate))
-
- self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With:"])
-
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m:
- self.link = m.group(1)
-
-
- def solveCaptcha(self):
- for _i in xrange(5):
- m = re.search(self.LIMIT_WAIT_PATTERN, self.html)
- if m:
- wait_time = int(m.group(1))
- self.wait(wait_time, wait_time > 60)
- self.retry()
-
- action, inputs = self.parseHtmlForm("action='#'")
- if not inputs:
- self.error(_("Captcha form not found"))
- self.logDebug(inputs)
-
- if inputs['captcha_type'] == 'recaptcha':
- recaptcha = ReCaptcha(self)
- inputs['recaptcha_response_field'], inputs['recaptcha_challenge_field'] = recaptcha.challenge()
- else:
- m = re.search(self.CAPTCHA_PATTERN, self.html)
- if m is None:
- self.error(_("captcha"))
- captcha_url = m.group(1)
- inputs['captcha_response'] = self.decryptCaptcha(captcha_url)
-
- self.logDebug(inputs)
- self.html = self.load(self.url, post=inputs)
-
- if '<div class="captcha-error">Incorrect, try again!<' in self.html:
- self.invalidCaptcha()
- else:
- self.correctCaptcha()
- break
- else:
- self.fail(_("Invalid captcha"))
-
-
- def getRtUpdate(self):
- rtUpdate = self.getStorage("rtUpdate")
- if not rtUpdate:
- if self.getStorage("version") != self.__version__ \
- or int(self.getStorage("timestamp", 0)) + 86400000 < timestamp():
- # that's right, we are even using jdownloader updates
- rtUpdate = getURL("http://update0.jdownloader.org/pluginstuff/tbupdate.js")
- rtUpdate = self.decrypt(rtUpdate.splitlines()[1])
- # but we still need to fix the syntax to work with other engines than rhino
- rtUpdate = re.sub(r'for each\(var (\w+) in(\[[^\]]+\])\)\{',
- r'zza=\2;for(var zzi=0;zzi<zza.length;zzi++){\1=zza[zzi];', rtUpdate)
- rtUpdate = re.sub(r"for\((\w+)=", r"for(var \1=", rtUpdate)
-
- self.setStorage("rtUpdate", rtUpdate)
- self.setStorage("timestamp", timestamp())
- self.setStorage("version", self.__version__)
- else:
- self.logError(_("Unable to download, wait for update..."))
- self.tempOffline()
-
- return rtUpdate
-
-
- def getDownloadUrl(self, rtUpdate):
- self.req.http.lastURL = self.url
-
- m = re.search("(/\w+/timeout\.js\?\w+=)([^\"\'<>]+)", self.html)
- if m:
- url = "http://turbobit.net%s%s" % m.groups()
- else:
- url = "http://turbobit.net/files/timeout.js?ver=%s" % "".join(random.choice('0123456789ABCDEF') for _i in xrange(32))
-
- fun = self.load(url)
-
- self.setWait(65, False)
-
- for b in [1, 3]:
- self.jscode = "var id = \'%s\';var b = %d;var inn = \'%s\';%sout" % (
- self.info['pattern']['ID'], b, quote(fun), rtUpdate)
-
- try:
- out = self.js.eval(self.jscode)
- self.logDebug("URL", self.js.engine, out)
- if out.startswith('/download/'):
- return "http://turbobit.net%s" % out.strip()
-
- except Exception, e:
- self.logError(e)
- else:
- if self.retries >= 2:
- # retry with updated js
- self.delStorage("rtUpdate")
- else:
- self.retry()
-
- self.wait()
-
-
- def decrypt(self, data):
- cipher = ARC4.new(hexlify('E\x15\xa1\x9e\xa3M\xa0\xc6\xa0\x84\xb6H\x83\xa8o\xa0'))
- return unhexlify(cipher.encrypt(unhexlify(data)))
-
-
- def getLocalTimeString(self):
- lt = time.localtime()
- tz = time.altzone if lt.tm_isdst else time.timezone
- return "%s GMT%+03d%02d" % (time.strftime("%a %b %d %Y %H:%M:%S", lt), -tz // 3600, tz % 3600)
-
-
-getInfo = create_getInfo(TurbobitNet)
diff --git a/module/plugins/hoster/TurbouploadCom.py b/module/plugins/hoster/TurbouploadCom.py
deleted file mode 100644
index f821438dd..000000000
--- a/module/plugins/hoster/TurbouploadCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class TurbouploadCom(DeadHoster):
- __name__ = "TurbouploadCom"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?turboupload\.com/(\w+)'
-
- __description__ = """Turboupload.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(TurbouploadCom)
diff --git a/module/plugins/hoster/TusfilesNet.py b/module/plugins/hoster/TusfilesNet.py
deleted file mode 100644
index 9fdb6eae1..000000000
--- a/module/plugins/hoster/TusfilesNet.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.network.HTTPRequest import BadHeader
-from module.plugins.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class TusfilesNet(XFSHoster):
- __name__ = "TusfilesNet"
- __type__ = "hoster"
- __version__ = "0.09"
-
- __pattern__ = r'https?://(?:www\.)?tusfiles\.net/\w{12}'
-
- __description__ = """Tusfiles.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com"),
- ("guidobelix", "guidobelix@hotmail.it")]
-
-
- INFO_PATTERN = r'\](?P<N>.+) - (?P<S>[\d.,]+) (?P<U>[\w^_]+)\['
- OFFLINE_PATTERN = r'>File Not Found|<Title>TusFiles - Fast Sharing Files!|The file you are trying to download is no longer available'
-
-
- def setup(self):
- self.chunkLimit = -1
- self.multiDL = True
- self.resumeDownload = True
-
-
- def downloadLink(self, link):
- try:
- return super(TusfilesNet, self).downloadLink(link)
-
- except BadHeader, e:
- if e.code is 503:
- self.multiDL = False
- raise Retry("503")
-
-
-getInfo = create_getInfo(TusfilesNet)
diff --git a/module/plugins/hoster/TwoSharedCom.py b/module/plugins/hoster/TwoSharedCom.py
deleted file mode 100644
index 53911762d..000000000
--- a/module/plugins/hoster/TwoSharedCom.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class TwoSharedCom(SimpleHoster):
- __name__ = "TwoSharedCom"
- __type__ = "hoster"
- __version__ = "0.13"
-
- __pattern__ = r'http://(?:www\.)?2shared\.com/(account/)?(download|get|file|document|photo|video|audio)/.+'
-
- __description__ = """2Shared.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<h1>(?P<N>.*)</h1>'
- SIZE_PATTERN = r'<span class="dtitle">File size:</span>\s*(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
- OFFLINE_PATTERN = r'The file link that you requested is not valid\.|This file was deleted\.'
-
- LINK_FREE_PATTERN = r'window.location =\'(.+?)\';'
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = True
-
-
-getInfo = create_getInfo(TwoSharedCom)
diff --git a/module/plugins/hoster/UlozTo.py b/module/plugins/hoster/UlozTo.py
deleted file mode 100644
index 104209a66..000000000
--- a/module/plugins/hoster/UlozTo.py
+++ /dev/null
@@ -1,158 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-import time
-
-from pyload.utils import json_loads
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-def convertDecimalPrefix(m):
- # decimal prefixes used in filesize and traffic
- return ("%%.%df" % {'k': 3, 'M': 6, 'G': 9}[m.group(2)] % float(m.group(1))).replace('.', '')
-
-
-class UlozTo(SimpleHoster):
- __name__ = "UlozTo"
- __type__ = "hoster"
- __version__ = "1.04"
-
- __pattern__ = r'http://(?:www\.)?(uloz\.to|ulozto\.(cz|sk|net)|bagruj\.cz|zachowajto\.pl)/(?:live/)?(?P<ID>\w+/[^/?]*)'
-
- __description__ = """Uloz.to hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- INFO_PATTERN = r'<p>File <strong>(?P<N>[^<]+)</strong> is password protected</p>'
- NAME_PATTERN = r'<title>(?P<N>[^<]+) \| Uloz\.to</title>'
- SIZE_PATTERN = r'<span id="fileSize">.*?(?P<S>[\d.,]+\s[kMG]?B)</span>'
- OFFLINE_PATTERN = r'<title>404 - Page not found</title>|<h1 class="h1">File (has been deleted|was banned)</h1>'
-
- URL_REPLACEMENTS = [(r"(?<=http://)([^/]+)", "www.ulozto.net")]
- SIZE_REPLACEMENTS = [('([\d.]+)\s([kMG])B', convertDecimalPrefix)]
-
- ADULT_PATTERN = r'<form action="([^\"]*)" method="post" id="frm-askAgeForm">'
- PASSWD_PATTERN = r'<div class="passwordProtectedFile">'
- VIPLINK_PATTERN = r'<a href="[^"]*\?disclaimer=1" class="linkVip">'
- TOKEN_PATTERN = r'<input type="hidden" name="_token_" .*?value="(.+?)"'
-
-
- def setup(self):
- self.chunkLimit = 16 if self.premium else 1
- self.multiDL = self.premium
- self.resumeDownload = True
-
-
- def process(self, pyfile):
- pyfile.url = re.sub(r"(?<=http://)([^/]+)", "www.ulozto.net", pyfile.url)
- self.html = self.load(pyfile.url, decode=True, cookies=True)
-
- if re.search(self.ADULT_PATTERN, self.html):
- self.logInfo(_("Adult content confirmation needed"))
-
- m = re.search(self.TOKEN_PATTERN, self.html)
- if m is None:
- self.error(_("TOKEN_PATTERN not found"))
- token = m.group(1)
-
- self.html = self.load(pyfile.url, get={'do': "askAgeForm-submit"},
- post={"agree": "Confirm", "_token_": token}, cookies=True)
-
- if self.PASSWD_PATTERN in self.html:
- password = self.getPassword()
-
- if password:
- self.logInfo(_("Password protected link, trying ") + password)
- self.html = self.load(pyfile.url, get={'do': "passwordProtectedForm-submit"},
- post={"password": password, "password_send": 'Send'}, cookies=True)
-
- if self.PASSWD_PATTERN in self.html:
- self.fail(_("Incorrect password"))
- else:
- self.fail(_("No password found"))
-
- if re.search(self.VIPLINK_PATTERN, self.html):
- self.html = self.load(pyfile.url, get={'disclaimer': "1"})
-
- self.getFileInfo()
-
- if self.premium and self.checkTrafficLeft():
- self.handlePremium(pyfile)
- else:
- self.handleFree(pyfile)
-
- self.doCheckDownload()
-
-
- def handleFree(self, pyfile):
- action, inputs = self.parseHtmlForm('id="frm-downloadDialog-freeDownloadForm"')
- if not action or not inputs:
- self.error(_("Free download form not found"))
-
- self.logDebug("inputs.keys = " + str(inputs.keys()))
- # get and decrypt captcha
- if all(key in inputs for key in ("captcha_value", "captcha_id", "captcha_key")):
- # Old version - last seen 9.12.2013
- self.logDebug('Using "old" version')
-
- captcha_value = self.decryptCaptcha("http://img.uloz.to/captcha/%s.png" % inputs['captcha_id'])
- self.logDebug("CAPTCHA ID: " + inputs['captcha_id'] + ", CAPTCHA VALUE: " + captcha_value)
-
- inputs.update({'captcha_id': inputs['captcha_id'], 'captcha_key': inputs['captcha_key'], 'captcha_value': captcha_value})
-
- elif all(key in inputs for key in ("captcha_value", "timestamp", "salt", "hash")):
- # New version - better to get new parameters (like captcha reload) because of image url - since 6.12.2013
- self.logDebug('Using "new" version')
-
- xapca = self.load("http://www.ulozto.net/reloadXapca.php", get={'rnd': str(int(time.time()))})
- self.logDebug("xapca = " + str(xapca))
-
- data = json_loads(xapca)
- captcha_value = self.decryptCaptcha(str(data['image']))
- self.logDebug("CAPTCHA HASH: " + data['hash'], "CAPTCHA SALT: " + str(data['salt']), "CAPTCHA VALUE: " + captcha_value)
-
- inputs.update({'timestamp': data['timestamp'], 'salt': data['salt'], 'hash': data['hash'], 'captcha_value': captcha_value})
- else:
- self.error(_("CAPTCHA form changed"))
-
- self.multiDL = True
- self.download("http://www.ulozto.net" + action, post=inputs, cookies=True, disposition=True)
-
-
- def handlePremium(self, pyfile):
- self.download(pyfile.url, get={'do': "directDownload"}, disposition=True)
-
-
- def doCheckDownload(self):
- check = self.checkDownload({
- "wrong_captcha": re.compile(r'<ul class="error">\s*<li>Error rewriting the text.</li>'),
- "offline" : re.compile(self.OFFLINE_PATTERN),
- "passwd" : self.PASSWD_PATTERN,
- "server_error" : 'src="http://img.ulozto.cz/error403/vykricnik.jpg"', # paralell dl, server overload etc.
- "not_found" : "<title>UloÅŸ.to</title>"
- })
-
- if check == "wrong_captcha":
- #self.delStorage("captcha_id")
- #self.delStorage("captcha_text")
- self.invalidCaptcha()
- self.retry(reason=_("Wrong captcha code"))
-
- elif check == "offline":
- self.offline()
-
- elif check == "passwd":
- self.fail(_("Wrong password"))
-
- elif check == "server_error":
- self.logError(_("Server error, try downloading later"))
- self.multiDL = False
- self.wait(1 * 60 * 60, True)
- self.retry()
-
- elif check == "not_found":
- self.fail(_("Server error - file not downloadable"))
-
-
-getInfo = create_getInfo(UlozTo)
diff --git a/module/plugins/hoster/UloziskoSk.py b/module/plugins/hoster/UloziskoSk.py
deleted file mode 100644
index 862429af5..000000000
--- a/module/plugins/hoster/UloziskoSk.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class UloziskoSk(SimpleHoster):
- __name__ = "UloziskoSk"
- __type__ = "hoster"
- __version__ = "0.25"
-
- __pattern__ = r'http://(?:www\.)?ulozisko\.sk/.+'
-
- __description__ = """Ulozisko.sk hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<div class="down1">(?P<N>[^<]+)</div>'
- SIZE_PATTERN = ur'Veğkosť súboru: <strong>(?P<S>[\d.,]+) (?P<U>[\w^_]+)</strong><br />'
- OFFLINE_PATTERN = ur'<span class = "red">ZadanÜ súbor neexistuje z jedného z nasledujúcich dÎvodov:</span>'
-
- LINK_FREE_PATTERN = r'<form name = "formular" action = "([^"]+)" method = "post">'
- ID_PATTERN = r'<input type = "hidden" name = "id" value = "([^"]+)" />'
- CAPTCHA_PATTERN = r'<img src="(/obrazky/obrazky\.php\?fid=[^"]+)" alt="" />'
- IMG_PATTERN = ur'<strong>PRE ZVÄČŠENIE KLIKNITE NA OBRÁZOK</strong><br /><a href = "([^"]+)">'
-
-
- def process(self, pyfile):
- self.html = self.load(pyfile.url, decode=True)
- self.getFileInfo()
-
- m = re.search(self.IMG_PATTERN, self.html)
- if m:
- url = "http://ulozisko.sk" + m.group(1)
- self.download(url)
- else:
- self.handleFree(pyfile)
-
-
- def handleFree(self, pyfile):
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("LINK_FREE_PATTERN not found"))
- parsed_url = 'http://www.ulozisko.sk' + m.group(1)
-
- m = re.search(self.ID_PATTERN, self.html)
- if m is None:
- self.error(_("ID_PATTERN not found"))
- id = m.group(1)
-
- self.logDebug("URL:" + parsed_url + ' ID:' + id)
-
- m = re.search(self.CAPTCHA_PATTERN, self.html)
- if m is None:
- self.error(_("CAPTCHA_PATTERN not found"))
- captcha_url = 'http://www.ulozisko.sk' + m.group(1)
-
- captcha = self.decryptCaptcha(captcha_url, cookies=True)
-
- self.logDebug("CAPTCHA_URL:" + captcha_url + ' CAPTCHA:' + captcha)
-
- self.download(parsed_url,
- post={"antispam": captcha,
- "id" : id,
- "name" : pyfile.name,
- "but" : "++++STIAHNI+S%DABOR++++"})
-
-
-getInfo = create_getInfo(UloziskoSk)
diff --git a/module/plugins/hoster/UnibytesCom.py b/module/plugins/hoster/UnibytesCom.py
deleted file mode 100644
index dadbe2fec..000000000
--- a/module/plugins/hoster/UnibytesCom.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urlparse import urljoin
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class UnibytesCom(SimpleHoster):
- __name__ = "UnibytesCom"
- __type__ = "hoster"
- __version__ = "0.12"
-
- __pattern__ = r'https?://(?:www\.)?unibytes\.com/[\w .-]{11}B'
-
- __description__ = """UniBytes.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- HOSTER_DOMAIN = "unibytes.com"
-
- INFO_PATTERN = r'<span[^>]*?id="fileName"[^>]*>(?P<N>[^>]+)</span>\s*\((?P<S>\d.*?)\)'
-
- WAIT_PATTERN = r'Wait for <span id="slowRest">(\d+)</span> sec'
- LINK_FREE_PATTERN = r'<a href="([^"]+)">Download</a>'
-
-
- def handleFree(self, pyfile):
- domain = "http://www.%s/" % self.HOSTER_DOMAIN
- action, post_data = self.parseHtmlForm('id="startForm"')
-
-
- for _i in xrange(8):
- self.logDebug(action, post_data)
- self.html = self.load(urljoin(domain, action), post=post_data, follow_location=False)
-
- m = re.search(r'location:\s*(\S+)', self.req.http.header, re.I)
- if m:
- url = m.group(1)
- break
-
- if '>Somebody else is already downloading using your IP-address<' in self.html:
- self.wait(10 * 60, True)
- self.retry()
-
- if post_data['step'] == 'last':
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m:
- url = m.group(1)
- self.correctCaptcha()
- break
- else:
- self.invalidCaptcha()
-
- last_step = post_data['step']
- action, post_data = self.parseHtmlForm('id="stepForm"')
-
- if last_step == 'timer':
- m = re.search(self.WAIT_PATTERN, self.html)
- self.wait(m.group(1) if m else 60, False)
-
- elif last_step in ("captcha", "last"):
- post_data['captcha'] = self.decryptCaptcha(urljoin(domain, "/captcha.jpg"))
-
- else:
- self.fail(_("No valid captcha code entered"))
-
- self.download(url)
-
-
-getInfo = create_getInfo(UnibytesCom)
diff --git a/module/plugins/hoster/UnrestrictLi.py b/module/plugins/hoster/UnrestrictLi.py
deleted file mode 100644
index 99fe01257..000000000
--- a/module/plugins/hoster/UnrestrictLi.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.common.json_layer import json_loads
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-from module.plugins.internal.SimpleHoster import secondsToMidnight
-
-
-class UnrestrictLi(MultiHoster):
- __name__ = "UnrestrictLi"
- __type__ = "hoster"
- __version__ = "0.21"
-
- __pattern__ = r'https?://(?:www\.)?(unrestrict|unr)\.li/dl/[\w^_]+'
-
- __description__ = """Unrestrict.li multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- LOGIN_ACCOUNT = False
-
-
- def setup(self):
- self.chunkLimit = 16
- self.resumeDownload = True
-
-
- def handleFree(self, pyfile):
- for _i in xrange(5):
- self.html = self.load('https://unrestrict.li/unrestrict.php',
- post={'link': pyfile.url, 'domain': 'long'})
-
- self.logDebug("JSON data: " + self.html)
-
- if self.html:
- break
- else:
- self.logInfo(_("Unable to get API data, waiting 1 minute and retry"))
- self.retry(5, 60, "Unable to get API data")
-
- if 'Expired session' in self.html \
- or ("You are not allowed to download from this host" in self.html and self.premium):
- self.account.relogin(self.user)
- self.retry()
-
- elif "File offline" in self.html:
- self.offline()
-
- elif "You are not allowed to download from this host" in self.html:
- self.fail(_("You are not allowed to download from this host"))
-
- elif "You have reached your daily limit for this host" in self.html:
- self.logWarning(_("Reached daily limit for this host"))
- self.retry(5, secondsToMidnight(gmt=2), "Daily limit for this host reached")
-
- elif "ERROR_HOSTER_TEMPORARILY_UNAVAILABLE" in self.html:
- self.logInfo(_("Hoster temporarily unavailable, waiting 1 minute and retry"))
- self.retry(5, 60, "Hoster is temporarily unavailable")
-
- self.html = json_loads(self.html)
- self.link = self.html.keys()[0]
- self.api_data = self.html[self.link]
-
- if hasattr(self, 'api_data'):
- self.setNameSize()
-
-
- def checkFile(self):
- super(UnrestrictLi, self).checkFile()
-
- if self.getConfig("history"):
- self.load("https://unrestrict.li/history/", get={'delete': "all"})
- self.logInfo(_("Download history deleted"))
-
-
- def setNameSize(self):
- if 'name' in self.api_data:
- self.pyfile.name = self.api_data['name']
- if 'size' in self.api_data:
- self.pyfile.size = self.api_data['size']
-
-
-getInfo = create_getInfo(UnrestrictLi)
diff --git a/module/plugins/hoster/UpleaCom.py b/module/plugins/hoster/UpleaCom.py
deleted file mode 100644
index d14f2fdc5..000000000
--- a/module/plugins/hoster/UpleaCom.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urlparse import urljoin
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class UpleaCom(XFSHoster):
- __name__ = "UpleaCom"
- __type__ = "hoster"
- __version__ = "0.06"
-
- __pattern__ = r'https?://(?:www\.)?uplea\.com/dl/\w{15}'
-
- __description__ = """Uplea.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Redleon", "")]
-
-
- NAME_PATTERN = r'class="agmd size18">(?P<N>.+?)<'
- SIZE_PATTERN = r'size14">(?P<S>[\d.,]+) (?P<U>[\w^_])</span>'
-
- OFFLINE_PATTERN = r'>You followed an invalid or expired link'
-
- LINK_PATTERN = r'"(http?://\w+\.uplea\.com/anonym/.*?)"'
-
- WAIT_PATTERN = r'timeText:([\d.]+),'
- STEP_PATTERN = r'<a href="(/step/.+)">'
-
-
- def setup(self):
- self.multiDL = False
- self.chunkLimit = 1
- self.resumeDownload = True
-
-
- def handleFree(self, pyfile):
- m = re.search(self.STEP_PATTERN, self.html)
- if m is None:
- self.error(_("STEP_PATTERN not found"))
-
- self.html = self.load(urljoin("http://uplea.com/", m.group(1)))
-
- m = re.search(self.WAIT_PATTERN, self.html)
- if m:
- self.wait(m.group(1), True)
- self.retry()
-
- m = re.search(self.LINK_PATTERN, self.html)
- if m is None:
- self.error(_("LINK_PATTERN not found"))
-
- self.link = m.group(1)
- self.wait(15)
-
-
-getInfo = create_getInfo(UpleaCom)
diff --git a/module/plugins/hoster/UploadStationCom.py b/module/plugins/hoster/UploadStationCom.py
deleted file mode 100644
index daa7a9e81..000000000
--- a/module/plugins/hoster/UploadStationCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class UploadStationCom(DeadHoster):
- __name__ = "UploadStationCom"
- __type__ = "hoster"
- __version__ = "0.52"
-
- __pattern__ = r'http://(?:www\.)?uploadstation\.com/file/(?P<ID>\w+)'
-
- __description__ = """UploadStation.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("fragonib", "fragonib[AT]yahoo[DOT]es"),
- ("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(UploadStationCom)
diff --git a/module/plugins/hoster/UploadableCh.py b/module/plugins/hoster/UploadableCh.py
deleted file mode 100644
index bddd26f57..000000000
--- a/module/plugins/hoster/UploadableCh.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from time import sleep
-
-from pyload.plugin.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class UploadableCh(SimpleHoster):
- __name__ = "UploadableCh"
- __type__ = "hoster"
- __version__ = "0.08"
-
- __pattern__ = r'http://(?:www\.)?uploadable\.ch/file/(?P<ID>\w+)'
-
- __description__ = """Uploadable.ch hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- URL_REPLACEMENTS = [(__pattern__ + ".*", r'http://www.uploadable.ch/file/\g<ID>')]
-
- INFO_PATTERN = r'div id=\"file_name\" title=.*>(?P<N>.+)<span class=\"filename_normal\">\((?P<S>[\d.]+) (?P<U>\w+)\)</span><'
-
- OFFLINE_PATTERN = r'>(File not available|This file is no longer available)'
- TEMP_OFFLINE_PATTERN = r'<div class="icon_err">'
-
- WAIT_PATTERN = r'>Please wait.+?<'
-
- RECAPTCHA_KEY = "6LdlJuwSAAAAAPJbPIoUhyqOJd7-yrah5Nhim5S3"
-
-
- def handleFree(self, pyfile):
- # Click the "free user" button and wait
- a = self.load(pyfile.url, cookies=True, post={'downloadLink': "wait"}, decode=True)
- self.logDebug(a)
-
- self.wait(30)
-
- # Make the recaptcha appear and show it the pyload interface
- b = self.load(pyfile.url, cookies=True, post={'checkDownload': "check"}, decode=True)
- self.logDebug(b) #: Expected output: {"success":"showCaptcha"}
-
- recaptcha = ReCaptcha(self)
-
- response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY)
-
- # Submit the captcha solution
- self.load("http://www.uploadable.ch/checkReCaptcha.php",
- cookies=True,
- post={'recaptcha_challenge_field' : challenge,
- 'recaptcha_response_field' : response,
- 'recaptcha_shortencode_field': self.info['pattern']['ID']},
- decode=True)
-
- self.wait(3)
-
- # Get ready for downloading
- self.load(pyfile.url, cookies=True, post={'downloadLink': "show"}, decode=True)
-
- self.wait(3)
-
- # Download the file
- self.download(pyfile.url, cookies=True, post={'download': "normal"}, disposition=True)
-
-
- def checkFile(self):
- if self.checkDownload({'wait': re.compile("Please wait for")}):
- self.logInfo("Downloadlimit reached, please wait or reconnect")
- self.wait(60 * 60, True)
- self.retry()
-
- return super(UploadableCh, self).checkFile()
-
-
-getInfo = create_getInfo(UploadableCh)
diff --git a/module/plugins/hoster/UploadboxCom.py b/module/plugins/hoster/UploadboxCom.py
deleted file mode 100644
index 6285b56c5..000000000
--- a/module/plugins/hoster/UploadboxCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class UploadboxCom(DeadHoster):
- __name__ = "Uploadbox"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'http://(?:www\.)?uploadbox\.com/files/.+'
-
- __description__ = """UploadBox.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(UploadboxCom)
diff --git a/module/plugins/hoster/UploadedTo.py b/module/plugins/hoster/UploadedTo.py
deleted file mode 100644
index 83a16c251..000000000
--- a/module/plugins/hoster/UploadedTo.py
+++ /dev/null
@@ -1,120 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from time import sleep
-
-from module.network.RequestFactory import getURL
-from module.plugins.internal.CaptchaService import ReCaptcha
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class UploadedTo(SimpleHoster):
- __name__ = "UploadedTo"
- __type__ = "hoster"
- __version__ = "0.84"
-
- __pattern__ = r'https?://(?:www\.)?(uploaded\.(to|net)|ul\.to)(/file/|/?\?id=|.*?&id=|/)(?P<ID>\w+)'
-
- __description__ = """Uploaded.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- API_KEY = "lhF2IeeprweDfu9ccWlxXVVypA5nA3EL"
-
- URL_REPLACEMENTS = [(__pattern__ + ".*", r'http://uploaded.net/file/\g<ID>')]
-
- LINK_PREMIUM_PATTERN = r'<div class="tfree".*\s*<form method="post" action="(.+?)"'
-
- WAIT_PATTERN = r'Current waiting period: <span>(\d+)'
- DL_LIMIT_ERROR = r'You have reached the max. number of possible free downloads for this hour'
-
-
- @classmethod
- def apiInfo(cls, url="", get={}, post={}):
- info = super(UploadedTo, cls).apiInfo(url)
-
- for _i in xrange(5):
- html = getURL("http://uploaded.net/api/filemultiple",
- get={"apikey": cls.API_KEY, 'id_0': re.match(cls.__pattern__, url).group('ID')},
- decode=True)
-
- if html != "can't find request":
- api = html.split(",", 4)
- if api[0] == "online":
- info.update({'name': api[4].strip(), 'size': api[2], 'status': 2})
- else:
- info['status'] = 1
- break
- else:
- sleep(3)
-
- return info
-
-
- def setup(self):
- self.multiDL = self.resumeDownload = self.premium
- self.chunkLimit = 1 # critical problems with more chunks
-
-
- def checkErrors(self):
- if 'var free_enabled = false;' in self.html:
- self.logError(_("Free-download capacities exhausted"))
- self.retry(24, 5 * 60)
-
- elif "limit-size" in self.html:
- self.fail(_("File too big for free download"))
-
- elif "limit-slot" in self.html: # Temporary restriction so just wait a bit
- self.wait(30 * 60, True)
- self.retry()
-
- elif "limit-parallel" in self.html:
- self.fail(_("Cannot download in parallel"))
-
- elif "limit-dl" in self.html or self.DL_LIMIT_ERROR in self.html: # limit-dl
- self.wait(3 * 60 * 60, True)
- self.retry()
-
- elif '"err":"captcha"' in self.html:
- self.invalidCaptcha()
-
- else:
- m = re.search(self.WAIT_PATTERN, self.html)
- if m:
- self.wait(m.group(1))
-
-
- def handleFree(self, pyfile):
- self.load("http://uploaded.net/language/en", just_header=True)
-
- self.html = self.load("http://uploaded.net/js/download.js", decode=True)
-
- recaptcha = ReCaptcha(self)
- response, challenge = recaptcha.challenge()
-
- self.html = self.load("http://uploaded.net/io/ticket/captcha/%s" % self.info['pattern']['ID'],
- post={'recaptcha_challenge_field': challenge,
- 'recaptcha_response_field' : response})
-
- if "type:'download'" in self.html:
- self.correctCaptcha()
- try:
- self.link = re.search("url:'([^']+)", self.html).group(1)
-
- except Exception:
- pass
-
- self.checkErrors()
-
-
- def checkFile(self):
- if self.checkDownload({'limit-dl': self.DL_LIMIT_ERROR}):
- self.wait(3 * 60 * 60, True)
- self.retry()
-
- return super(UploadedTo, self).checkFile()
-
-
-getInfo = create_getInfo(UploadedTo)
diff --git a/module/plugins/hoster/UploadhereCom.py b/module/plugins/hoster/UploadhereCom.py
deleted file mode 100644
index 64b235eda..000000000
--- a/module/plugins/hoster/UploadhereCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class UploadhereCom(DeadHoster):
- __name__ = "UploadhereCom"
- __type__ = "hoster"
- __version__ = "0.12"
-
- __pattern__ = r'http://(?:www\.)?uploadhere\.com/\w{10}'
-
- __description__ = """Uploadhere.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(UploadhereCom)
diff --git a/module/plugins/hoster/UploadheroCom.py b/module/plugins/hoster/UploadheroCom.py
deleted file mode 100644
index a0a9cffcb..000000000
--- a/module/plugins/hoster/UploadheroCom.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# http://uploadhero.co/dl/wQBRAVSM
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class UploadheroCom(SimpleHoster):
- __name__ = "UploadheroCom"
- __type__ = "hoster"
- __version__ = "0.17"
-
- __pattern__ = r'http://(?:www\.)?uploadhero\.com?/dl/\w+'
-
- __description__ = """UploadHero.co plugin"""
- __license__ = "GPLv3"
- __authors__ = [("mcmyst", "mcmyst@hotmail.fr"),
- ("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'<div class="nom_de_fichier">(?P<N>.*?)</div>'
- SIZE_PATTERN = r'Taille du fichier : </span><strong>(?P<S>.*?)</strong>'
- OFFLINE_PATTERN = r'<p class="titre_dl_2">|<div class="raison"><strong>Le lien du fichier ci-dessus n\'existe plus.'
-
- COOKIES = [("uploadhero.co", "lang", "en")]
-
- IP_BLOCKED_PATTERN = r'href="(/lightbox_block_download\.php\?min=.*?)"'
- IP_WAIT_PATTERN = r'<span id="minutes">(\d+)</span>.*\s*<span id="seconds">(\d+)</span>'
-
- CAPTCHA_PATTERN = r'"(/captchadl\.php\?\w+)"'
-
- LINK_FREE_PATTERN = r'var magicomfg = \'<a href="(http://[^<>"]*?)"|"(http://storage\d+\.uploadhero\.co/\?d=\w+/[^<>"/]+)"'
- LINK_PREMIUM_PATTERN = r'<a href="([^"]+)" id="downloadnow"'
-
-
- def handleFree(self, pyfile):
- self.checkErrors()
-
- m = re.search(self.CAPTCHA_PATTERN, self.html)
- if m is None:
- self.error(_("CAPTCHA_PATTERN not found"))
- captcha_url = "http://uploadhero.co" + m.group(1)
-
- for _i in xrange(5):
- captcha = self.decryptCaptcha(captcha_url)
- self.html = self.load(pyfile.url, get={"code": captcha})
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m:
- self.correctCaptcha()
- download_url = m.group(1) or m.group(2)
- break
- else:
- self.invalidCaptcha()
- else:
- self.fail(_("No valid captcha code entered"))
-
- self.download(download_url)
-
-
- def checkErrors(self):
- m = re.search(self.IP_BLOCKED_PATTERN, self.html)
- if m:
- self.html = self.load("http://uploadhero.co%s" % m.group(1))
-
- m = re.search(self.IP_WAIT_PATTERN, self.html)
- wait_time = (int(m.group(1)) * 60 + int(m.group(2))) if m else 5 * 60
- self.wait(wait_time, True)
- self.retry()
-
- self.info.pop('error', None)
-
-
-getInfo = create_getInfo(UploadheroCom)
diff --git a/module/plugins/hoster/UploadingCom.py b/module/plugins/hoster/UploadingCom.py
deleted file mode 100644
index a315d3466..000000000
--- a/module/plugins/hoster/UploadingCom.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pycurl import HTTPHEADER
-
-from pyload.utils import json_loads
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo, timestamp
-
-
-class UploadingCom(SimpleHoster):
- __name__ = "UploadingCom"
- __type__ = "hoster"
- __version__ = "0.40"
-
- __pattern__ = r'http://(?:www\.)?uploading\.com/files/(?:get/)?(?P<ID>\w+)'
-
- __description__ = """Uploading.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("jeix", "jeix@hasnomail.de"),
- ("mkaay", "mkaay@mkaay.de"),
- ("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'id="file_title">(?P<N>.+)</'
- SIZE_PATTERN = r'size tip_container">(?P<S>[\d.,]+) (?P<U>[\w^_]+)<'
- OFFLINE_PATTERN = r'(Page|file) not found'
-
- COOKIES = [("uploading.com", "lang", "1"),
- (".uploading.com", "language", "1"),
- (".uploading.com", "setlang", "en"),
- (".uploading.com", "_lang", "en")]
-
-
- def process(self, pyfile):
- if not "/get/" in pyfile.url:
- pyfile.url = pyfile.url.replace("/files", "/files/get")
-
- self.html = self.load(pyfile.url, decode=True)
- self.getFileInfo()
-
- if self.premium:
- self.handlePremium(pyfile)
- else:
- self.handleFree(pyfile)
-
-
- def handlePremium(self, pyfile):
- postData = {'action': 'get_link',
- 'code' : self.info['pattern']['ID'],
- 'pass' : 'undefined'}
-
- self.html = self.load('http://uploading.com/files/get/?JsHttpRequest=%d-xml' % timestamp(), post=postData)
- url = re.search(r'"link"\s*:\s*"(.*?)"', self.html)
- if url:
- url = url.group(1).replace("\\/", "/")
- self.download(url)
-
- raise Exception("Plugin defect")
-
-
- def handleFree(self, pyfile):
- m = re.search('<h2>((Daily )?Download Limit)</h2>', self.html)
- if m:
- pyfile.error = m.group(1)
- self.logWarning(pyfile.error)
- self.retry(6, (6 * 60 if m.group(2) else 15) * 60, pyfile.error)
-
- ajax_url = "http://uploading.com/files/get/?ajax"
- self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
- self.req.http.lastURL = pyfile.url
-
- res = json_loads(self.load(ajax_url, post={'action': 'second_page', 'code': self.info['pattern']['ID']}))
-
- if 'answer' in res and 'wait_time' in res['answer']:
- wait_time = int(res['answer']['wait_time'])
- self.logInfo(_("Waiting %d seconds") % wait_time)
- self.wait(wait_time)
- else:
- self.error(_("No AJAX/WAIT"))
-
- res = json_loads(self.load(ajax_url, post={'action': 'get_link', 'code': self.info['pattern']['ID'], 'pass': 'false'}))
-
- if 'answer' in res and 'link' in res['answer']:
- url = res['answer']['link']
- else:
- self.error(_("No AJAX/URL"))
-
- self.html = self.load(url)
- m = re.search(r'<form id="file_form" action="(.*?)"', self.html)
- if m:
- url = m.group(1)
- else:
- self.error(_("No URL"))
-
- self.download(url)
-
-
-getInfo = create_getInfo(UploadingCom)
diff --git a/module/plugins/hoster/UploadkingCom.py b/module/plugins/hoster/UploadkingCom.py
deleted file mode 100644
index a490d0d48..000000000
--- a/module/plugins/hoster/UploadkingCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class UploadkingCom(DeadHoster):
- __name__ = "UploadkingCom"
- __type__ = "hoster"
- __version__ = "0.14"
-
- __pattern__ = r'http://(?:www\.)?uploadking\.com/\w{10}'
-
- __description__ = """UploadKing.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
-getInfo = create_getInfo(UploadkingCom)
diff --git a/module/plugins/hoster/UpstoreNet.py b/module/plugins/hoster/UpstoreNet.py
deleted file mode 100644
index b1ceb7df1..000000000
--- a/module/plugins/hoster/UpstoreNet.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.captcha import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class UpstoreNet(SimpleHoster):
- __name__ = "UpstoreNet"
- __type__ = "hoster"
- __version__ = "0.05"
-
- __pattern__ = r'https?://(?:www\.)?upstore\.net/'
-
- __description__ = """Upstore.Net File Download Hoster"""
- __license__ = "GPLv3"
- __authors__ = [("igel", "igelkun@myopera.com")]
-
-
- INFO_PATTERN = r'<div class="comment">.*?</div>\s*\n<h2 style="margin:0">(?P<N>.*?)</h2>\s*\n<div class="comment">\s*\n\s*(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
- OFFLINE_PATTERN = r'<span class="error">File not found</span>'
-
- WAIT_PATTERN = r'var sec = (\d+)'
- CHASH_PATTERN = r'<input type="hidden" name="hash" value="([^"]*)">'
- LINK_FREE_PATTERN = r'<a href="(https?://.*?)" target="_blank"><b>'
-
-
- def handleFree(self, pyfile):
- # STAGE 1: get link to continue
- m = re.search(self.CHASH_PATTERN, self.html)
- if m is None:
- self.error(_("CHASH_PATTERN not found"))
- chash = m.group(1)
- self.logDebug("Read hash " + chash)
- # continue to stage2
- post_data = {'hash': chash, 'free': 'Slow download'}
- self.html = self.load(pyfile.url, post=post_data, decode=True)
-
- # STAGE 2: solv captcha and wait
- # first get the infos we need: recaptcha key and wait time
- recaptcha = ReCaptcha(self)
-
- # try the captcha 5 times
- for i in xrange(5):
- m = re.search(self.WAIT_PATTERN, self.html)
- if m is None:
- self.error(_("Wait pattern not found"))
- wait_time = int(m.group(1))
-
- # then, do the waiting
- self.wait(wait_time)
-
- # then, handle the captcha
- response, challenge = recaptcha.challenge()
- post_data.update({'recaptcha_challenge_field': challenge,
- 'recaptcha_response_field' : response})
-
- self.html = self.load(pyfile.url, post=post_data, decode=True)
-
- # STAGE 3: get direct link
- m = re.search(self.LINK_FREE_PATTERN, self.html, re.S)
- if m:
- break
-
- if m is None:
- self.error(_("Download link not found"))
-
- self.link = m.group(1)
-
-
-getInfo = create_getInfo(UpstoreNet)
diff --git a/module/plugins/hoster/UptoboxCom.py b/module/plugins/hoster/UptoboxCom.py
deleted file mode 100644
index 3d3505f90..000000000
--- a/module/plugins/hoster/UptoboxCom.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class UptoboxCom(XFSHoster):
- __name__ = "UptoboxCom"
- __type__ = "hoster"
- __version__ = "0.17"
-
- __pattern__ = r'https?://(?:www\.)?(uptobox|uptostream)\.com/\w{12}'
-
- __description__ = """Uptobox.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- INFO_PATTERN = r'"para_title">(?P<N>.+) \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)'
- OFFLINE_PATTERN = r'>(File not found|Access Denied|404 Not Found)'
-
- LINK_PATTERN = r'"(https?://\w+\.uptobox\.com/d/.*?)"'
-
- ERROR_PATTERN = r'>(You have to wait.+till next download.)<' #@TODO: Check XFSHoster ERROR_PATTERN
-
-
- def setup(self):
- self.multiDL = True
- self.chunkLimit = 1
- self.resumeDownload = True
-
-
-getInfo = create_getInfo(UptoboxCom)
diff --git a/module/plugins/hoster/VeohCom.py b/module/plugins/hoster/VeohCom.py
deleted file mode 100644
index cb3e896d6..000000000
--- a/module/plugins/hoster/VeohCom.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class VeohCom(SimpleHoster):
- __name__ = "VeohCom"
- __type__ = "hoster"
- __version__ = "0.22"
-
- __pattern__ = r'http://(?:www\.)?veoh\.com/(tv/)?(watch|videos)/(?P<ID>v\w+)'
- __config__ = [("quality", "Low;High;Auto", "Quality", "Auto")]
-
- __description__ = """Veoh.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- NAME_PATTERN = r'<meta name="title" content="(?P<N>.*?)"'
- OFFLINE_PATTERN = r'>Sorry, we couldn\'t find the video you were looking for'
-
- URL_REPLACEMENTS = [(__pattern__ + ".*", r'http://www.veoh.com/watch/\g<ID>')]
-
- COOKIES = [("veoh.com", "lassieLocale", "en")]
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = True
- self.chunkLimit = -1
-
-
- def handleFree(self, pyfile):
- quality = self.getConfig("quality")
- if quality == "Auto":
- quality = ("High", "Low")
-
- for q in quality:
- pattern = r'"fullPreviewHash%sPath":"(.+?)"' % q
- m = re.search(pattern, self.html)
- if m:
- pyfile.name += ".mp4"
- link = m.group(1).replace("\\", "")
- self.download(link)
- return
- else:
- self.logInfo(_("No %s quality video found") % q.upper())
- else:
- self.fail(_("No video found!"))
-
-
-getInfo = create_getInfo(VeohCom)
diff --git a/module/plugins/hoster/VidPlayNet.py b/module/plugins/hoster/VidPlayNet.py
deleted file mode 100644
index 5f979e856..000000000
--- a/module/plugins/hoster/VidPlayNet.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Test links:
-# BigBuckBunny_320x180.mp4 - 61.7 Mb - http://vidplay.net/38lkev0h3jv0
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class VidPlayNet(XFSHoster):
- __name__ = "VidPlayNet"
- __type__ = "hoster"
- __version__ = "0.04"
-
- __pattern__ = r'https?://(?:www\.)?vidplay\.net/\w{12}'
-
- __description__ = """VidPlay.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("t4skforce", "t4skforce1337[AT]gmail[DOT]com")]
-
-
- NAME_PATTERN = r'<b>Password:</b></div>\s*<h[1-6]>(?P<N>[^<]+)</h[1-6]>'
-
-
-getInfo = create_getInfo(VidPlayNet)
diff --git a/module/plugins/hoster/VimeoCom.py b/module/plugins/hoster/VimeoCom.py
deleted file mode 100644
index 7ca6c962b..000000000
--- a/module/plugins/hoster/VimeoCom.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class VimeoCom(SimpleHoster):
- __name__ = "VimeoCom"
- __type__ = "hoster"
- __version__ = "0.04"
-
- __pattern__ = r'https?://(?:www\.)?(player\.)?vimeo\.com/(video/)?(?P<ID>\d+)'
- __config__ = [("quality", "Lowest;Mobile;SD;HD;Highest", "Quality", "Highest"),
- ("original", "bool", "Try to download the original file first", True)]
-
- __description__ = """Vimeo.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- NAME_PATTERN = r'<title>(?P<N>.+) on Vimeo<'
- OFFLINE_PATTERN = r'class="exception_header"'
- TEMP_OFFLINE_PATTERN = r'Please try again in a few minutes.<'
-
- URL_REPLACEMENTS = [(__pattern__ + ".*", r'https://www.vimeo.com/\g<ID>')]
-
- COOKIES = [("vimeo.com", "language", "en")]
-
-
- def setup(self):
- self.resumeDownload = True
- self.multiDL = True
- self.chunkLimit = -1
-
-
- def handleFree(self, pyfile):
- password = self.getPassword()
-
- if self.js and 'class="btn iconify_down_b"' in self.html:
- html = self.js.eval(self.load(pyfile.url, get={'action': "download", 'password': password}, decode=True))
- pattern = r'href="(?P<URL>http://vimeo\.com.+?)".*?\>(?P<QL>.+?) '
- else:
- html = self.load("https://player.vimeo.com/video/" + self.info['pattern']['ID'], get={'password': password})
- pattern = r'"(?P<QL>\w+)":{"profile".*?"(?P<URL>http://pdl\.vimeocdn\.com.+?)"'
-
- link = dict((l.group('QL').lower(), l.group('URL')) for l in re.finditer(pattern, html))
-
- if self.getConfig("original"):
- if "original" in link:
- self.download(link[q])
- return
- else:
- self.logInfo(_("Original file not downloadable"))
-
- quality = self.getConfig("quality")
- if quality == "Highest":
- qlevel = ("hd", "sd", "mobile")
- elif quality == "Lowest":
- qlevel = ("mobile", "sd", "hd")
- else:
- qlevel = quality.lower()
-
- for q in qlevel:
- if q in link:
- self.download(link[q])
- return
- else:
- self.logInfo(_("No %s quality video found") % q.upper())
- else:
- self.fail(_("No video found!"))
-
-
-getInfo = create_getInfo(VimeoCom)
diff --git a/module/plugins/hoster/Vipleech4UCom.py b/module/plugins/hoster/Vipleech4UCom.py
deleted file mode 100644
index dec67e7a4..000000000
--- a/module/plugins/hoster/Vipleech4UCom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class Vipleech4UCom(DeadHoster):
- __name__ = "Vipleech4UCom"
- __type__ = "hoster"
- __version__ = "0.20"
-
- __pattern__ = r'http://(?:www\.)?vipleech4u\.com/manager\.php'
-
- __description__ = """Vipleech4u.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Kagenoshin", "kagenoshin@gmx.ch")]
-
-
-getInfo = create_getInfo(Vipleech4UCom)
diff --git a/module/plugins/hoster/WarserverCz.py b/module/plugins/hoster/WarserverCz.py
deleted file mode 100644
index 1631a021d..000000000
--- a/module/plugins/hoster/WarserverCz.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class WarserverCz(DeadHoster):
- __name__ = "WarserverCz"
- __type__ = "hoster"
- __version__ = "0.13"
-
- __pattern__ = r'http://(?:www\.)?warserver\.cz/stahnout/\d+'
-
- __description__ = """Warserver.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
-getInfo = create_getInfo(WarserverCz)
diff --git a/module/plugins/hoster/WebshareCz.py b/module/plugins/hoster/WebshareCz.py
deleted file mode 100644
index 98187d46a..000000000
--- a/module/plugins/hoster/WebshareCz.py
+++ /dev/null
@@ -1,63 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.network.RequestFactory import getURL
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class WebshareCz(SimpleHoster):
- __name__ = "WebshareCz"
- __type__ = "hoster"
- __version__ = "0.16"
-
- __pattern__ = r'https?://(?:www\.)?webshare\.cz/(?:#/)?file/(?P<ID>\w+)'
-
- __description__ = """WebShare.cz hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it"),
- ("rush", "radek.senfeld@gmail.com")]
-
-
- @classmethod
- def getInfo(cls, url="", html=""):
- info = super(WebshareCz, cls).getInfo(url, html)
-
- if url:
- info['pattern'] = re.match(cls.__pattern__, url).groupdict()
-
- api_data = getURL("https://webshare.cz/api/file_info/",
- post={'ident': info['pattern']['ID']},
- decode=True)
-
- if 'File not found' in api_data:
- info['status'] = 1
- else:
- info["status"] = 2
- info['name'] = re.search('<name>(.+)</name>', api_data).group(1) or info['name']
- info['size'] = re.search('<size>(.+)</size>', api_data).group(1) or info['size']
-
- return info
-
-
- def handleFree(self, pyfile):
- wst = self.account.infos['wst'] if self.account and 'wst' in self.account.infos else ""
-
- api_data = getURL('https://webshare.cz/api/file_link/',
- post={'ident': self.info['pattern']['ID'], 'wst': wst},
- decode=True)
-
- self.logDebug("API data: " + api_data)
-
- m = re.search('<link>(.+)</link>', api_data)
- if m is None:
- self.error(_("Unable to detect direct link"))
-
- self.link = m.group(1)
-
-
- def handlePremium(self, pyfile):
- return self.handleFree(pyfile)
-
-
-getInfo = create_getInfo(WebshareCz)
diff --git a/module/plugins/hoster/WrzucTo.py b/module/plugins/hoster/WrzucTo.py
deleted file mode 100644
index 631f9d3c6..000000000
--- a/module/plugins/hoster/WrzucTo.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pycurl import HTTPHEADER
-
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class WrzucTo(SimpleHoster):
- __name__ = "WrzucTo"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'http://(?:www\.)?wrzuc\.to/(\w+(\.wt|\.html)|(\w+/?linki/\w+))'
-
- __description__ = """Wrzuc.to hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'id="file_info">\s*<strong>(?P<N>.*?)</strong>'
- SIZE_PATTERN = r'class="info">\s*<tr>\s*<td>(?P<S>.*?)</td>'
-
- COOKIES = [("wrzuc.to", "language", "en")]
-
-
- def setup(self):
- self.multiDL = True
-
-
- def handleFree(self, pyfile):
- data = dict(re.findall(r'(md5|file): "(.*?)"', self.html))
- if len(data) != 2:
- self.error(_("No file ID"))
-
- self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
- self.req.http.lastURL = pyfile.url
- self.load("http://www.wrzuc.to/ajax/server/prepair", post={"md5": data['md5']})
-
- self.req.http.lastURL = pyfile.url
- self.html = self.load("http://www.wrzuc.to/ajax/server/download_link", post={"file": data['file']})
-
- data.update(re.findall(r'"(download_link|server_id)":"(.*?)"', self.html))
- if len(data) != 4:
- self.error(_("No download URL"))
-
- download_url = "http://%s.wrzuc.to/pobierz/%s" % (data['server_id'], data['download_link'])
- self.download(download_url)
-
-
-getInfo = create_getInfo(WrzucTo)
diff --git a/module/plugins/hoster/WuploadCom.py b/module/plugins/hoster/WuploadCom.py
deleted file mode 100644
index a73ac92e0..000000000
--- a/module/plugins/hoster/WuploadCom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class WuploadCom(DeadHoster):
- __name__ = "WuploadCom"
- __type__ = "hoster"
- __version__ = "0.23"
-
- __pattern__ = r'http://(?:www\.)?wupload\..+?/file/((\w+/)?\d+)(/.*)?'
-
- __description__ = """Wupload.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("jeix", "jeix@hasnomail.de"),
- ("Paul King", "")]
-
-
-getInfo = create_getInfo(WuploadCom)
diff --git a/module/plugins/hoster/X7To.py b/module/plugins/hoster/X7To.py
deleted file mode 100644
index 6ccc6d637..000000000
--- a/module/plugins/hoster/X7To.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class X7To(DeadHoster):
- __name__ = "X7To"
- __type__ = "hoster"
- __version__ = "0.41"
-
- __pattern__ = r'http://(?:www\.)?x7\.to/'
-
- __description__ = """X7.to hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("ernieb", "ernieb")]
-
-
-getInfo = create_getInfo(X7To)
diff --git a/module/plugins/hoster/XFileSharingPro.py b/module/plugins/hoster/XFileSharingPro.py
deleted file mode 100644
index 23af6e7fc..000000000
--- a/module/plugins/hoster/XFileSharingPro.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.plugin.internal.XFSHoster import XFSHoster, create_getInfo
-
-
-class XFileSharingPro(XFSHoster):
- __name__ = "XFileSharingPro"
- __type__ = "hoster"
- __version__ = "0.44"
-
- __pattern__ = r'^unmatchable$'
-
- __description__ = """XFileSharingPro dummy hoster plugin for hook"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- URL_REPLACEMENTS = [("/embed-", "/")]
-
-
- def _log(self, type, args):
- msg = " | ".join(str(a).strip() for a in args if a)
- logger = getattr(self.log, type)
- logger("%s: %s: %s" % (self.__name__, self.HOSTER_NAME, msg or _("%s MARK" % type.upper())))
-
-
- def init(self):
- super(XFileSharingPro, self).init()
-
- self.__pattern__ = self.core.pluginManager.hosterPlugins[self.__name__]['pattern']
-
- self.HOSTER_DOMAIN = re.match(self.__pattern__, self.pyfile.url).group("DOMAIN").lower()
- self.HOSTER_NAME = "".join(part.capitalize() for part in re.split(r'(\.|\d+)', self.HOSTER_DOMAIN) if part != '.')
-
- if self.HOSTER_NAME[0].isdigit():
- self.HOSTER_NAME = 'X' + self.HOSTER_NAME
-
- account = self.core.accountManager.getAccountPlugin(self.HOSTER_NAME)
-
- if account and account.canUse():
- self.account = account
-
- elif self.account:
- self.account.HOSTER_DOMAIN = self.HOSTER_DOMAIN
-
- else:
- return
-
- self.user, data = self.account.selectAccount()
- self.req = self.account.getAccountRequest(self.user)
- self.premium = self.account.isPremium(self.user)
-
-
- def setup(self):
- self.chunkLimit = 1
- self.resumeDownload = self.premium
- self.multiDL = True
-
-
-getInfo = create_getInfo(XFileSharingPro)
diff --git a/module/plugins/hoster/XdadevelopersCom.py b/module/plugins/hoster/XdadevelopersCom.py
deleted file mode 100644
index 7d50d4f57..000000000
--- a/module/plugins/hoster/XdadevelopersCom.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# -*- coding: utf-8 -*
-#
-# Test links:
-# http://forum.xda-developers.com/devdb/project/dl/?id=10885
-
-import re
-
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class XdadevelopersCom(SimpleHoster):
- __name__ = "XdadevelopersCom"
- __type__ = "hoster"
- __version__ = "0.03"
-
- __pattern__ = r'https?://(?:www\.)?forum\.xda-developers\.com/devdb/project/dl/\?id=\d+'
-
- __description__ = """Xda-developers.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
-
-
- NAME_PATTERN = r'<label>Filename:</label>\s*<div>\s*(?P<N>.*?)\n'
- SIZE_PATTERN = r'<label>Size:</label>\s*<div>\s*(?P<S>[\d.,]+)(?P<U>[\w^_]+)'
- OFFLINE_PATTERN = r'</i> Device Filter</h3>'
-
-
- def setup(self):
- self.multiDL = True
- self.resumeDownload = True
- self.chunkLimit = 1
-
-
- def handleFree(self, pyfile):
- self.link = pyfile.url + "&task=get" #@TODO: Revert to `get={'task': "get"}` in 0.4.10
-
-
-getInfo = create_getInfo(XdadevelopersCom)
diff --git a/module/plugins/hoster/YibaishiwuCom.py b/module/plugins/hoster/YibaishiwuCom.py
deleted file mode 100644
index 6da5cff33..000000000
--- a/module/plugins/hoster/YibaishiwuCom.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from pyload.utils import json_loads
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class YibaishiwuCom(SimpleHoster):
- __name__ = "YibaishiwuCom"
- __type__ = "hoster"
- __version__ = "0.14"
-
- __pattern__ = r'http://(?:www\.)?(?:u\.)?115\.com/file/(?P<ID>\w+)'
-
- __description__ = """115.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- NAME_PATTERN = r'file_name: \'(?P<N>.+?)\''
- SIZE_PATTERN = r'file_size: \'(?P<S>.+?)\''
- OFFLINE_PATTERN = ur'<h3><i style="color:red;">哎呀提取码䞍存圚䞍劚搜搜看吧</i></h3>'
-
- LINK_FREE_PATTERN = r'(/\?ct=(pickcode|download)[^"\']+)'
-
-
- def handleFree(self, pyfile):
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("LINK_FREE_PATTERN not found"))
-
- url = m.group(1)
-
- self.logDebug(('FREEUSER' if m.group(2) == 'download' else 'GUEST') + ' URL', url)
-
- res = json_loads(self.load("http://115.com" + url, decode=False))
- if "urls" in res:
- mirrors = res['urls']
-
- elif "data" in res:
- mirrors = res['data']
-
- else:
- mirrors = None
-
- for mr in mirrors:
- try:
- url = mr['url'].replace("\\", "")
- self.logDebug("Trying URL: " + url)
- self.download(url)
- break
- except Exception:
- continue
- else:
- self.fail(_("No working link found"))
-
-
-getInfo = create_getInfo(YibaishiwuCom)
diff --git a/module/plugins/hoster/ZShareNet.py b/module/plugins/hoster/ZShareNet.py
deleted file mode 100644
index a6a34143f..000000000
--- a/module/plugins/hoster/ZShareNet.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.internal.DeadHoster import DeadHoster, create_getInfo
-
-
-class ZShareNet(DeadHoster):
- __name__ = "ZShareNet"
- __type__ = "hoster"
- __version__ = "0.21"
-
- __pattern__ = r'https?://(?:ww[2w]\.)?zshares?\.net/.+'
-
- __description__ = """ZShare.net hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("espes", ""),
- ("Cptn Sandwich", "")]
-
-
-getInfo = create_getInfo(ZShareNet)
diff --git a/module/plugins/hoster/ZeveraCom.py b/module/plugins/hoster/ZeveraCom.py
deleted file mode 100644
index 665b64789..000000000
--- a/module/plugins/hoster/ZeveraCom.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urlparse import urljoin
-
-from module.plugins.internal.MultiHoster import MultiHoster, create_getInfo
-
-
-class ZeveraCom(MultiHoster):
- __name__ = "ZeveraCom"
- __type__ = "hoster"
- __version__ = "0.28"
-
- __pattern__ = r'https?://(?:www\.)zevera\.com/(getFiles\.ashx|Members/download\.ashx)\?.*ourl=.+'
-
- __description__ = """Zevera.com multi-hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- def handlePremium(self, pyfile):
- self.link = "https://%s/getFiles.ashx?ourl=%s" % (self.account.HOSTER_DOMAIN, pyfile.url)
-
-
- def checkFile(self):
- if self.checkDownload({"error": 'action="ErrorDownload.aspx'}):
- self.fail(_("Error response received"))
-
- return super(ZeveraCom, self).checkFile()
-
-
-getInfo = create_getInfo(ZeveraCom)
diff --git a/module/plugins/hoster/ZippyshareCom.py b/module/plugins/hoster/ZippyshareCom.py
deleted file mode 100644
index f08fb7dae..000000000
--- a/module/plugins/hoster/ZippyshareCom.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.CaptchaService import ReCaptcha
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo
-
-
-class ZippyshareCom(SimpleHoster):
- __name__ = "ZippyshareCom"
- __type__ = "hoster"
- __version__ = "0.72"
-
- __pattern__ = r'http://www\d{0,2}\.zippyshare\.com/v(/|iew\.jsp.*key=)(?P<KEY>[\w^_]+)'
-
- __description__ = """Zippyshare.com hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- COOKIES = [("zippyshare.com", "ziplocale", "en")]
-
- NAME_PATTERN = r'("\d{6,}/"[ ]*\+.+?"/|<title>Zippyshare.com - )(?P<N>.+?)("|</title>)'
- SIZE_PATTERN = r'>Size:.+?">(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
- OFFLINE_PATTERN = r'>File does not exist on this server'
-
- LINK_PREMIUM_PATTERN = r'document.location = \'(.+?)\''
-
-
- def setup(self):
- self.chunkLimit = -1
- self.multiDL = True
- self.resumeDownload = True
-
-
- def handleFree(self, pyfile):
- recaptcha = ReCaptcha(self)
- captcha_key = recaptcha.detect_key()
-
- if captcha_key:
- try:
- self.link = re.search(self.LINK_PREMIUM_PATTERN, self.html)
- recaptcha.challenge()
-
- except Exception, e:
- self.error(e)
-
- else:
- self.link = '/'.join(("d", self.info['pattern']['KEY'], str(self.get_checksum()), self.pyfile.name))
-
-
- def get_checksum(self):
- try:
- n = 2
- b = int(re.search(r'var b = (\d+)', self.html).group(1))
- checksum = int("%d3" % (n + n * 2 + b))
-
- except Exception:
- self.error(_("Unable to calculate checksum"))
-
- else:
- return checksum
-
-
-getInfo = create_getInfo(ZippyshareCom)
diff --git a/module/plugins/internal/BasePlugin.py b/module/plugins/internal/BasePlugin.py
deleted file mode 100644
index 792497449..000000000
--- a/module/plugins/internal/BasePlugin.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urllib import unquote
-from urlparse import urljoin, urlparse
-
-from module.network.HTTPRequest import BadHeader
-from module.plugins.internal.SimpleHoster import create_getInfo, fileUrl
-from module.plugins.Hoster import Hoster
-
-
-class BasePlugin(Hoster):
- __name__ = "BasePlugin"
- __type__ = "hoster"
- __version__ = "0.34"
-
- __pattern__ = r'^unmatchable$'
-
- __description__ = """Base plugin when any other didnt fit"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- @classmethod
- def getInfo(cls, url="", html=""): #@TODO: Move to hoster class in 0.4.10
- url = unquote(url)
- url_p = urlparse(url)
- return {'name' : (url_p.path.split('/')[-1]
- or url_p.query.split('=', 1)[::-1][0].split('&', 1)[0]
- or url_p.netloc.split('.', 1)[0]),
- 'size' : 0,
- 'status': 3 if url else 8,
- 'url' : url}
-
-
- def setup(self):
- self.chunkLimit = -1
- self.multiDL = True
- self.resumeDownload = True
-
-
- def process(self, pyfile):
- """main function"""
-
- pyfile.name = self.getInfo(pyfile.url)['name']
-
- if not pyfile.url.startswith("http"):
- self.fail(_("No plugin matched"))
-
- for _i in xrange(5):
- try:
- link = fileUrl(self, unquote(pyfile.url))
-
- if link:
- self.download(link, ref=False, disposition=True)
- else:
- self.fail(_("File not found"))
-
- except BadHeader, e:
- if e.code is 404:
- self.offline()
-
- elif e.code in (401, 403):
- self.logDebug("Auth required", "Received HTTP status code: %d" % e.code)
-
- account = self.core.accountManager.getAccountPlugin('Http')
- servers = [x['login'] for x in account.getAllAccounts()]
- server = urlparse(pyfile.url).netloc
-
- if server in servers:
- self.logDebug("Logging on to %s" % server)
- self.req.addAuth(account.getAccountData(server)['password'])
- else:
- pwd = self.getPassword()
- if ':' in pwd:
- self.req.addAuth(pwd)
- else:
- self.fail(_("Authorization required"))
- else:
- self.fail(e)
- else:
- break
- else:
- self.fail(_("No file downloaded")) #@TODO: Move to hoster class in 0.4.10
-
- check = self.checkDownload({'empty file': re.compile(r'\A\Z'),
- 'html file' : re.compile(r'\A\s*<!DOCTYPE html'),
- 'html error': re.compile(r'\A\s*(<.+>)?\d{3}(\Z|\s+)')})
- if check:
- self.fail(check.capitalize())
-
-
-getInfo = create_getInfo(BasePlugin)
diff --git a/module/plugins/internal/CaptchaService.py b/module/plugins/internal/CaptchaService.py
deleted file mode 100644
index 6f2c8e06d..000000000
--- a/module/plugins/internal/CaptchaService.py
+++ /dev/null
@@ -1,522 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-import time
-
-from base64 import b64encode
-from random import random, randint
-from urlparse import urljoin, urlparse
-
-from module.common.json_layer import json_loads
-from module.plugins.Plugin import Base
-
-
-#@TODO: Extend (new) Plugin class; remove all `html` args
-class CaptchaService(Base):
- __name__ = "CaptchaService"
- __version__ = "0.25"
-
- __description__ = """Base captcha service plugin"""
- __license__ = "GPLv3"
- __authors__ = [("pyLoad Team", "admin@pyload.org")]
-
-
- key = None #: last key detected
-
-
- def __init__(self, plugin):
- self.plugin = plugin
- super(CaptchaService, self).__init__(plugin.core)
-
-
- def detect_key(self, html=None):
- raise NotImplementedError
-
-
- def challenge(self, key=None, html=None):
- raise NotImplementedError
-
-
- def result(self, server, challenge):
- raise NotImplementedError
-
-
-class ReCaptcha(CaptchaService):
- __name__ = "ReCaptcha"
- __version__ = "0.14"
-
- __description__ = """ReCaptcha captcha service plugin"""
- __license__ = "GPLv3"
- __authors__ = [("pyLoad Team", "admin@pyload.org"),
- ("Walter Purcaro", "vuolter@gmail.com"),
- ("zapp-brannigan", "fuerst.reinje@web.de")]
-
-
- KEY_V2_PATTERN = r'(?:data-sitekey=["\']|["\']sitekey["\']:\s*["\'])([\w-]+)'
- KEY_V1_PATTERN = r'(?:recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=|Recaptcha\.create\s*\(\s*["\'])([\w-]+)'
-
-
- def detect_key(self, html=None):
- if not html:
- if hasattr(self.plugin, "html") and self.plugin.html:
- html = self.plugin.html
- else:
- errmsg = _("ReCaptcha html not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- m = re.search(self.KEY_V2_PATTERN, html) or re.search(self.KEY_V1_PATTERN, html)
- if m:
- self.key = m.group(1).strip()
- self.logDebug("Key: %s" % self.key)
- return self.key
- else:
- self.logDebug("Key not found")
- return None
-
-
- def challenge(self, key=None, html=None, version=None):
- if not key:
- if self.detect_key(html):
- key = self.key
- else:
- errmsg = _("ReCaptcha key not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- if version in (1, 2):
- return getattr(self, "_challenge_v%s" % version)(key)
-
- elif not html and hasattr(self.plugin, "html") and self.plugin.html:
- version = 2 if re.search(self.KEY_V2_PATTERN, self.plugin.html) else 1
- return self.challenge(key, self.plugin.html, version)
-
- else:
- errmsg = _("ReCaptcha html not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
-
- def _challenge_v1(self, key):
- html = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge",
- get={'k': key})
- try:
- challenge = re.search("challenge : '(.+?)',", html).group(1)
- server = re.search("server : '(.+?)',", html).group(1)
-
- except AttributeError:
- errmsg = _("ReCaptcha challenge pattern not found")
- self.plugin.fail(errmsg)
- raise AttributeError(errmsg)
-
- self.logDebug("Challenge: %s" % challenge)
-
- return self.result(server, challenge), challenge
-
-
- def result(self, server, challenge):
- result = self.plugin.decryptCaptcha("%simage" % server,
- get={'c': challenge},
- cookies=True,
- forceUser=True,
- imgtype="jpg")
-
- self.logDebug("Result: %s" % result)
-
- return result
-
-
- def _collectApiInfo(self):
- html = self.plugin.req.load("http://www.google.com/recaptcha/api.js")
- a = re.search(r'po.src = \'(.*?)\';', html).group(1)
- vers = a.split("/")[5]
-
- self.logDebug("API version: %s" %vers)
-
- language = a.split("__")[1].split(".")[0]
-
- self.logDebug("API language: %s" % language)
-
- html = self.plugin.req.load("https://apis.google.com/js/api.js")
- b = re.search(r'"h":"(.*?)","', html).group(1)
- jsh = b.decode('unicode-escape')
-
- self.logDebug("API jsh-string: %s" % jsh)
-
- return vers, language, jsh
-
-
- def _prepareTimeAndRpc(self):
- self.plugin.req.load("http://www.google.com/recaptcha/api2/demo")
-
- millis = int(round(time.time() * 1000))
-
- self.logDebug("Time: %s" % millis)
-
- rand = randint(1, 99999999)
- a = "0.%s" % str(rand * 2147483647)
- rpc = int(100000000 * float(a))
-
- self.logDebug("Rpc-token: %s" % rpc)
-
- return millis, rpc
-
-
- def _challenge_v2(self, key, parent=None):
- if parent is None:
- try:
- parent = urljoin("http://", urlparse(self.plugin.pyfile.url).netloc)
-
- except Exception:
- parent = ""
-
- botguardstring = "!A"
- vers, language, jsh = self._collectApiInfo()
- millis, rpc = self._prepareTimeAndRpc()
-
- html = self.plugin.req.load("https://www.google.com/recaptcha/api2/anchor",
- get={'k' : key,
- 'hl' : language,
- 'v' : vers,
- 'usegapi' : "1",
- 'jsh' : "%s#id=IO_%s" % (jsh, millis),
- 'parent' : parent,
- 'pfname' : "",
- 'rpctoken': rpc})
-
- token1 = re.search(r'id="recaptcha-token" value="(.*?)">', html)
- self.logDebug("Token #1: %s" % token1.group(1))
-
- html = self.plugin.req.load("https://www.google.com/recaptcha/api2/frame",
- get={'c' : token1.group(1),
- 'hl' : language,
- 'v' : vers,
- 'bg' : botguardstring,
- 'k' : key,
- 'usegapi': "1",
- 'jsh' : jsh}).decode('unicode-escape')
-
- token2 = re.search(r'"finput","(.*?)",', html)
- self.logDebug("Token #2: %s" % token2.group(1))
-
- token3 = re.search(r'."asconf".\s,".*?".\s,"(.*?)".', html)
- self.logDebug("Token #3: %s" % token3.group(1))
-
- html = self.plugin.req.load("https://www.google.com/recaptcha/api2/reload",
- post={'k' : key,
- 'c' : token2.group(1),
- 'reason': "fi",
- 'fbg' : token3.group(1)})
-
- token4 = re.search(r'"rresp","(.*?)",', html)
- self.logDebug("Token #4: %s" % token4.group(1))
-
- millis_captcha_loading = int(round(time.time() * 1000))
- captcha_response = self.plugin.decryptCaptcha("https://www.google.com/recaptcha/api2/payload",
- get={'c':token4.group(1), 'k':key},
- cookies=True,
- forceUser=True)
- response = b64encode('{"response":"%s"}' % captcha_response)
-
- self.logDebug("Result: %s" % response)
-
- timeToSolve = int(round(time.time() * 1000)) - millis_captcha_loading
- timeToSolveMore = timeToSolve + int(float("0." + str(randint(1, 99999999))) * 500)
-
- html = self.plugin.req.load("https://www.google.com/recaptcha/api2/userverify",
- post={'k' : key,
- 'c' : token4.group(1),
- 'response': response,
- 't' : timeToSolve,
- 'ct' : timeToSolveMore,
- 'bg' : botguardstring})
-
- token5 = re.search(r'"uvresp","(.*?)",', html)
- self.logDebug("Token #5: %s" % token5.group(1))
-
- result = token5.group(1)
-
- return result, None
-
-
-
-class AdsCaptcha(CaptchaService):
- __name__ = "AdsCaptcha"
- __version__ = "0.08"
-
- __description__ = """AdsCaptcha captcha service plugin"""
- __license__ = "GPLv3"
- __authors__ = [("pyLoad Team", "admin@pyload.org")]
-
-
- CAPTCHAID_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*CaptchaId=(\d+)'
- PUBLICKEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*PublicKey=([\w-]+)'
-
-
- def detect_key(self, html=None):
- if not html:
- if hasattr(self.plugin, "html") and self.plugin.html:
- html = self.plugin.html
- else:
- errmsg = _("AdsCaptcha html not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- m = re.search(self.PUBLICKEY_PATTERN, html)
- n = re.search(self.CAPTCHAID_PATTERN, html)
- if m and n:
- self.key = (m.group(1).strip(), n.group(1).strip()) #: key is the tuple(PublicKey, CaptchaId)
- self.logDebug("Key|id: %s | %s" % self.key)
- return self.key
- else:
- self.logDebug("Key or id not found")
- return None
-
-
- def challenge(self, key=None, html=None):
- if not key:
- if self.detect_key(html):
- key = self.key
- else:
- errmsg = _("AdsCaptcha key not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- PublicKey, CaptchaId = key
-
- html = self.plugin.req.load("http://api.adscaptcha.com/Get.aspx",
- get={'CaptchaId': CaptchaId,
- 'PublicKey': PublicKey})
- try:
- challenge = re.search("challenge: '(.+?)',", html).group(1)
- server = re.search("server: '(.+?)',", html).group(1)
-
- except AttributeError:
- errmsg = _("AdsCaptcha challenge pattern not found")
- self.plugin.fail(errmsg)
- raise AttributeError(errmsg)
-
- self.logDebug("Challenge: %s" % challenge)
-
- return self.result(server, challenge), challenge
-
-
- def result(self, server, challenge):
- result = self.plugin.decryptCaptcha("%sChallenge.aspx" % server,
- get={'cid': challenge, 'dummy': random()},
- cookies=True,
- imgtype="jpg")
-
- self.logDebug("Result: %s" % result)
-
- return result
-
-
-class SolveMedia(CaptchaService):
- __name__ = "SolveMedia"
- __version__ = "0.12"
-
- __description__ = """SolveMedia captcha service plugin"""
- __license__ = "GPLv3"
- __authors__ = [("pyLoad Team", "admin@pyload.org")]
-
-
- KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(?:no)?script\?k=(.+?)["\']'
-
-
- def detect_key(self, html=None):
- if not html:
- if hasattr(self.plugin, "html") and self.plugin.html:
- html = self.plugin.html
- else:
- errmsg = _("SolveMedia html not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- m = re.search(self.KEY_PATTERN, html)
- if m:
- self.key = m.group(1).strip()
- self.logDebug("Key: %s" % self.key)
- return self.key
- else:
- self.logDebug("Key not found")
- return None
-
-
- def challenge(self, key=None, html=None):
- if not key:
- if self.detect_key(html):
- key = self.key
- else:
- errmsg = _("SolveMedia key not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.noscript",
- get={'k': key})
- try:
- challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="([^"]+)">',
- html).group(1)
- server = "http://api.solvemedia.com/papi/media"
-
- except AttributeError:
- errmsg = _("SolveMedia challenge pattern not found")
- self.plugin.fail(errmsg)
- raise AttributeError(errmsg)
-
- self.logDebug("Challenge: %s" % challenge)
-
- result = self.result(server, challenge)
-
- try:
- magic = re.search(r'name="magic" value="(.+?)"', html).group(1)
-
- except AttributeError:
- self.logDebug("Magic code not found")
-
- else:
- if not self._verify(key, magic, result, challenge):
- self.logDebug("Captcha code was invalid")
-
- return result, challenge
-
-
- def _verify(self, key, magic, result, challenge, ref=None): #@TODO: Clean up
- if ref is None:
- try:
- ref = self.plugin.pyfile.url
-
- except Exception:
- ref = ""
-
- html = self.plugin.req.load("http://api.solvemedia.com/papi/verify.noscript",
- post={'adcopy_response' : result,
- 'k' : key,
- 'l' : "en",
- 't' : "img",
- 's' : "standard",
- 'magic' : magic,
- 'adcopy_challenge' : challenge,
- 'ref' : ref})
- try:
- html = self.plugin.req.load(re.search(r'URL=(.+?)">', html).group(1))
- gibberish = re.search(r'id=gibberish>(.+?)</textarea>', html).group(1)
-
- except Exception:
- return False
-
- else:
- return True
-
-
- def result(self, server, challenge):
- result = self.plugin.decryptCaptcha(server,
- get={'c': challenge},
- cookies=True,
- imgtype="gif")
-
- self.logDebug("Result: %s" % result)
-
- return result
-
-
-class AdYouLike(CaptchaService):
- __name__ = "AdYouLike"
- __version__ = "0.05"
-
- __description__ = """AdYouLike captcha service plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- AYL_PATTERN = r'Adyoulike\.create\s*\((.+?)\)'
- CALLBACK_PATTERN = r'(Adyoulike\.g\._jsonp_\d+)'
-
-
- def detect_key(self, html=None):
- if not html:
- if hasattr(self.plugin, "html") and self.plugin.html:
- html = self.plugin.html
- else:
- errmsg = _("AdYouLike html not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- m = re.search(self.AYL_PATTERN, html)
- n = re.search(self.CALLBACK_PATTERN, html)
- if m and n:
- self.key = (m.group(1).strip(), n.group(1).strip())
- self.logDebug("Ayl|callback: %s | %s" % self.key)
- return self.key #: key is the tuple(ayl, callback)
- else:
- self.logDebug("Ayl or callback not found")
- return None
-
-
- def challenge(self, key=None, html=None):
- if not key:
- if self.detect_key(html):
- key = self.key
- else:
- errmsg = _("AdYouLike key not found")
- self.plugin.fail(errmsg)
- raise TypeError(errmsg)
-
- ayl, callback = key
-
- # {"adyoulike":{"key":"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"},
- # "all":{"element_id":"ayl_private_cap_92300","lang":"fr","env":"prod"}}
- ayl = json_loads(ayl)
-
- html = self.plugin.req.load("http://api-ayl.appspot.com/challenge",
- get={'key' : ayl['adyoulike']['key'],
- 'env' : ayl['all']['env'],
- 'callback': callback})
- try:
- challenge = json_loads(re.search(callback + r'\s*\((.+?)\)', html).group(1))
-
- except AttributeError:
- errmsg = _("AdYouLike challenge pattern not found")
- self.plugin.fail(errmsg)
- raise AttributeError(errmsg)
-
- self.logDebug("Challenge: %s" % challenge)
-
- return self.result(ayl, challenge), challenge
-
-
- def result(self, server, challenge):
- # Adyoulike.g._jsonp_5579316662423138
- # ({"translations":{"fr":{"instructions_visual":"Recopiez « Soonnight » ci-dessous :"}},
- # "site_under":true,"clickable":true,"pixels":{"VIDEO_050":[],"DISPLAY":[],"VIDEO_000":[],"VIDEO_100":[],
- # "VIDEO_025":[],"VIDEO_075":[]},"medium_type":"image/adyoulike",
- # "iframes":{"big":"<iframe src=\"http://www.soonnight.com/campagn.html\" scrolling=\"no\"
- # height=\"250\" width=\"300\" frameborder=\"0\"></iframe>"},"shares":{},"id":256,
- # "token":"e6QuI4aRSnbIZJg02IsV6cp4JQ9~MjA1","formats":{"small":{"y":300,"x":0,"w":300,"h":60},
- # "big":{"y":0,"x":0,"w":300,"h":250},"hover":{"y":440,"x":0,"w":300,"h":60}},
- # "tid":"SqwuAdxT1EZoi4B5q0T63LN2AkiCJBg5"})
-
- if isinstance(server, basestring):
- server = json_loads(server)
-
- if isinstance(challenge, basestring):
- challenge = json_loads(challenge)
-
- try:
- instructions_visual = challenge['translations'][server['all']['lang']]['instructions_visual']
- result = re.search(u'«(.+?)»', instructions_visual).group(1).strip()
-
- except AttributeError:
- errmsg = _("AdYouLike result not found")
- self.plugin.fail(errmsg)
- raise AttributeError(errmsg)
-
- result = {'_ayl_captcha_engine' : "adyoulike",
- '_ayl_env' : server['all']['env'],
- '_ayl_tid' : challenge['tid'],
- '_ayl_token_challenge': challenge['token'],
- '_ayl_response' : response}
-
- self.logDebug("Result: %s" % result)
-
- return result
diff --git a/module/plugins/internal/DeadCrypter.py b/module/plugins/internal/DeadCrypter.py
deleted file mode 100644
index ce56947fc..000000000
--- a/module/plugins/internal/DeadCrypter.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.Crypter import Crypter as _Crypter
-from pyload.plugin.internal.SimpleCrypter import create_getInfo
-
-
-class DeadCrypter(_Crypter):
- __name__ = "DeadCrypter"
- __type__ = "crypter"
- __version__ = "0.04"
-
- __pattern__ = r'^unmatchable$'
-
- __description__ = """Crypter is no longer available"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it")]
-
-
- @classmethod
- def apiInfo(cls, url="", get={}, post={}):
- api = super(DeadCrypter, self).apiInfo(url, get, post)
- api['status'] = 1
- return api
-
-
- def setup(self):
- self.pyfile.error = "Crypter is no longer available"
- self.offline() #@TODO: self.offline("Crypter is no longer available")
-
-
-getInfo = create_getInfo(DeadCrypter)
diff --git a/module/plugins/internal/DeadHoster.py b/module/plugins/internal/DeadHoster.py
deleted file mode 100644
index 132e4741a..000000000
--- a/module/plugins/internal/DeadHoster.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from pyload.plugin.Hoster import Hoster as _Hoster
-from pyload.plugin.internal.SimpleHoster import create_getInfo
-
-
-class DeadHoster(_Hoster):
- __name__ = "DeadHoster"
- __type__ = "hoster"
- __version__ = "0.14"
-
- __pattern__ = r'^unmatchable$'
-
- __description__ = """Hoster is no longer available"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
-
-
- @classmethod
- def apiInfo(cls, url="", get={}, post={}):
- api = super(DeadHoster, self).apiInfo(url, get, post)
- api['status'] = 1
- return api
-
-
- def setup(self):
- self.pyfile.error = "Hoster is no longer available"
- self.offline() #@TODO: self.offline("Hoster is no longer available")
-
-
-getInfo = create_getInfo(DeadHoster)
diff --git a/module/plugins/internal/Extractor.py b/module/plugins/internal/Extractor.py
deleted file mode 100644
index b445f1497..000000000
--- a/module/plugins/internal/Extractor.py
+++ /dev/null
@@ -1,139 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import os
-
-from module.PyFile import PyFile
-
-
-class ArchiveError(Exception):
- pass
-
-
-class CRCError(Exception):
- pass
-
-
-class PasswordError(Exception):
- pass
-
-
-class Extractor:
- __name__ = "Extractor"
- __version__ = "0.20"
-
- __description__ = """Base extractor plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "ranan@pyload.org"),
- ("Walter Purcaro", "vuolter@gmail.com"),
- ("Immenz", "immenz@gmx.net")]
-
-
- EXTENSIONS = []
- VERSION = ""
-
-
- @classmethod
- def isArchive(cls, filename):
- name = os.path.basename(filename).lower()
- return any(name.endswith(ext) for ext in cls.EXTENSIONS) and not cls.isMultipart(filename)
-
-
- @classmethod
- def isMultipart(cls,filename):
- return False
-
-
- @classmethod
- def isUsable(cls):
- """ Check if system statisfy dependencies
- :return: boolean
- """
- return None
-
-
- @classmethod
- def getTargets(cls, files_ids):
- """ Filter suited targets from list of filename id tuple list
- :param files_ids: List of filepathes
- :return: List of targets, id tuple list
- """
- return [(fname, id, fout) for fname, id, fout in files_ids if cls.isArchive(fname)]
-
-
- def __init__(self, manager, filename, out,
- fullpath=True,
- overwrite=False,
- excludefiles=[],
- renice=0,
- delete=False,
- keepbroken=False,
- fid=None):
- """ Initialize extractor for specific file """
- self.manager = manager
- self.filename = filename
- self.out = out
- self.fullpath = fullpath
- self.overwrite = overwrite
- self.excludefiles = excludefiles
- self.renice = renice
- self.delete = delete
- self.keepbroken = keepbroken
- self.files = [] #: Store extracted files here
-
- pyfile = self.manager.core.files.getFile(fid) if fid else None
- self.notifyProgress = lambda x: pyfile.setProgress(x) if pyfile else lambda x: None
-
-
- def init(self):
- """ Initialize additional data structures """
- pass
-
-
- def check(self):
- """Check if password if needed. Raise ArchiveError if integrity is
- questionable.
-
- :return: boolean
- :raises ArchiveError
- """
- raise PasswordError
-
-
- def isPassword(self, password):
- """ Check if the given password is/might be correct.
- If it can not be decided at this point return true.
-
- :param password:
- :return: boolean
- """
- return None
-
-
- def repair(self):
- return None
-
-
- def extract(self, password=None):
- """Extract the archive. Raise specific errors in case of failure.
-
- :param progress: Progress function, call this to update status
- :param password password to use
- :raises PasswordError
- :raises CRCError
- :raises ArchiveError
- :return:
- """
- raise NotImplementedError
-
-
- def getDeleteFiles(self):
- """Return list of files to delete, do *not* delete them here.
-
- :return: List with paths of files to delete
- """
- return [self.filename]
-
-
- def list(self, password=None):
- """Populate self.files at some point while extracting"""
- return self.files
diff --git a/module/plugins/internal/MultiHook.py b/module/plugins/internal/MultiHook.py
deleted file mode 100644
index 652443098..000000000
--- a/module/plugins/internal/MultiHook.py
+++ /dev/null
@@ -1,308 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from time import sleep
-
-from module.plugins.Hook import Hook
-from module.utils import decode, remove_chars
-
-
-class MultiHook(Hook):
- __name__ = "MultiHook"
- __type__ = "hook"
- __version__ = "0.37"
-
- __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
- ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
- ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
- ("retry" , "int" , "Number of retries before revert" , 10 ),
- ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
- ("reload" , "bool" , "Reload plugin list" , True ),
- ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
-
- __description__ = """Hook plugin for multi hoster/crypter"""
- __license__ = "GPLv3"
- __authors__ = [("pyLoad Team", "admin@pyload.org"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- MIN_INTERVAL = 1 * 60 * 60
-
- DOMAIN_REPLACEMENTS = [(r'180upload\.com' , "hundredeightyupload.com"),
- (r'1fichier\.com' , "onefichier.com" ),
- (r'2shared\.com' , "twoshared.com" ),
- (r'4shared\.com' , "fourshared.com" ),
- (r'bayfiles\.net' , "bayfiles.com" ),
- (r'cloudnator\.com' , "shragle.com" ),
- (r'dfiles\.eu' , "depositfiles.com" ),
- (r'easy-share\.com' , "crocko.com" ),
- (r'freakshare\.net' , "freakshare.com" ),
- (r'hellshare\.com' , "hellshare.cz" ),
- (r'ifile\.it' , "filecloud.io" ),
- (r'nowdownload\.\w+', "nowdownload.sx" ),
- (r'nowvideo\.\w+' , "nowvideo.sx" ),
- (r'putlocker\.com' , "firedrive.com" ),
- (r'share-?rapid\.cz', "multishare.cz" ),
- (r'ul\.to' , "uploaded.to" ),
- (r'uploaded\.net' , "uploaded.to" ),
- (r'uploadhero\.co' , "uploadhero.com" ),
- (r'zshares\.net' , "zshare.net" ),
- (r'(\d+.+)' , "X\1" )]
-
-
- def setup(self):
- self.plugins = []
- self.supported = []
- self.new_supported = []
-
- self.account = None
- self.pluginclass = None
- self.pluginmodule = None
- self.pluginname = None
- self.plugintype = None
-
- self._initPlugin()
-
-
- def _initPlugin(self):
- plugin, type = self.core.pluginManager.findPlugin(self.__name__)
-
- if not plugin:
- self.logWarning("Hook plugin will be deactivated due missing plugin reference")
- self.setConfig('activated', False)
- else:
- self.pluginname = self.__name__
- self.plugintype = type
- self.pluginmodule = self.core.pluginManager.loadModule(type, self.__name__)
- self.pluginclass = getattr(self.pluginmodule, self.__name__)
-
-
- def _loadAccount(self):
- self.account = self.core.accountManager.getAccountPlugin(self.pluginname)
-
- if self.account and not self.account.canUse():
- self.account = None
-
- if not self.account and hasattr(self.pluginclass, "LOGIN_ACCOUNT") and self.pluginclass.LOGIN_ACCOUNT:
- self.logWarning("Hook plugin will be deactivated due missing account reference")
- self.setConfig('activated', False)
-
-
- def coreReady(self):
- self._loadAccount()
-
-
- def getURL(self, *args, **kwargs): #@TODO: Remove in 0.4.10
- """ see HTTPRequest for argument list """
- h = pyreq.getHTTPRequest(timeout=120)
- try:
- if not 'decode' in kwargs:
- kwargs['decode'] = True
- rep = h.load(*args, **kwargs)
- finally:
- h.close()
-
- return rep
-
-
- def getConfig(self, option, default=''):
- """getConfig with default value - sublass may not implements all config options"""
- try:
- return self.getConf(option)
-
- except KeyError:
- return default
-
-
- def pluginsCached(self):
- if self.plugins:
- return self.plugins
-
- for _i in xrange(3):
- try:
- pluginset = self._pluginSet(self.getHosters() if self.plugintype == "hoster" else self.getCrypters())
-
- except Exception, e:
- self.logError(e, "Waiting 1 minute and retry")
- sleep(60)
-
- else:
- break
- else:
- return list()
-
- try:
- configmode = self.getConfig("pluginmode", 'all')
- if configmode in ("listed", "unlisted"):
- pluginlist = self.getConfig("pluginlist", '').replace('|', ',').replace(';', ',').split(',')
- configset = self._pluginSet(pluginlist)
-
- if configmode == "listed":
- pluginset &= configset
- else:
- pluginset -= configset
-
- except Exception, e:
- self.logError(e)
-
- self.plugins = list(pluginset)
-
- return self.plugins
-
-
- def _pluginSet(self, plugins):
- plugins = set((decode(x).strip().lower() for x in plugins if '.' in x))
-
- for rf, rt in self.DOMAIN_REPLACEMENTS:
- regex = re.compile(rf)
- for p in filter(lambda x: regex.match(x), plugins):
- plugins.remove(p)
- plugins.add(re.sub(rf, rt, p))
-
- plugins.discard('')
-
- return plugins
-
-
- def getHosters(self):
- """Load list of supported hoster
-
- :return: List of domain names
- """
- raise NotImplementedError
-
-
- def getCrypters(self):
- """Load list of supported crypters
-
- :return: List of domain names
- """
- raise NotImplementedError
-
-
- def periodical(self):
- """reload plugin list periodically"""
- self.logInfo(_("Reloading supported %s list") % self.plugintype)
-
- old_supported = self.supported
-
- self.supported = []
- self.new_supported = []
- self.plugins = []
-
- self.overridePlugins()
-
- old_supported = [plugin for plugin in old_supported if plugin not in self.supported]
-
- if old_supported:
- self.logDebug("Unload: %s" % ", ".join(old_supported))
- for plugin in old_supported:
- self.unloadPlugin(plugin)
-
- if self.getConfig("reload", True):
- self.interval = max(self.getConfig("reloadinterval", 12) * 60 * 60, self.MIN_INTERVAL)
- else:
- self.core.scheduler.removeJob(self.cb)
- self.cb = None
-
-
- def overridePlugins(self):
- excludedList = []
-
- if self.plugintype == "hoster":
- pluginMap = dict((name.lower(), name) for name in self.core.pluginManager.hosterPlugins.iterkeys())
- accountList = [account.type.lower() for account in self.core.api.getAccounts(False) if account.valid and account.premium]
- else:
- pluginMap = {}
- accountList = [name[::-1].replace("Folder"[::-1], "", 1).lower()[::-1] for name in self.core.pluginManager.crypterPlugins.iterkeys()]
-
- for plugin in self.pluginsCached():
- name = remove_chars(plugin, "-.")
-
- if name in accountList:
- excludedList.append(plugin)
- else:
- if name in pluginMap:
- self.supported.append(pluginMap[name])
- else:
- self.new_supported.append(plugin)
-
- if not self.supported and not self.new_supported:
- self.logError(_("No %s loaded") % self.plugintype)
- return
-
- # inject plugin plugin
- self.logDebug("Overwritten %ss: %s" % (self.plugintype, ", ".join(sorted(self.supported))))
-
- for plugin in self.supported:
- hdict = self.core.pluginManager.plugins[self.plugintype][plugin]
- hdict['new_module'] = self.pluginmodule
- hdict['new_name'] = self.pluginname
-
- if excludedList:
- self.logInfo(_("%ss not overwritten: %s") % (self.plugintype.capitalize(), ", ".join(sorted(excludedList))))
-
- if self.new_supported:
- plugins = sorted(self.new_supported)
-
- self.logDebug("New %ss: %s" % (self.plugintype, ", ".join(plugins)))
-
- # create new regexp
- regexp = r'.*(?P<DOMAIN>%s).*' % "|".join([x.replace(".", "\.") for x in plugins])
- if hasattr(self.pluginclass, "__pattern__") and isinstance(self.pluginclass.__pattern__, basestring) and '://' in self.pluginclass.__pattern__:
- regexp = r'%s|%s' % (self.pluginclass.__pattern__, regexp)
-
- self.logDebug("Regexp: %s" % regexp)
-
- hdict = self.core.pluginManager.plugins[self.plugintype][self.pluginname]
- hdict['pattern'] = regexp
- hdict['re'] = re.compile(regexp)
-
-
- def unloadPlugin(self, plugin):
- hdict = self.core.pluginManager.plugins[self.plugintype][plugin]
- if "module" in hdict:
- del hdict['module']
-
- if "new_module" in hdict:
- del hdict['new_module']
- del hdict['new_name']
-
-
- def unload(self):
- """Remove override for all plugins. Scheduler job is removed by hookmanager"""
- for plugin in self.supported:
- self.unloadPlugin(plugin)
-
- # reset pattern
- hdict = self.core.pluginManager.plugins[self.plugintype][self.pluginname]
-
- hdict['pattern'] = getattr(self.pluginclass, "__pattern__", r'^unmatchable$')
- hdict['re'] = re.compile(hdict['pattern'])
-
-
- def downloadFailed(self, pyfile):
- """remove plugin override if download fails but not if file is offline/temp.offline"""
- if pyfile.status != 8 or not self.getConfig("revertfailed", True):
- return
-
- hdict = self.core.pluginManager.plugins[self.plugintype][pyfile.pluginname]
- if "new_name" in hdict and hdict['new_name'] == self.pluginname:
- if pyfile.error == "MultiHook":
- self.logDebug("Unload MultiHook", pyfile.pluginname, hdict)
- self.unloadPlugin(pyfile.pluginname)
- pyfile.setStatus("queued")
- pyfile.sync()
- else:
- retries = max(self.getConfig("retry", 10), 0)
- wait_time = max(self.getConfig("retryinterval", 1), 0)
-
- if 0 < retries > pyfile.plugin.retries:
- self.logInfo(_("Retrying: %s") % pyfile.name)
- pyfile.setCustomStatus("MultiHook", "queued")
- pyfile.sync()
-
- pyfile.plugin.retries += 1
- pyfile.plugin.setWait(wait_time)
- pyfile.plugin.wait()
diff --git a/module/plugins/internal/MultiHoster.py b/module/plugins/internal/MultiHoster.py
deleted file mode 100644
index 63b7d76b1..000000000
--- a/module/plugins/internal/MultiHoster.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns, set_cookies
-
-
-class MultiHoster(SimpleHoster):
- __name__ = "MultiHoster"
- __type__ = "hoster"
- __version__ = "0.37"
-
- __pattern__ = r'^unmatchable$'
-
- __description__ = """Multi hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- LOGIN_ACCOUNT = True
-
-
- def setup(self):
- self.chunkLimit = 1
- self.multiDL = bool(self.account)
- self.resumeDownload = self.premium
-
-
- def prepare(self):
- self.info = {}
- self.html = ""
- self.link = "" #@TODO: Move to hoster class in 0.4.10
- self.directDL = False #@TODO: Move to hoster class in 0.4.10
-
- if self.LOGIN_ACCOUNT and not self.account:
- self.fail(_("Required account not found"))
-
- self.req.setOption("timeout", 120)
-
- if isinstance(self.COOKIES, list):
- set_cookies(self.req.cj, self.COOKIES)
-
- if self.DIRECT_LINK is None:
- self.directDL = self.__pattern__ != r'^unmatchable$' and re.match(self.__pattern__, self.pyfile.url)
- else:
- self.directDL = self.DIRECT_LINK
-
- self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS)
-
-
- def process(self, pyfile):
- self.prepare()
-
- if self.directDL:
- self.checkInfo()
- self.logDebug("Looking for direct download link...")
- self.handleDirect(pyfile)
-
- if not self.link and not self.lastDownload:
- self.preload()
-
- self.checkErrors()
- self.checkStatus(getinfo=False)
-
- if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()):
- self.logDebug("Handled as premium download")
- self.handlePremium(pyfile)
-
- elif not self.LOGIN_ACCOUNT or (not self.CHECK_TRAFFIC or self.checkTrafficLeft()):
- self.logDebug("Handled as free download")
- self.handleFree(pyfile)
-
- self.downloadLink(self.link, True)
- self.checkFile()
-
-
- def handlePremium(self, pyfile):
- return self.handleFree(pyfile)
-
-
- def handleFree(self, pyfile):
- if self.premium:
- raise NotImplementedError
- else:
- self.fail(_("Required premium account not found"))
diff --git a/module/plugins/internal/SevenZip.py b/module/plugins/internal/SevenZip.py
deleted file mode 100644
index 7ad6b0d7a..000000000
--- a/module/plugins/internal/SevenZip.py
+++ /dev/null
@@ -1,155 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import os
-import re
-
-from subprocess import Popen, PIPE
-
-from module.plugins.internal.UnRar import ArchiveError, CRCError, PasswordError, UnRar, renice
-from module.utils import fs_encode, save_join
-
-
-class SevenZip(UnRar):
- __name__ = "SevenZip"
- __version__ = "0.08"
-
- __description__ = """7-Zip extractor plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Michael Nowak", ""),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- CMD = "7z"
- VERSION = ""
-
- EXTENSIONS = [".7z", ".xz", ".zip", ".gz", ".gzip", ".tgz", ".bz2", ".bzip2",
- ".tbz2", ".tbz", ".tar", ".wim", ".swm", ".lzma", ".rar", ".cab",
- ".arj", ".z", ".taz", ".cpio", ".rpm", ".deb", ".lzh", ".lha",
- ".chm", ".chw", ".hxs", ".iso", ".msi", ".doc", ".xls", ".ppt",
- ".dmg", ".xar", ".hfs", ".exe", ".ntfs", ".fat", ".vhd", ".mbr",
- ".squashfs", ".cramfs", ".scap"]
-
-
- #@NOTE: there are some more uncovered 7z formats
- re_filelist = re.compile(r'([\d\:]+)\s+([\d\:]+)\s+([\w\.]+)\s+(\d+)\s+(\d+)\s+(.+)')
- re_wrongpwd = re.compile(r'(Can not open encrypted archive|Wrong password)', re.I)
- re_wrongcrc = re.compile(r'Encrypted\s+\=\s+\+', re.I)
- re_version = re.compile(r'7-Zip\s(?:\[64\]\s)?(\d+\.\d+)', re.I)
-
-
- @classmethod
- def isUsable(cls):
- if os.name == "nt":
- cls.CMD = os.path.join(pypath, "7z.exe")
- p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE)
- out,err = p.communicate()
- else:
- p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE)
- out, err = p.communicate()
-
- cls.VERSION = cls.re_version.search(out).group(1)
-
- return True
-
-
- def check(self):
- file = fs_encode(self.filename)
-
- p = self.call_cmd("t", file)
- out, err = p.communicate()
-
- if p.returncode > 1:
- raise CRCError(err)
-
- p = self.call_cmd("l", "-slt", file)
- out, err = p.communicate()
-
- if p.returncode > 1:
- raise ArchiveError(_("Process return code: %d") % p.returncode)
-
- # check if output or error macthes the 'wrong password'-Regexp
- if self.re_wrongpwd.search(out):
- raise PasswordError
-
- # check if output matches 'Encrypted = +'
- if self.re_wrongcrc.search(out):
- raise CRCError(_("Header protected"))
-
-
- def isPassword(self, password):
- p = self.call_cmd("l", fs_encode(self.filename), password=password)
- p.communicate()
- return p.returncode == 0
-
-
- def repair(self):
- return False
-
-
- def extract(self, password=None):
- command = "x" if self.fullpath else "e"
-
- p = self.call_cmd(command, '-o' + self.out, fs_encode(self.filename), password=password)
-
- renice(p.pid, self.renice)
-
- # communicate and retrieve stderr
- self._progress(p)
- err = p.stderr.read().strip()
-
- if err:
- if self.re_wrongpwd.search(err):
- raise PasswordError
-
- elif self.re_wrongcrc.search(err):
- raise CRCError(err)
-
- else: #: raise error if anything is on stderr
- raise ArchiveError(err)
-
- if p.returncode > 1:
- raise ArchiveError(_("Process return code: %d") % p.returncode)
-
- self.files = self.list(password)
-
-
- def list(self, password=None):
- command = "l" if self.fullpath else "l"
-
- p = self.call_cmd(command, fs_encode(self.filename), password=password)
- out, err = p.communicate()
-
- if "Can not open" in err:
- raise ArchiveError(_("Cannot open file"))
-
- if p.returncode > 1:
- raise ArchiveError(_("Process return code: %d") % p.returncode)
-
- result = set()
- for groups in self.re_filelist.findall(out):
- f = groups[-1].strip()
- result.add(save_join(self.out, f))
-
- return list(result)
-
-
- def call_cmd(self, command, *xargs, **kwargs):
- args = []
-
- #overwrite flag
- if self.overwrite:
- args.append("-y")
-
- #set a password
- if "password" in kwargs and kwargs["password"]:
- args.append("-p'%s'" % kwargs["password"])
- else:
- args.append("-p-")
-
- #@NOTE: return codes are not reliable, some kind of threading, cleanup whatever issue
- call = [self.CMD, command] + args + list(xargs)
-
- self.manager.logDebug(" ".join(call))
-
- p = Popen(call, stdout=PIPE, stderr=PIPE)
- return p
diff --git a/module/plugins/internal/SimpleCrypter.py b/module/plugins/internal/SimpleCrypter.py
deleted file mode 100644
index dc34f864f..000000000
--- a/module/plugins/internal/SimpleCrypter.py
+++ /dev/null
@@ -1,157 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urlparse import urljoin, urlparse
-
-from pyload.plugin.Crypter import Crypter
-from pyload.plugin.internal.SimpleHoster import SimpleHoster, create_getInfo, replace_patterns, set_cookies
-from pyload.utils import fixup
-
-
-class SimpleCrypter(Crypter, SimpleHoster):
- __name__ = "SimpleCrypter"
- __type__ = "crypter"
- __version__ = "0.43"
-
- __pattern__ = r'^unmatchable$'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), #: Overrides core.config['general']['folder_per_package']
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Simple decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("stickell", "l.stickell@yahoo.it"),
- ("zoidberg", "zoidberg@mujmail.cz"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- """
- Following patterns should be defined by each crypter:
-
- LINK_PATTERN: Download link or regex to catch links in group(1)
- example: LINK_PATTERN = r'<div class="link"><a href="(.+?)"'
-
- NAME_PATTERN: (optional) folder name or page title
- example: NAME_PATTERN = r'<title>Files of: (?P<N>[^<]+) folder</title>'
-
- OFFLINE_PATTERN: (optional) Checks if the page is unreachable
- example: OFFLINE_PATTERN = r'File (deleted|not found)'
-
- TEMP_OFFLINE_PATTERN: (optional) Checks if the page is temporarily unreachable
- example: TEMP_OFFLINE_PATTERN = r'Server maintainance'
-
-
- You can override the getLinks method if you need a more sophisticated way to extract the links.
-
-
- If the links are splitted on multiple pages you can define the PAGES_PATTERN regex:
-
- PAGES_PATTERN: (optional) group(1) should be the number of overall pages containing the links
- example: PAGES_PATTERN = r'Pages: (\d+)'
-
- and its loadPage method:
-
-
- def loadPage(self, page_n):
- return the html of the page number page_n
- """
-
- LINK_PATTERN = None
-
- NAME_REPLACEMENTS = [("&#?\w+;", fixup)]
- URL_REPLACEMENTS = []
-
- TEXT_ENCODING = False #: Set to True or encoding name if encoding in http header is not correct
- COOKIES = True #: or False or list of tuples [(domain, name, value)]
-
- LOGIN_ACCOUNT = False
- LOGIN_PREMIUM = False
-
-
- def prepare(self):
- self.pyfile.error = "" #@TODO: Remove in 0.4.10
-
- self.info = {}
- self.html = ""
- self.links = [] #@TODO: Move to hoster class in 0.4.10
-
- if self.LOGIN_PREMIUM and not self.premium:
- self.fail(_("Required premium account not found"))
-
- if self.LOGIN_ACCOUNT and not self.account:
- self.fail(_("Required account not found"))
-
- self.req.setOption("timeout", 120)
-
- if isinstance(self.COOKIES, list):
- set_cookies(self.req.cj, self.COOKIES)
-
- self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS)
-
-
- def decrypt(self, pyfile):
- self.prepare()
-
- self.preload()
- self.checkInfo()
-
- self.links = self.getLinks()
-
- if hasattr(self, 'PAGES_PATTERN') and hasattr(self, 'loadPage'):
- self.handlePages(pyfile)
-
- self.logDebug("Package has %d links" % len(self.links))
-
- if self.links:
- self.packages = [(self.info['name'], self.links, self.info['folder'])]
-
- elif not self.urls and not self.packages: #@TODO: Remove in 0.4.10
- self.fail(_("No link grabbed"))
-
-
- def checkNameSize(self, getinfo=True):
- if not self.info or getinfo:
- self.logDebug("File info (BEFORE): %s" % self.info)
- self.info.update(self.getInfo(self.pyfile.url, self.html))
- self.logDebug("File info (AFTER): %s" % self.info)
-
- try:
- url = self.info['url'].strip()
- name = self.info['name'].strip()
- if name and name != url:
- self.pyfile.name = name
-
- except Exception:
- pass
-
- try:
- folder = self.info['folder'] = self.pyfile.name
-
- except Exception:
- pass
-
- self.logDebug("File name: %s" % self.pyfile.name,
- "File folder: %s" % self.pyfile.name)
-
-
- def getLinks(self):
- """
- Returns the links extracted from self.html
- You should override this only if it's impossible to extract links using only the LINK_PATTERN.
- """
- url_p = urlparse(self.pyfile.url)
- baseurl = "%s://%s" % (url_p.scheme, url_p.netloc)
-
- return [urljoin(baseurl, link) if not urlparse(link).scheme else link \
- for link in re.findall(self.LINK_PATTERN, self.html)]
-
-
- def handlePages(self, pyfile):
- try:
- pages = int(re.search(self.PAGES_PATTERN, self.html).group(1))
- except Exception:
- pages = 1
-
- for p in xrange(2, pages + 1):
- self.html = self.loadPage(p)
- self.links += self.getLinks()
diff --git a/module/plugins/internal/SimpleDereferer.py b/module/plugins/internal/SimpleDereferer.py
deleted file mode 100644
index bd00f5d25..000000000
--- a/module/plugins/internal/SimpleDereferer.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from urllib import unquote
-
-from module.plugins.Crypter import Crypter
-from module.plugins.internal.SimpleHoster import fileUrl, set_cookies
-
-
-class SimpleDereferer(Crypter):
- __name__ = "SimpleDereferer"
- __type__ = "crypter"
- __version__ = "0.07"
-
- __pattern__ = r'^unmatchable$'
- __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
- ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
-
- __description__ = """Simple dereferer plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- """
- Following patterns should be defined by each crypter:
-
- LINK_PATTERN: Regex to catch the redirect url in group(1)
- example: LINK_PATTERN = r'<div class="link"><a href="(.+?)"'
-
- OFFLINE_PATTERN: (optional) Checks if the page is unreachable
- example: OFFLINE_PATTERN = r'File (deleted|not found)'
-
- TEMP_OFFLINE_PATTERN: (optional) Checks if the page is temporarily unreachable
- example: TEMP_OFFLINE_PATTERN = r'Server maintainance'
-
-
- You can override the getLinks method if you need a more sophisticated way to extract the redirect url.
- """
-
- LINK_PATTERN = None
-
- TEXT_ENCODING = False
- COOKIES = True
-
-
- def decrypt(self, pyfile):
- link = fileUrl(self, pyfile.url)
-
- if not link:
- try:
- link = unquote(re.match(self.__pattern__, pyfile.url).group('LINK'))
-
- except Exception:
- self.prepare()
- self.preload()
- self.checkStatus()
-
- link = self.getLink()
-
- if link.strip():
- self.urls = [link.strip()] #@TODO: Remove `.strip()` in 0.4.10
-
- elif not self.urls and not self.packages: #@TODO: Remove in 0.4.10
- self.fail(_("No link grabbed"))
-
-
- def prepare(self):
- self.info = {}
- self.html = ""
-
- self.req.setOption("timeout", 120)
-
- if isinstance(self.COOKIES, list):
- set_cookies(self.req.cj, self.COOKIES)
-
-
- def preload(self):
- self.html = self.load(self.pyfile.url, cookies=bool(self.COOKIES), decode=not self.TEXT_ENCODING)
-
- if isinstance(self.TEXT_ENCODING, basestring):
- self.html = unicode(self.html, self.TEXT_ENCODING)
-
-
- def checkStatus(self):
- if hasattr(self, "OFFLINE_PATTERN") and re.search(self.OFFLINE_PATTERN, self.html):
- self.offline()
-
- elif hasattr(self, "TEMP_OFFLINE_PATTERN") and re.search(self.TEMP_OFFLINE_PATTERN, self.html):
- self.tempOffline()
-
-
- def getLink(self):
- try:
- return re.search(self.LINK_PATTERN, self.html).group(1)
-
- except Exception:
- pass
diff --git a/module/plugins/internal/SimpleHoster.py b/module/plugins/internal/SimpleHoster.py
deleted file mode 100644
index e4ff1a2d8..000000000
--- a/module/plugins/internal/SimpleHoster.py
+++ /dev/null
@@ -1,701 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import mimetypes
-import os
-import re
-
-from datetime import datetime, timedelta
-from inspect import isclass
-from time import time
-from urllib import unquote
-from urlparse import urljoin, urlparse
-
-from module.PyFile import statusMap as _statusMap
-from module.network.CookieJar import CookieJar
-from module.network.HTTPRequest import BadHeader
-from module.network.RequestFactory import getURL
-from module.plugins.Hoster import Hoster
-from module.plugins.Plugin import Fail
-from module.utils import fixup, fs_encode, parseFileSize
-
-
-#@TODO: Adapt and move to PyFile in 0.4.10
-statusMap = dict((v, k) for k, v in _statusMap.iteritems())
-
-
-#@TODO: Remove in 0.4.10 and redirect to self.error instead
-def _error(self, reason, type):
- if not reason and not type:
- type = "unknown"
-
- msg = _("%s error") % type.strip().capitalize() if type else _("Error")
- msg += ": %s" % reason.strip() if reason else ""
- msg += _(" | Plugin may be out of date")
-
- raise Fail(msg)
-
-
-#@TODO: Remove in 0.4.10
-def _wait(self, seconds, reconnect):
- if seconds:
- self.setWait(int(seconds) + 1)
-
- if reconnect is not None:
- self.wantReconnect = reconnect
-
- super(SimpleHoster, self).wait()
-
-
-def replace_patterns(string, ruleslist):
- for r in ruleslist:
- rf, rt = r
- string = re.sub(rf, rt, string)
- return string
-
-
-def set_cookies(cj, cookies):
- for cookie in cookies:
- if isinstance(cookie, tuple) and len(cookie) == 3:
- domain, name, value = cookie
- cj.setCookie(domain, name, value)
-
-
-def parseHtmlTagAttrValue(attr_name, tag):
- m = re.search(r"%s\s*=\s*([\"']?)((?<=\")[^\"]+|(?<=')[^']+|[^>\s\"'][^>\s]*)\1" % attr_name, tag, re.I)
- return m.group(2) if m else None
-
-
-def parseHtmlForm(attr_str, html, input_names={}):
- for form in re.finditer(r"(?P<TAG><form[^>]*%s[^>]*>)(?P<CONTENT>.*?)</?(form|body|html)[^>]*>" % attr_str,
- html, re.S | re.I):
- inputs = {}
- action = parseHtmlTagAttrValue("action", form.group('TAG'))
-
- for inputtag in re.finditer(r'(<(input|textarea)[^>]*>)([^<]*(?=</\2)|)', form.group('CONTENT'), re.S | re.I):
- name = parseHtmlTagAttrValue("name", inputtag.group(1))
- if name:
- value = parseHtmlTagAttrValue("value", inputtag.group(1))
- if not value:
- inputs[name] = inputtag.group(3) or ''
- else:
- inputs[name] = value
-
- if input_names:
- # check input attributes
- for key, val in input_names.iteritems():
- if key in inputs:
- if isinstance(val, basestring) and inputs[key] == val:
- continue
- elif isinstance(val, tuple) and inputs[key] in val:
- continue
- elif hasattr(val, "search") and re.match(val, inputs[key]):
- continue
- break #: attibute value does not match
- else:
- break #: attibute name does not match
- else:
- return action, inputs #: passed attribute check
- else:
- # no attribute check
- return action, inputs
-
- return {}, None #: no matching form found
-
-
-#: Deprecated
-def parseFileInfo(plugin, url="", html=""):
- if hasattr(plugin, "getInfo"):
- info = plugin.getInfo(url, html)
- res = info['name'], info['size'], info['status'], info['url']
- else:
- url = unquote(url)
- url_p = urlparse(url)
- res = ((url_p.path.split('/')[-1]
- or url_p.query.split('=', 1)[::-1][0].split('&', 1)[0]
- or url_p.netloc.split('.', 1)[0]),
- 0,
- 3 if url else 8,
- url)
-
- return res
-
-
-#@TODO: Remove in 0.4.10
-#@NOTE: Every plugin must have own parseInfos classmethod to work with 0.4.10
-def create_getInfo(plugin):
-
- def generator(list):
- for x in list:
- yield x
-
- if hasattr(plugin, "parseInfos"):
- fn = lambda urls: generator((info['name'], info['size'], info['status'], info['url']) for info in plugin.parseInfos(urls))
- else:
- fn = lambda urls: generator(parseFileInfo(url) for url in urls)
-
- return fn
-
-
-def timestamp():
- return int(time() * 1000)
-
-
-#@TODO: Move to hoster class in 0.4.10
-def fileUrl(self, url, follow_location=None):
- link = ""
- redirect = 1
-
- if type(follow_location) is int:
- redirect = max(follow_location, 1)
- else:
- redirect = 5
-
- for i in xrange(redirect):
- try:
- self.logDebug("Redirect #%d to: %s" % (i, url))
- header = self.load(url, ref=True, cookies=True, just_header=True, decode=True)
-
- except Exception: #: Bad bad bad...
- req = pyreq.getHTTPRequest()
- res = req.load(url, cookies=True, just_header=True, decode=True)
-
- req.close()
-
- header = {"code": req.code}
- for line in res.splitlines():
- line = line.strip()
- if not line or ":" not in line:
- continue
-
- key, none, value = line.partition(":")
- key = key.lower().strip()
- value = value.strip()
-
- if key in header:
- if type(header[key]) == list:
- header[key].append(value)
- else:
- header[key] = [header[key], value]
- else:
- header[key] = value
-
- if 'content-disposition' in header:
- link = url
-
- elif 'location' in header and header['location'].strip():
- location = header['location']
-
- if not urlparse(location).scheme:
- url_p = urlparse(url)
- baseurl = "%s://%s" % (url_p.scheme, url_p.netloc)
- location = urljoin(baseurl, location)
-
- if 'code' in header and header['code'] == 302:
- link = location
-
- if follow_location:
- url = location
- continue
-
- else:
- extension = os.path.splitext(urlparse(url).path.split('/')[-1])[-1]
-
- if 'content-type' in header and header['content-type'].strip():
- mimetype = header['content-type'].split(';')[0].strip()
-
- elif extension:
- mimetype = mimetypes.guess_type(extension, False)[0] or "application/octet-stream"
-
- else:
- mimetype = ""
-
- if mimetype and (link or 'html' not in mimetype):
- link = url
- else:
- link = ""
-
- break
-
- else:
- try:
- self.logError(_("Too many redirects"))
- except Exception:
- pass
-
- return link
-
-
-def secondsToMidnight(gmt=0):
- now = datetime.utcnow() + timedelta(hours=gmt)
-
- if now.hour is 0 and now.minute < 10:
- midnight = now
- else:
- midnight = now + timedelta(days=1)
-
- td = midnight.replace(hour=0, minute=10, second=0, microsecond=0) - now
-
- if hasattr(td, 'total_seconds'):
- res = td.total_seconds()
- else: #@NOTE: work-around for python 2.5 and 2.6 missing timedelta.total_seconds
- res = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
-
- return int(res)
-
-
-class SimpleHoster(Hoster):
- __name__ = "SimpleHoster"
- __type__ = "hoster"
- __version__ = "1.15"
-
- __pattern__ = r'^unmatchable$'
-
- __description__ = """Simple hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
- ("stickell", "l.stickell@yahoo.it"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- """
- Info patterns should be defined by each hoster:
-
- INFO_PATTERN: (optional) Name and Size of the file
- example: INFO_PATTERN = r'(?P<N>file_name) (?P<S>file_size) (?P<U>size_unit)'
- or
- NAME_PATTERN: (optional) Name that will be set for the file
- example: NAME_PATTERN = r'(?P<N>file_name)'
- SIZE_PATTERN: (optional) Size that will be checked for the file
- example: SIZE_PATTERN = r'(?P<S>file_size) (?P<U>size_unit)'
-
- HASHSUM_PATTERN: (optional) Hash code and type of the file
- example: HASHSUM_PATTERN = r'(?P<H>hash_code) (?P<T>MD5)'
-
- OFFLINE_PATTERN: (optional) Check if the page is unreachable
- example: OFFLINE_PATTERN = r'File (deleted|not found)'
-
- TEMP_OFFLINE_PATTERN: (optional) Check if the page is temporarily unreachable
- example: TEMP_OFFLINE_PATTERN = r'Server (maintenance|maintainance)'
-
-
- Error handling patterns are all optional:
-
- WAIT_PATTERN: (optional) Detect waiting time
- example: WAIT_PATTERN = r''
-
- PREMIUM_ONLY_PATTERN: (optional) Check if the file can be downloaded only with a premium account
- example: PREMIUM_ONLY_PATTERN = r'Premium account required'
-
- ERROR_PATTERN: (optional) Detect any error preventing download
- example: ERROR_PATTERN = r''
-
-
- Instead overriding handleFree and handlePremium methods you can define the following patterns for direct download:
-
- LINK_FREE_PATTERN: (optional) group(1) should be the direct link for free download
- example: LINK_FREE_PATTERN = r'<div class="link"><a href="(.+?)"'
-
- LINK_PREMIUM_PATTERN: (optional) group(1) should be the direct link for premium download
- example: LINK_PREMIUM_PATTERN = r'<div class="link"><a href="(.+?)"'
- """
-
- NAME_REPLACEMENTS = [("&#?\w+;", fixup)]
- SIZE_REPLACEMENTS = []
- URL_REPLACEMENTS = []
-
- TEXT_ENCODING = False #: Set to True or encoding name if encoding value in http header is not correct
- COOKIES = True #: or False or list of tuples [(domain, name, value)]
- CHECK_TRAFFIC = False #: Set to True to force checking traffic left for premium account
- DIRECT_LINK = None #: Set to True to looking for direct link (as defined in handleDirect method), set to None to do it if self.account is True else False
- MULTI_HOSTER = False #: Set to True to leech other hoster link (as defined in handleMulti method)
- LOGIN_ACCOUNT = False #: Set to True to require account login
- DISPOSITION = True #: Work-around to `filename*=UTF-8` bug; remove in 0.4.10
-
- directLink = fileUrl #@TODO: Remove in 0.4.10
-
-
- @classmethod
- def parseInfos(cls, urls): #@TODO: Built-in in 0.4.10 core, then remove from plugins
- for url in urls:
- url = replace_patterns(url, cls.URL_REPLACEMENTS)
- yield cls.getInfo(url)
-
-
- @classmethod
- def apiInfo(cls, url="", get={}, post={}):
- url = unquote(url)
- url_p = urlparse(url)
- return {'name' : (url_p.path.split('/')[-1]
- or url_p.query.split('=', 1)[::-1][0].split('&', 1)[0]
- or url_p.netloc.split('.', 1)[0]),
- 'size' : 0,
- 'status': 3 if url else 8,
- 'url' : url}
-
-
- @classmethod
- def getInfo(cls, url="", html=""):
- info = cls.apiInfo(url)
- online = False if info['status'] != 2 else True
-
- try:
- info['pattern'] = re.match(cls.__pattern__, url).groupdict() #: pattern groups will be saved here
-
- except Exception:
- info['pattern'] = {}
-
- if not html and not online:
- if not url:
- info['error'] = "missing url"
- info['status'] = 1
-
- elif info['status'] is 3 and not fileUrl(None, url):
- try:
- html = getURL(url, cookies=cls.COOKIES, decode=not cls.TEXT_ENCODING)
-
- if isinstance(cls.TEXT_ENCODING, basestring):
- html = unicode(html, cls.TEXT_ENCODING)
-
- except BadHeader, e:
- info['error'] = "%d: %s" % (e.code, e.content)
-
- if e.code is 404:
- info['status'] = 1
-
- elif e.code is 503:
- info['status'] = 6
-
- if html:
- if hasattr(cls, "OFFLINE_PATTERN") and re.search(cls.OFFLINE_PATTERN, html):
- info['status'] = 1
-
- elif hasattr(cls, "TEMP_OFFLINE_PATTERN") and re.search(cls.TEMP_OFFLINE_PATTERN, html):
- info['status'] = 6
-
- else:
- for pattern in ("INFO_PATTERN", "NAME_PATTERN", "SIZE_PATTERN", "HASHSUM_PATTERN"):
- try:
- attr = getattr(cls, pattern)
- pdict = re.search(attr, html).groupdict()
-
- if all(True for k in pdict if k not in info['pattern']):
- info['pattern'].update(pdict)
-
- except AttributeError:
- continue
-
- else:
- online = True
-
- if online:
- info['status'] = 2
-
- if 'N' in info['pattern']:
- info['name'] = replace_patterns(unquote(info['pattern']['N'].strip()),
- cls.NAME_REPLACEMENTS)
-
- if 'S' in info['pattern']:
- size = replace_patterns(info['pattern']['S'] + info['pattern']['U'] if 'U' in info['pattern'] else info['pattern']['S'],
- cls.SIZE_REPLACEMENTS)
- info['size'] = parseFileSize(size)
-
- elif isinstance(info['size'], basestring):
- unit = info['units'] if 'units' in info else None
- info['size'] = parseFileSize(info['size'], unit)
-
- if 'H' in info['pattern']:
- hashtype = info['pattern']['T'] if 'T' in info['pattern'] else "hash"
- info[hashtype] = info['pattern']['H']
-
- if not info['pattern']:
- info.pop('pattern', None)
-
- return info
-
-
- def setup(self):
- self.resumeDownload = self.multiDL = self.premium
-
-
- def prepare(self):
- self.pyfile.error = "" #@TODO: Remove in 0.4.10
-
- self.info = {}
- self.html = ""
- self.link = "" #@TODO: Move to hoster class in 0.4.10
- self.directDL = False #@TODO: Move to hoster class in 0.4.10
- self.multihost = False #@TODO: Move to hoster class in 0.4.10
-
- if self.LOGIN_ACCOUNT and not self.account:
- self.fail(_("Required account not found"))
-
- self.req.setOption("timeout", 120)
-
- if isinstance(self.COOKIES, list):
- set_cookies(self.req.cj, self.COOKIES)
-
- if (self.MULTI_HOSTER
- and (self.__pattern__ != self.core.pluginManager.hosterPlugins[self.__name__]['pattern']
- or re.match(self.__pattern__, self.pyfile.url) is None)):
- self.multihost = True
- return
-
- if self.DIRECT_LINK is None:
- self.directDL = bool(self.account)
- else:
- self.directDL = self.DIRECT_LINK
-
- self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS)
-
-
- def preload(self):
- self.html = self.load(self.pyfile.url, cookies=bool(self.COOKIES), decode=not self.TEXT_ENCODING)
-
- if isinstance(self.TEXT_ENCODING, basestring):
- self.html = unicode(self.html, self.TEXT_ENCODING)
-
-
- def process(self, pyfile):
- self.prepare()
- self.checkInfo()
-
- if self.directDL:
- self.logDebug("Looking for direct download link...")
- self.handleDirect(pyfile)
-
- if self.multihost and not self.link and not self.lastDownload:
- self.logDebug("Looking for leeched download link...")
- self.handleMulti(pyfile)
-
- if not self.link and not self.lastDownload:
- self.MULTI_HOSTER = False
- self.retry(1, reason="Multi hoster fails")
-
- if not self.link and not self.lastDownload:
- self.preload()
- self.checkInfo()
-
- if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()):
- self.logDebug("Handled as premium download")
- self.handlePremium(pyfile)
-
- elif not self.LOGIN_ACCOUNT or (not self.CHECK_TRAFFIC or self.checkTrafficLeft()):
- self.logDebug("Handled as free download")
- self.handleFree(pyfile)
-
- self.downloadLink(self.link, self.DISPOSITION) #: Remove `self.DISPOSITION` in 0.4.10
- self.checkFile()
-
-
- def downloadLink(self, link, disposition=True):
- if link and isinstance(link, basestring):
- self.correctCaptcha()
-
- if not urlparse(link).scheme:
- url_p = urlparse(self.pyfile.url)
- baseurl = "%s://%s" % (url_p.scheme, url_p.netloc)
- link = urljoin(baseurl, link)
-
- self.download(link, ref=False, disposition=disposition)
-
-
- def checkFile(self):
- if self.cTask and not self.lastDownload:
- self.invalidCaptcha()
- self.retry(10, reason=_("Wrong captcha"))
-
- elif not self.lastDownload or not os.path.exists(fs_encode(self.lastDownload)):
- self.lastDownload = ""
- self.error(self.pyfile.error or _("No file downloaded"))
-
- else:
- rules = {'empty file': re.compile(r'\A\Z'),
- 'html file' : re.compile(r'\A\s*<!DOCTYPE html'),
- 'html error': re.compile(r'\A\s*(<.+>)?\d{3}(\Z|\s+)')}
-
- if hasattr(self, 'ERROR_PATTERN'):
- rules['error'] = re.compile(self.ERROR_PATTERN)
-
- check = self.checkDownload(rules)
- if check: #@TODO: Move to hoster in 0.4.10
- errmsg = check.strip().capitalize()
- if self.lastCheck:
- errmsg += " | " + self.lastCheck.group(0).strip()
-
- self.lastDownload = ""
- self.retry(10, 60, errmsg)
-
-
- def checkErrors(self):
- if not self.html:
- self.logWarning(_("No html code to check"))
- return
-
- if hasattr(self, 'PREMIUM_ONLY_PATTERN') and not self.premium and re.search(self.PREMIUM_ONLY_PATTERN, self.html):
- self.fail(_("Link require a premium account to be handled"))
-
- elif hasattr(self, 'ERROR_PATTERN'):
- m = re.search(self.ERROR_PATTERN, self.html)
- if m:
- errmsg = self.info['error'] = m.group(1)
- self.error(errmsg)
-
- elif hasattr(self, 'WAIT_PATTERN'):
- m = re.search(self.WAIT_PATTERN, self.html)
- if m:
- wait_time = sum(int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1}[u.lower()] for v, u in
- re.findall(r'(\d+)\s*(hr|hour|min|sec)', m.group(0), re.I))
- self.wait(wait_time, wait_time > 300)
- return
-
- self.info.pop('error', None)
-
-
- def checkStatus(self, getinfo=True):
- if not self.info or getinfo:
- self.logDebug("Update file info...")
- self.logDebug("Previous file info: %s" % self.info)
- self.info.update(self.getInfo(self.pyfile.url, self.html))
- self.logDebug("Current file info: %s" % self.info)
-
- try:
- status = self.info['status']
-
- if status is 1:
- self.offline()
-
- elif status is 6:
- self.tempOffline()
-
- elif status is 8:
- self.fail()
-
- finally:
- self.logDebug("File status: %s" % statusMap[status])
-
-
- def checkNameSize(self, getinfo=True):
- if not self.info or getinfo:
- self.logDebug("Update file info...")
- self.logDebug("Previous file info: %s" % self.info)
- self.info.update(self.getInfo(self.pyfile.url, self.html))
- self.logDebug("Current file info: %s" % self.info)
-
- try:
- url = self.info['url'].strip()
- name = self.info['name'].strip()
- if name and name != url:
- self.pyfile.name = name
-
- except Exception:
- pass
-
- try:
- size = self.info['size']
- if size > 0:
- self.pyfile.size = size
-
- except Exception:
- pass
-
- self.logDebug("File name: %s" % self.pyfile.name,
- "File size: %s byte" % self.pyfile.size if self.pyfile.size > 0 else "File size: Unknown")
-
-
- def checkInfo(self):
- self.checkNameSize()
-
- if self.html:
- self.checkErrors()
- self.checkNameSize()
-
- self.checkStatus(getinfo=False)
-
-
- #: Deprecated
- def getFileInfo(self):
- self.info = {}
- self.checkInfo()
- return self.info
-
-
- def handleDirect(self, pyfile):
- link = self.directLink(pyfile.url, self.resumeDownload)
-
- if link:
- self.logInfo(_("Direct download link detected"))
-
- self.link = link
- else:
- self.logDebug("Direct download link not found")
-
-
- def handleMulti(self, pyfile): #: Multi-hoster handler
- pass
-
-
- def handleFree(self, pyfile):
- if not hasattr(self, 'LINK_FREE_PATTERN'):
- self.logError(_("Free download not implemented"))
-
- m = re.search(self.LINK_FREE_PATTERN, self.html)
- if m is None:
- self.error(_("Free download link not found"))
- else:
- self.link = m.group(1)
-
-
- def handlePremium(self, pyfile):
- if not hasattr(self, 'LINK_PREMIUM_PATTERN'):
- self.logError(_("Premium download not implemented"))
- self.logDebug("Handled as free download")
- self.handleFree(pyfile)
-
- m = re.search(self.LINK_PREMIUM_PATTERN, self.html)
- if m is None:
- self.error(_("Premium download link not found"))
- else:
- self.link = m.group(1)
-
-
- def longWait(self, wait_time=None, max_tries=3):
- if wait_time and isinstance(wait_time, (int, long, float)):
- time_str = "%dh %dm" % divmod(wait_time / 60, 60)
- else:
- wait_time = 900
- time_str = _("(unknown time)")
- max_tries = 100
-
- self.logInfo(_("Download limit reached, reconnect or wait %s") % time_str)
-
- self.wait(wait_time, True)
- self.retry(max_tries=max_tries, reason=_("Download limit reached"))
-
-
- def parseHtmlForm(self, attr_str="", input_names={}):
- return parseHtmlForm(attr_str, self.html, input_names)
-
-
- def checkTrafficLeft(self):
- if not self.account:
- return True
-
- traffic = self.account.getAccountInfo(self.user, True)['trafficleft']
-
- if traffic is None:
- return False
- elif traffic == -1:
- return True
- else:
- size = self.pyfile.size / 1024
- self.logInfo(_("Filesize: %i KiB, Traffic left for user %s: %i KiB") % (size, self.user, traffic))
- return size <= traffic
-
-
- #@TODO: Remove in 0.4.10
- def wait(self, seconds=0, reconnect=None):
- return _wait(self, seconds, reconnect)
-
-
- def error(self, reason="", type="parse"):
- return _error(self, reason, type)
diff --git a/module/plugins/internal/UnRar.py b/module/plugins/internal/UnRar.py
deleted file mode 100644
index 54d64c430..000000000
--- a/module/plugins/internal/UnRar.py
+++ /dev/null
@@ -1,248 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import os
-import re
-
-from glob import glob
-from string import digits
-from subprocess import Popen, PIPE
-
-from module.plugins.internal.Extractor import Extractor, ArchiveError, CRCError, PasswordError
-from module.utils import decode, fs_encode, save_join
-
-
-def renice(pid, value):
- if value and os.name != "nt":
- try:
- Popen(["renice", str(value), str(pid)], stdout=PIPE, stderr=PIPE, bufsize=-1)
-
- except Exception:
- pass
-
-
-class UnRar(Extractor):
- __name__ = "UnRar"
- __version__ = "1.13"
-
- __description__ = """Rar extractor plugin"""
- __license__ = "GPLv3"
- __authors__ = [("RaNaN", "RaNaN@pyload.org"),
- ("Walter Purcaro", "vuolter@gmail.com"),
- ("Immenz", "immenz@gmx.net"),]
-
-
- CMD = "unrar"
- VERSION = ""
-
- EXTENSIONS = [".rar"]
-
-
- re_multipart = re.compile(r'\.(part|r)(\d+)(?:\.rar)?',re.I)
-
- re_filefixed = re.compile(r'Building (.+)')
- re_filelist = re.compile(r'^(.)(\s*[\w\.\-]+)\s+(\d+\s+)+(?:\d+\%\s+)?[\d\-]{8}\s+[\d\:]{5}', re.M|re.I)
-
- re_wrongpwd = re.compile(r'password', re.I)
- re_wrongcrc = re.compile(r'encrypted|damaged|CRC failed|checksum error', re.I)
-
- re_version = re.compile(r'UNRAR\s(\d+\.\d+)', re.I)
-
-
- @classmethod
- def isUsable(cls):
- if os.name == "nt":
- cls.CMD = os.path.join(pypath, "UnRAR.exe")
- p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE)
- out, err = p.communicate()
- else:
- try:
- p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE)
- out, err = p.communicate()
-
- except OSError: #: fallback to rar
- cls.CMD = "rar"
- p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE)
- out, err = p.communicate()
-
- cls.VERSION = cls.re_version.search(out).group(1)
-
- return True
-
-
- @classmethod
- def isMultipart(cls,filename):
- multipart = cls.re_multipart.search(filename)
- if multipart:
- # First Multipart file (part1.rar for *.part1-9.rar format or *.rar for .r1-9 format) handled as normal Archive
- return False if (multipart.group(1) == "part" and int(multipart.group(2)) == 1) else True
-
- return False
-
-
- def check(self):
- p = self.call_cmd("l", "-v", fs_encode(self.filename))
- out, err = p.communicate()
-
- if self.re_wrongpwd.search(err):
- raise PasswordError
-
- if self.re_wrongcrc.search(err):
- raise CRCError(err)
-
- # output only used to check if passworded files are present
- for attr in self.re_filelist.findall(out):
- if attr[0].startswith("*"):
- raise PasswordError
-
-
- def isPassword(self, password):
- # at this point we can only verify header protected files
- p = self.call_cmd("l", "-v", fs_encode(self.filename), password=password)
- out, err = p.communicate()
- return False if self.re_wrongpwd.search(err) else True
-
-
- def repair(self):
- p = self.call_cmd("rc", fs_encode(self.filename))
-
- # communicate and retrieve stderr
- self._progress(p)
- err = p.stderr.read().strip()
-
- if err or p.returncode:
- p = self.call_cmd("r", fs_encode(self.filename))
-
- # communicate and retrieve stderr
- self._progress(p)
- err = p.stderr.read().strip()
-
- if err or p.returncode:
- return False
- else:
- dir = os.path.dirname(filename)
- name = re_filefixed.search(out).group(1)
-
- self.filename = os.path.join(dir, name)
-
- return True
-
-
- def _progress(self, process):
- s = ""
- while True:
- c = process.stdout.read(1)
- # quit loop on eof
- if not c:
- break
- # reading a percentage sign -> set progress and restart
- if c == '%':
- self.notifyProgress(int(s))
- s = ""
- # not reading a digit -> therefore restart
- elif c not in digits:
- s = ""
- # add digit to progressstring
- else:
- s += c
-
-
- def extract(self, password=None):
- command = "x" if self.fullpath else "e"
-
- p = self.call_cmd(command, fs_encode(self.filename), self.out, password=password)
-
- renice(p.pid, self.renice)
-
- # communicate and retrieve stderr
- self._progress(p)
- err = p.stderr.read().strip()
-
- if err:
- if self.re_wrongpwd.search(err):
- raise PasswordError
-
- elif self.re_wrongcrc.search(err):
- raise CRCError(err)
-
- else: #: raise error if anything is on stderr
- raise ArchiveError(err)
-
- if p.returncode:
- raise ArchiveError(_("Process return code: %d") % p.returncode)
-
- self.files = self.list(password)
-
-
- def getDeleteFiles(self):
- dir, name = os.path.split(self.filename)
-
- # actually extracted file
- files = [self.filename]
-
- # eventually Multipart Files
- files.extend(save_join(dir, os.path.basename(file)) for file in filter(self.isMultipart, os.listdir(dir))
- if re.sub(self.re_multipart,".rar",name) == re.sub(self.re_multipart,".rar",file))
-
- return files
-
-
- def list(self, password=None):
- command = "vb" if self.fullpath else "lb"
-
- p = self.call_cmd(command, "-v", fs_encode(self.filename), password=password)
- out, err = p.communicate()
-
- if "Cannot open" in err:
- raise ArchiveError(_("Cannot open file"))
-
- if err.strip(): #: only log error at this point
- self.manager.logError(err.strip())
-
- result = set()
- if not self.fullpath and self.VERSION.startswith('5'):
- # NOTE: Unrar 5 always list full path
- for f in decode(out).splitlines():
- f = save_join(self.out, os.path.basename(f.strip()))
- if os.path.isfile(f):
- result.add(save_join(self.out, os.path.basename(f)))
- else:
- for f in decode(out).splitlines():
- f = f.strip()
- result.add(save_join(self.out, f))
-
- return list(result)
-
-
- def call_cmd(self, command, *xargs, **kwargs):
- args = []
-
- # overwrite flag
- if self.overwrite:
- args.append("-o+")
- else:
- args.append("-o-")
- if self.delete:
- args.append("-or")
-
- for word in self.excludefiles:
- args.append("-x'%s'" % word.strip())
-
- # assume yes on all queries
- args.append("-y")
-
- # set a password
- if "password" in kwargs and kwargs['password']:
- args.append("-p%s" % kwargs['password'])
- else:
- args.append("-p-")
-
- if self.keepbroken:
- args.append("-kb")
-
- # NOTE: return codes are not reliable, some kind of threading, cleanup whatever issue
- call = [self.CMD, command] + args + list(xargs)
-
- self.manager.logDebug(" ".join(call))
-
- p = Popen(call, stdout=PIPE, stderr=PIPE)
- return p
diff --git a/module/plugins/internal/UnZip.py b/module/plugins/internal/UnZip.py
deleted file mode 100644
index 704b49ca0..000000000
--- a/module/plugins/internal/UnZip.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from __future__ import with_statement
-
-import os
-import sys
-import zipfile
-
-from module.plugins.internal.Extractor import Extractor, ArchiveError, CRCError, PasswordError
-from module.utils import fs_encode
-
-
-class UnZip(Extractor):
- __name__ = "UnZip"
- __version__ = "1.10"
-
- __description__ = """Zip extractor plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- EXTENSIONS = [".zip", ".zip64"]
- VERSION ="(python %s.%s.%s)" % (sys.version_info[0], sys.version_info[1], sys.version_info[2])
-
-
- @classmethod
- def isUsable(cls):
- return sys.version_info[:2] >= (2, 6)
-
-
- def list(self, password=None):
- with zipfile.ZipFile(fs_encode(self.filename), 'r', allowZip64=True) as z:
- z.setpassword(password)
- return z.namelist()
-
-
- def check(self):
- with zipfile.ZipFile(fs_encode(self.filename), 'r', allowZip64=True) as z:
- badfile = z.testzip()
-
- if badfile:
- raise CRCError(badfile)
- else:
- raise PasswordError
-
-
- def extract(self, password=None):
- try:
- with zipfile.ZipFile(fs_encode(self.filename), 'r', allowZip64=True) as z:
- z.setpassword(password)
-
- badfile = z.testzip()
-
- if badfile:
- raise CRCError(badfile)
- else:
- z.extractall(self.out)
-
- except (zipfile.BadZipfile, zipfile.LargeZipFile), e:
- raise ArchiveError(e)
-
- except RuntimeError, e:
- if "encrypted" in e:
- raise PasswordError
- else:
- raise ArchiveError(e)
- else:
- self.files = z.namelist()
diff --git a/module/plugins/internal/UpdateManager.py b/module/plugins/internal/UpdateManager.py
deleted file mode 100644
index 7bbfc0c79..000000000
--- a/module/plugins/internal/UpdateManager.py
+++ /dev/null
@@ -1,300 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-import sys
-
-from operator import itemgetter
-from os import path, remove, stat
-
-from pyload.network.RequestFactory import getURL
-from pyload.plugin.Addon import Expose, Addon, threaded
-from pyload.utils import safe_join
-
-
-class UpdateManager(Addon):
- __name__ = "UpdateManager"
- __type__ = "addon"
- __version__ = "0.40"
-
- __config__ = [("activated" , "bool" , "Activated" , True ),
- ("mode" , "pyLoad + plugins;plugins only", "Check updates for" , "pyLoad + plugins"),
- ("interval" , "int" , "Check interval in hours" , 8 ),
- ("reloadplugins", "bool" , "Monitor plugins for code changes (debug mode only)", True ),
- ("nodebugupdate", "bool" , "Don't check for updates in debug mode" , True )]
-
- __description__ = """Check for updates"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- # event_list = ["pluginConfigChanged"]
-
- SERVER_URL = "http://updatemanager.pyload.org"
- MIN_INTERVAL = 6 * 60 * 60 #: 6h minimum check interval (value is in seconds)
-
-
- def pluginConfigChanged(self, plugin, name, value):
- if name == "interval":
- interval = value * 60 * 60
- if self.MIN_INTERVAL <= interval != self.interval:
- self.core.scheduler.removeJob(self.cb)
- self.interval = interval
- self.initPeriodical()
- else:
- self.logDebug("Invalid interval value, kept current")
-
- elif name == "reloadplugins":
- if self.cb2:
- self.core.scheduler.removeJob(self.cb2)
- if value is True and self.core.debug:
- self.periodical2()
-
-
- def activate(self):
- self.pluginConfigChanged(self.__name__, "interval", self.getConfig("interval"))
- x = lambda: self.pluginConfigChanged(self.__name__, "reloadplugins", self.getConfig("reloadplugins"))
- self.core.scheduler.addJob(10, x, threaded=False)
-
-
- def deactivate(self):
- self.pluginConfigChanged(self.__name__, "reloadplugins", False)
-
-
- def setup(self):
- self.cb2 = None
- self.interval = self.MIN_INTERVAL
- self.updating = False
- self.info = {'pyload': False, 'version': None, 'plugins': False}
- self.mtimes = {} #: store modification time for each plugin
-
-
- def periodical2(self):
- if not self.updating:
- self.autoreloadPlugins()
-
- self.cb2 = self.core.scheduler.addJob(4, self.periodical2, threaded=False)
-
-
- @Expose
- def autoreloadPlugins(self):
- """ reload and reindex all modified plugins """
- modules = filter(
- lambda m: m and (m.__name__.startswith("pyload.plugin.") or
- m.__name__.startswith("userplugins.")) and
- m.__name__.count(".") >= 2, sys.modules.itervalues()
- )
-
- reloads = []
-
- for m in modules:
- root, type, name = m.__name__.rsplit(".", 2)
- id = (type, name)
- if type in self.core.pluginManager.plugins:
- f = m.__file__.replace(".pyc", ".py")
- if not path.isfile(f):
- continue
-
- mtime = stat(f).st_mtime
-
- if id not in self.mtimes:
- self.mtimes[id] = mtime
- elif self.mtimes[id] < mtime:
- reloads.append(id)
- self.mtimes[id] = mtime
-
- return True if self.core.pluginManager.reloadPlugins(reloads) else False
-
-
- def periodical(self):
- if self.info['pyload'] or self.getConfig("nodebugupdate") and self.core.debug:
- return
-
- self.updateThread()
-
-
- def server_request(self):
- try:
- return getURL(self.SERVER_URL, get={'v': self.core.api.getServerVersion()}).splitlines()
- except Exception:
- self.logWarning(_("Unable to contact server to get updates"))
-
-
- @threaded
- def updateThread(self):
- self.updating = True
-
- status = self.update(onlyplugin=self.getConfig("mode") == "plugins only")
-
- if status == 2:
- self.core.api.restart()
- else:
- self.updating = False
-
-
- @Expose
- def updatePlugins(self):
- """ simple wrapper for calling plugin update quickly """
- return self.update(onlyplugin=True)
-
-
- @Expose
- def update(self, onlyplugin=False):
- """ check for updates """
- data = self.server_request()
-
- if not data:
- exitcode = 0
-
- elif data[0] == "None":
- self.logInfo(_("No new pyLoad version available"))
- updates = data[1:]
- exitcode = self._updatePlugins(updates)
-
- elif onlyplugin:
- exitcode = 0
-
- else:
- newversion = data[0]
- self.logInfo(_("*** New pyLoad Version %s available ***") % newversion)
- self.logInfo(_("*** Get it here: https://github.com/pyload/pyload/releases ***"))
- exitcode = 3
- self.info['pyload'] = True
- self.info['version'] = newversion
-
- return exitcode #: 0 = No plugins updated; 1 = Plugins updated; 2 = Plugins updated, but restart required; 3 = No plugins updated, new pyLoad version available
-
-
- def _updatePlugins(self, updates):
- """ check for plugin updates """
-
- if self.info['plugins']:
- return False #: plugins were already updated
-
- exitcode = 0
- updated = []
-
- vre = re.compile(r'__version__.*=.*("|\')([\d.]+)')
- url = updates[0]
- schema = updates[1].split('|')
-
- if "BLACKLIST" in updates:
- blacklist = updates[updates.index('BLACKLIST') + 1:]
- updates = updates[2:updates.index('BLACKLIST')]
- else:
- blacklist = None
- updates = updates[2:]
-
- upgradable = sorted(map(lambda x: dict(zip(schema, x.split('|'))), updates),
- key=itemgetter("type", "name"))
-
- for plugin in upgradable:
- filename = plugin['name']
- type = plugin['type']
- version = plugin['version']
-
- if filename.endswith(".pyc"):
- name = filename[:filename.find("_")]
- else:
- name = filename.replace(".py", "")
-
- plugins = getattr(self.core.pluginManager, "%sPlugins" % type)
-
- oldver = float(plugins[name]['version']) if name in plugins else None
- newver = float(version)
-
- if not oldver:
- msg = "New plugin: [%(type)s] %(name)s (v%(newver).2f)"
- elif newver > oldver:
- msg = "New version of plugin: [%(type)s] %(name)s (v%(oldver).2f -> v%(newver).2f)"
- else:
- continue
-
- self.logInfo(_(msg) % {'type' : type,
- 'name' : name,
- 'oldver': oldver,
- 'newver': newver})
- try:
- content = getURL(url % plugin)
- m = vre.search(content)
-
- if m and m.group(2) == version:
- f = open(safe_join("userplugins", prefix, filename), "wb")
- f.write(content)
- f.close()
- updated.append((prefix, name))
- else:
- raise Exception, _("Version mismatch")
-
- except Exception, e:
- self.logError(_("Error updating plugin %s") % filename, e)
-
- if blacklist:
- blacklisted = map(lambda x: (x.split('|')[0], x.split('|')[1].rsplit('.', 1)[0]), blacklist)
-
- # Always protect internal plugins from removing
- for i, n, t in blacklisted.enumerate():
- if t == "internal":
- del blacklisted[i]
-
- blacklisted = sorted(blacklisted)
- removed = self.removePlugins(blacklisted)
- for t, n in removed:
- self.logInfo(_("Removed blacklisted plugin [%(type)s] %(name)s") % {
- 'type': t,
- 'name': n,
- })
-
- if updated:
- reloaded = self.core.pluginManager.reloadPlugins(updated)
- if reloaded:
- self.logInfo(_("Plugins updated and reloaded"))
- exitcode = 1
- else:
- self.logInfo(_("*** Plugins have been updated, but need a pyLoad restart to be reloaded ***"))
- self.info['plugins'] = True
- exitcode = 2
- else:
- self.logInfo(_("No plugin updates available"))
-
- return exitcode #: 0 = No plugins updated; 1 = Plugins updated; 2 = Plugins updated, but restart required
-
-
- @Expose
- def removePlugins(self, type_plugins):
- """ delete plugins from disk """
-
- if not type_plugins:
- return
-
- self.logDebug("Requested deletion of plugins: %s" % type_plugins)
-
- removed = []
-
- for type, name in type_plugins:
- err = False
- file = name + ".py"
-
- for root in ("userplugins", path.join(pypath, "pyload", "plugins")):
-
- filename = safe_join(root, type, file)
- try:
- remove(filename)
- except Exception, e:
- self.logDebug("Error deleting: %s" % path.basename(filename), e)
- err = True
-
- filename += "c"
- if path.isfile(filename):
- try:
- if type == "addon":
- self.manager.deactivateAddon(name)
- remove(filename)
- except Exception, e:
- self.logDebug("Error deleting: %s" % path.basename(filename), e)
- err = True
-
- if not err:
- id = (type, name)
- removed.append(id)
-
- return removed #: return a list of the plugins successfully removed
diff --git a/module/plugins/internal/XFSCrypter.py b/module/plugins/internal/XFSCrypter.py
deleted file mode 100644
index 665e13b18..000000000
--- a/module/plugins/internal/XFSCrypter.py
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from module.plugins.internal.SimpleCrypter import SimpleCrypter, create_getInfo
-
-
-class XFSCrypter(SimpleCrypter):
- __name__ = "XFSCrypter"
- __type__ = "crypter"
- __version__ = "0.06"
-
- __pattern__ = r'^unmatchable$'
-
- __description__ = """XFileSharing decrypter plugin"""
- __license__ = "GPLv3"
- __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
-
-
- HOSTER_DOMAIN = None
-
- URL_REPLACEMENTS = [(r'&?per_page=\d+', ""), (r'[?/&]+$', ""), (r'(.+/[^?]+)$', r'\1?'), (r'$', r'&per_page=10000')]
-
- LINK_PATTERN = r'<(?:td|TD).*?>\s*<a href="(.+?)".*?>.+?(?:</a>)?\s*</(?:td|TD)>'
- NAME_PATTERN = r'<[tT]itle>.*?\: (?P<N>.+) folder</[tT]itle>'
-
- OFFLINE_PATTERN = r'>\s*\w+ (Not Found|file (was|has been) removed)'
- TEMP_OFFLINE_PATTERN = r'>\s*\w+ server (is in )?(maintenance|maintainance)'
-
-
- def prepare(self):
- if not self.HOSTER_DOMAIN:
- if self.account:
- account = self.account
- else:
- account_name = (self.__name__ + ".py").replace("Folder.py", "").replace(".py", "")
- account = self.pyfile.m.core.accountManager.getAccountPlugin(account_name)
-
- if account and hasattr(account, "HOSTER_DOMAIN") and account.HOSTER_DOMAIN:
- self.HOSTER_DOMAIN = account.HOSTER_DOMAIN
- else:
- self.fail(_("Missing HOSTER_DOMAIN"))
-
- if isinstance(self.COOKIES, list):
- self.COOKIES.insert((self.HOSTER_DOMAIN, "lang", "english"))
-
- return super(XFSCrypter, self).prepare()
diff --git a/module/plugins/internal/XFSHoster.py b/module/plugins/internal/XFSHoster.py
deleted file mode 100644
index ecdd2f125..000000000
--- a/module/plugins/internal/XFSHoster.py
+++ /dev/null
@@ -1,326 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import re
-
-from random import random
-from time import sleep
-from urlparse import urljoin, urlparse
-
-from pyload.plugin.internal.captcha import ReCaptcha, SolveMedia
-from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo, secondsToMidnight
-from pyload.utils import html_unescape
-
-
-class XFSHoster(SimpleHoster):
- __name__ = "XFSHoster"
- __type__ = "hoster"
- __version__ = "0.44"
-
- __pattern__ = r'^unmatchable$'
-
- __description__ = """XFileSharing hoster plugin"""
- __license__ = "GPLv3"
- __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
- ("stickell", "l.stickell@yahoo.it"),
- ("Walter Purcaro", "vuolter@gmail.com")]
-
-
- HOSTER_DOMAIN = None
-
- TEXT_ENCODING = False
- DIRECT_LINK = None
- MULTI_HOSTER = True #@NOTE: Should be default to False for safe, but I'm lazy...
-
- NAME_PATTERN = r'(Filename[ ]*:[ ]*</b>(</td><td nowrap>)?|name="fname"[ ]+value="|<[\w^_]+ class="(file)?name">)\s*(?P<N>.+?)(\s*<|")'
- SIZE_PATTERN = r'(Size[ ]*:[ ]*</b>(</td><td>)?|File:.*>|</font>\s*\(|<[\w^_]+ class="size">)\s*(?P<S>[\d.,]+)\s*(?P<U>[\w^_]+)'
-
- OFFLINE_PATTERN = r'>\s*\w+ (Not Found|file (was|has been) removed)'
- TEMP_OFFLINE_PATTERN = r'>\s*\w+ server (is in )?(maintenance|maintainance)'
-
- WAIT_PATTERN = r'<span id="countdown_str">.*?>(\d+)</span>|id="countdown" value=".*?(\d+).*?"'
- PREMIUM_ONLY_PATTERN = r'>This file is available for Premium Users only'
- ERROR_PATTERN = r'(?:class=["\']err["\'].*?>|<[Cc]enter><b>|>Error</td>|>\(ERROR:)(?:\s*<.+?>\s*)*(.+?)(?:["\']|<|\))'
-
- LINK_LEECH_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)'
- LINK_PATTERN = None #: final download url pattern
-
- CAPTCHA_PATTERN = r'(https?://[^"\']+?/captchas?/[^"\']+)'
- CAPTCHA_BLOCK_PATTERN = r'>Enter code.*?<div.*?>(.+?)</div>'
- RECAPTCHA_PATTERN = None
- SOLVEMEDIA_PATTERN = None
-
- FORM_PATTERN = None
- FORM_INPUTS_MAP = None #: dict passed as input_names to parseHtmlForm
-
-
- def setup(self):
- self.chunkLimit = -1 if self.premium else 1
- self.resumeDownload = self.multiDL = self.premium
-
-
- def prepare(self):
- """ Initialize important variables """
- if not self.HOSTER_DOMAIN:
- if self.account:
- account = self.account
- else:
- account = self.pyfile.m.core.accountManager.getAccountPlugin(self.__name__)
-
- if account and hasattr(account, "HOSTER_DOMAIN") and account.HOSTER_DOMAIN:
- self.HOSTER_DOMAIN = account.HOSTER_DOMAIN
- else:
- self.fail(_("Missing HOSTER_DOMAIN"))
-
- if isinstance(self.COOKIES, list):
- self.COOKIES.insert((self.HOSTER_DOMAIN, "lang", "english"))
-
- if not self.LINK_PATTERN:
- pattern = r'(https?://(?:www\.)?([^/]*?%s|\d+\.\d+\.\d+\.\d+)(\:\d+)?(/d/|(/files)?/\d+/\w+/).+?)["\'<]'
- self.LINK_PATTERN = pattern % self.HOSTER_DOMAIN.replace('.', '\.')
-
- self.captcha = None
- self.errmsg = None
-
- super(XFSHoster, self).prepare()
-
- if self.DIRECT_LINK is None:
- self.directDL = self.premium
-
-
- def handleFree(self, pyfile):
- for i in xrange(1, 6):
- self.logDebug("Getting download link: #%d" % i)
-
- self.checkErrors()
-
- m = re.search(self.LINK_PATTERN, self.html, re.S)
- if m:
- break
-
- data = self.getPostParameters()
-
- self.html = self.load(self.pyfile.url, post=data, ref=True, decode=True, follow_location=False)
-
- m = re.search(r'Location\s*:\s*(.+)', self.req.http.header, re.I)
- if m and not "op=" in m.group(1):
- break
-
- m = re.search(self.LINK_PATTERN, self.html, re.S)
- if m:
- break
- else:
- self.logError(data['op'] if 'op' in data else _("UNKNOWN"))
- return ""
-
- self.link = m.group(1).strip() #@TODO: Remove .strip() in 0.4.10
-
-
- def handlePremium(self, pyfile):
- return self.handleFree(pyfile)
-
-
- def handleMulti(self, pyfile):
- if not self.account:
- self.fail(_("Only registered or premium users can use url leech feature"))
-
- #only tested with easybytez.com
- self.html = self.load("http://www.%s/" % self.HOSTER_DOMAIN)
-
- action, inputs = self.parseHtmlForm()
-
- upload_id = "%012d" % int(random() * 10 ** 12)
- action += upload_id + "&js_on=1&utype=prem&upload_type=url"
-
- inputs['tos'] = '1'
- inputs['url_mass'] = pyfile.url
- inputs['up1oad_type'] = 'url'
-
- self.logDebug(action, inputs)
-
- self.req.setOption("timeout", 600) #: wait for file to upload to easybytez.com
-
- self.html = self.load(action, post=inputs)
-
- self.checkErrors()
-
- action, inputs = self.parseHtmlForm('F1')
- if not inputs:
- if self.errmsg:
- self.retry(reason=self.errmsg)
- else:
- self.error(_("TEXTAREA F1 not found"))
-
- self.logDebug(inputs)
-
- stmsg = inputs['st']
-
- if stmsg == 'OK':
- self.html = self.load(action, post=inputs)
-
- elif 'Can not leech file' in stmsg:
- self.retry(20, 3 * 60, _("Can not leech file"))
-
- elif 'today' in stmsg:
- self.retry(wait_time=secondsToMidnight(gmt=2), reason=_("You've used all Leech traffic today"))
-
- else:
- self.fail(stmsg)
-
- #get easybytez.com link for uploaded file
- m = re.search(self.LINK_LEECH_PATTERN, self.html)
- if m is None:
- self.error(_("LINK_LEECH_PATTERN not found"))
-
- header = self.load(m.group(1), just_header=True, decode=True)
-
- if 'location' in header: #: Direct download link
- self.link = header['location']
-
-
- def checkErrors(self):
- m = re.search(self.ERROR_PATTERN, self.html)
- if m is None:
- self.errmsg = None
- else:
- self.errmsg = m.group(1).strip()
-
- self.logWarning(re.sub(r"<.*?>", " ", self.errmsg))
-
- if 'wait' in self.errmsg:
- wait_time = sum(int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1}[u.lower()] for v, u in
- re.findall(r'(\d+)\s*(hr|hour|min|sec)', self.errmsg, re.I))
- self.wait(wait_time, True)
-
- elif 'country' in self.errmsg:
- self.fail(_("Downloads are disabled for your country"))
-
- elif 'captcha' in self.errmsg:
- self.invalidCaptcha()
-
- elif 'premium' in self.errmsg and 'require' in self.errmsg:
- self.fail(_("File can be downloaded by premium users only"))
-
- elif 'limit' in self.errmsg:
- if 'days' in self.errmsg:
- delay = secondsToMidnight(gmt=2)
- retries = 3
- else:
- delay = 1 * 60 * 60
- retries = 24
-
- self.wantReconnect = True
- self.retry(retries, delay, _("Download limit exceeded"))
-
- elif 'countdown' in self.errmsg or 'Expired' in self.errmsg:
- self.retry(reason=_("Link expired"))
-
- elif 'maintenance' in self.errmsg or 'maintainance' in self.errmsg:
- self.tempOffline()
-
- elif 'up to' in self.errmsg:
- self.fail(_("File too large for free download"))
-
- else:
- self.wantReconnect = True
- self.retry(wait_time=60, reason=self.errmsg)
-
- if self.errmsg:
- self.info['error'] = self.errmsg
- else:
- self.info.pop('error', None)
-
-
- def getPostParameters(self):
- if self.FORM_PATTERN or self.FORM_INPUTS_MAP:
- action, inputs = self.parseHtmlForm(self.FORM_PATTERN or "", self.FORM_INPUTS_MAP or {})
- else:
- action, inputs = self.parseHtmlForm(input_names={'op': re.compile(r'^download')})
-
- if not inputs:
- action, inputs = self.parseHtmlForm('F1')
- if not inputs:
- if self.errmsg:
- self.retry(reason=self.errmsg)
- else:
- self.error(_("TEXTAREA F1 not found"))
-
- self.logDebug(inputs)
-
- if 'op' in inputs:
- if "password" in inputs:
- password = self.getPassword()
- if password:
- inputs['password'] = password
- else:
- self.fail(_("Missing password"))
-
- if not self.premium:
- m = re.search(self.WAIT_PATTERN, self.html)
- if m:
- wait_time = int(m.group(1))
- self.setWait(wait_time, False)
-
- self.captcha = self.handleCaptcha(inputs)
-
- self.wait()
- else:
- inputs['referer'] = self.pyfile.url
-
- if self.premium:
- inputs['method_premium'] = "Premium Download"
- inputs.pop('method_free', None)
- else:
- inputs['method_free'] = "Free Download"
- inputs.pop('method_premium', None)
-
- return inputs
-
-
- def handleCaptcha(self, inputs):
- m = re.search(self.CAPTCHA_PATTERN, self.html)
- if m:
- captcha_url = m.group(1)
- inputs['code'] = self.decryptCaptcha(captcha_url)
- return 1
-
- m = re.search(self.CAPTCHA_BLOCK_PATTERN, self.html, re.S)
- if m:
- captcha_div = m.group(1)
- numerals = re.findall(r'<span.*?padding-left\s*:\s*(\d+).*?>(\d)</span>', html_unescape(captcha_div))
-
- self.logDebug(captcha_div)
-
- inputs['code'] = "".join(a[1] for a in sorted(numerals, key=lambda num: int(num[0])))
-
- self.logDebug("Captcha code: %s" % inputs['code'], numerals)
- return 2
-
- recaptcha = ReCaptcha(self)
- try:
- captcha_key = re.search(self.RECAPTCHA_PATTERN, self.html).group(1)
-
- except Exception:
- captcha_key = recaptcha.detect_key()
-
- else:
- self.logDebug("ReCaptcha key: %s" % captcha_key)
-
- if captcha_key:
- inputs['recaptcha_response_field'], inputs['recaptcha_challenge_field'] = recaptcha.challenge(captcha_key)
- return 3
-
- solvemedia = SolveMedia(self)
- try:
- captcha_key = re.search(self.SOLVEMEDIA_PATTERN, self.html).group(1)
-
- except Exception:
- captcha_key = solvemedia.detect_key()
-
- else:
- self.logDebug("SolveMedia key: %s" % captcha_key)
-
- if captcha_key:
- inputs['adcopy_response'], inputs['adcopy_challenge'] = solvemedia.challenge(captcha_key)
- return 4
-
- return 0
diff --git a/module/Core.py b/pyload/Core.py
index fe4ae566e..fe4ae566e 100644
--- a/module/Core.py
+++ b/pyload/Core.py
diff --git a/module/__init__.py b/pyload/__init__.py
index e29c81ad7..e29c81ad7 100644
--- a/module/__init__.py
+++ b/pyload/__init__.py
diff --git a/module/api/__init__.py b/pyload/api/__init__.py
index 387481da2..387481da2 100644
--- a/module/api/__init__.py
+++ b/pyload/api/__init__.py
diff --git a/module/api/types.py b/pyload/api/types.py
index 81385bf9f..81385bf9f 100644
--- a/module/api/types.py
+++ b/pyload/api/types.py
diff --git a/module/cli/AddPackage.py b/pyload/cli/AddPackage.py
index f7e30b64e..f7e30b64e 100644
--- a/module/cli/AddPackage.py
+++ b/pyload/cli/AddPackage.py
diff --git a/module/cli/Cli.py b/pyload/cli/Cli.py
index d8c8602fc..d8c8602fc 100644
--- a/module/cli/Cli.py
+++ b/pyload/cli/Cli.py
diff --git a/module/cli/Handler.py b/pyload/cli/Handler.py
index 4aab3f0e2..4aab3f0e2 100644
--- a/module/cli/Handler.py
+++ b/pyload/cli/Handler.py
diff --git a/module/cli/ManageFiles.py b/pyload/cli/ManageFiles.py
index ca1070113..ca1070113 100644
--- a/module/cli/ManageFiles.py
+++ b/pyload/cli/ManageFiles.py
diff --git a/module/cli/__init__.py b/pyload/cli/__init__.py
index a64fc0c0c..a64fc0c0c 100644
--- a/module/cli/__init__.py
+++ b/pyload/cli/__init__.py
diff --git a/module/config/Parser.py b/pyload/config/Parser.py
index e21eaba9f..e21eaba9f 100644
--- a/module/config/Parser.py
+++ b/pyload/config/Parser.py
diff --git a/module/config/Setup.py b/pyload/config/Setup.py
index 8b88daa48..8b88daa48 100644
--- a/module/config/Setup.py
+++ b/pyload/config/Setup.py
diff --git a/module/config/__init__.py b/pyload/config/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/config/__init__.py
+++ b/pyload/config/__init__.py
diff --git a/module/config/default.conf b/pyload/config/default.conf
index 6e2fb7749..6e2fb7749 100644
--- a/module/config/default.conf
+++ b/pyload/config/default.conf
diff --git a/module/database/DatabaseBackend.py b/pyload/database/DatabaseBackend.py
index 4b63dd284..4b63dd284 100644
--- a/module/database/DatabaseBackend.py
+++ b/pyload/database/DatabaseBackend.py
diff --git a/pyload/database/File.py b/pyload/database/File.py
new file mode 100644
index 000000000..0b22805a7
--- /dev/null
+++ b/pyload/database/File.py
@@ -0,0 +1,875 @@
+# -*- coding: utf-8 -*-
+# @author: RaNaN, mkaay
+
+from threading import RLock
+from time import time
+
+from pyload.utils import formatSize, lock
+from pyload.manager.Event import InsertEvent, ReloadAllEvent, RemoveEvent, UpdateEvent
+from pyload.datatype.Package import PyPackage
+from pyload.datatype.File import PyFile
+from pyload.database import style, DatabaseBackend
+
+try:
+ from pysqlite2 import dbapi2 as sqlite3
+except Exception:
+ import sqlite3
+
+
+class FileHandler(object):
+ """Handles all request made to obtain information,
+ modify status or other request for links or packages"""
+
+ def __init__(self, core):
+ """Constructor"""
+ self.core = core
+
+ # translations
+ self.statusMsg = [_("finished"), _("offline"), _("online"), _("queued"), _("skipped"), _("waiting"), _("temp. offline"), _("starting"), _("failed"), _("aborted"), _("decrypting"), _("custom"), _("downloading"), _("processing"), _("unknown")]
+
+ self.cache = {} #holds instances for files
+ self.packageCache = {} # same for packages
+ #@TODO: purge the cache
+
+ self.jobCache = {}
+
+ self.lock = RLock() #@TODO should be a Lock w/o R
+ #self.lock._Verbose__verbose = True
+
+ self.filecount = -1 # if an invalid value is set get current value from db
+ self.queuecount = -1 #number of package to be loaded
+ self.unchanged = False #determines if any changes was made since last call
+
+ self.db = self.core.db
+
+ def change(func):
+ def new(*args):
+ args[0].unchanged = False
+ args[0].filecount = -1
+ args[0].queuecount = -1
+ args[0].jobCache = {}
+ return func(*args)
+ return new
+
+ #--------------------------------------------------------------------------
+ def save(self):
+ """saves all data to backend"""
+ self.db.commit()
+
+ #--------------------------------------------------------------------------
+ def syncSave(self):
+ """saves all data to backend and waits until all data are written"""
+ pyfiles = self.cache.values()
+ for pyfile in pyfiles:
+ pyfile.sync()
+
+ pypacks = self.packageCache.values()
+ for pypack in pypacks:
+ pypack.sync()
+
+ self.db.syncSave()
+
+ @lock
+ def getCompleteData(self, queue=1):
+ """gets a complete data representation"""
+
+ data = self.db.getAllLinks(queue)
+ packs = self.db.getAllPackages(queue)
+
+ data.update([(x.id, x.toDbDict()[x.id]) for x in self.cache.values()])
+
+ for x in self.packageCache.itervalues():
+ if x.queue != queue or x.id not in packs: continue
+ packs[x.id].update(x.toDict()[x.id])
+
+ for key, value in data.iteritems():
+ if value["package"] in packs:
+ packs[value["package"]]["links"][key] = value
+
+ return packs
+
+ @lock
+ def getInfoData(self, queue=1):
+ """gets a data representation without links"""
+
+ packs = self.db.getAllPackages(queue)
+ for x in self.packageCache.itervalues():
+ if x.queue != queue or x.id not in packs: continue
+ packs[x.id].update(x.toDict()[x.id])
+
+ return packs
+
+ @lock
+ @change
+ def addLinks(self, urls, package):
+ """adds links"""
+
+ self.core.addonManager.dispatchEvent("links-added", urls, package)
+
+ data = self.core.pluginManager.parseUrls(urls)
+
+ self.db.addLinks(data, package)
+ self.core.threadManager.createInfoThread(data, package)
+
+ #@TODO change from reloadAll event to package update event
+ self.core.pullManager.addEvent(ReloadAllEvent("collector"))
+
+ #--------------------------------------------------------------------------
+ @lock
+ @change
+ def addPackage(self, name, folder, queue=0):
+ """adds a package, default to link collector"""
+ lastID = self.db.addPackage(name, folder, queue)
+ p = self.db.getPackage(lastID)
+ e = InsertEvent("pack", lastID, p.order, "collector" if not queue else "queue")
+ self.core.pullManager.addEvent(e)
+ return lastID
+
+ #--------------------------------------------------------------------------
+ @lock
+ @change
+ def deletePackage(self, id):
+ """delete package and all contained links"""
+
+ p = self.getPackage(id)
+ if not p:
+ if id in self.packageCache: del self.packageCache[id]
+ return
+
+ oldorder = p.order
+ queue = p.queue
+
+ e = RemoveEvent("pack", id, "collector" if not p.queue else "queue")
+
+ pyfiles = self.cache.values()
+
+ for pyfile in pyfiles:
+ if pyfile.packageid == id:
+ pyfile.abortDownload()
+ pyfile.release()
+
+ self.db.deletePackage(p)
+ self.core.pullManager.addEvent(e)
+ self.core.addonManager.dispatchEvent("package-deleted", id)
+
+ if id in self.packageCache:
+ del self.packageCache[id]
+
+ packs = self.packageCache.values()
+ for pack in packs:
+ if pack.queue == queue and pack.order > oldorder:
+ pack.order -= 1
+ pack.notifyChange()
+
+ #--------------------------------------------------------------------------
+ @lock
+ @change
+ def deleteLink(self, id):
+ """deletes links"""
+
+ f = self.getFile(id)
+ if not f:
+ return None
+
+ pid = f.packageid
+ e = RemoveEvent("file", id, "collector" if not f.package().queue else "queue")
+
+ oldorder = f.order
+
+ if id in self.core.threadManager.processingIds():
+ self.cache[id].abortDownload()
+
+ if id in self.cache:
+ del self.cache[id]
+
+ self.db.deleteLink(f)
+
+ self.core.pullManager.addEvent(e)
+
+ p = self.getPackage(pid)
+ if not len(p.getChildren()):
+ p.delete()
+
+ pyfiles = self.cache.values()
+ for pyfile in pyfiles:
+ if pyfile.packageid == pid and pyfile.order > oldorder:
+ pyfile.order -= 1
+ pyfile.notifyChange()
+
+ #--------------------------------------------------------------------------
+ def releaseLink(self, id):
+ """removes pyfile from cache"""
+ if id in self.cache:
+ del self.cache[id]
+
+ #--------------------------------------------------------------------------
+ def releasePackage(self, id):
+ """removes package from cache"""
+ if id in self.packageCache:
+ del self.packageCache[id]
+
+ #--------------------------------------------------------------------------
+ def updateLink(self, pyfile):
+ """updates link"""
+ self.db.updateLink(pyfile)
+
+ e = UpdateEvent("file", pyfile.id, "collector" if not pyfile.package().queue else "queue")
+ self.core.pullManager.addEvent(e)
+
+ #--------------------------------------------------------------------------
+ def updatePackage(self, pypack):
+ """updates a package"""
+ self.db.updatePackage(pypack)
+
+ e = UpdateEvent("pack", pypack.id, "collector" if not pypack.queue else "queue")
+ self.core.pullManager.addEvent(e)
+
+ #--------------------------------------------------------------------------
+ def getPackage(self, id):
+ """return package instance"""
+
+ if id in self.packageCache:
+ return self.packageCache[id]
+ else:
+ return self.db.getPackage(id)
+
+ #--------------------------------------------------------------------------
+ def getPackageData(self, id):
+ """returns dict with package information"""
+ pack = self.getPackage(id)
+
+ if not pack:
+ return None
+
+ pack = pack.toDict()[id]
+
+ data = self.db.getPackageData(id)
+
+ tmplist = []
+
+ cache = self.cache.values()
+ for x in cache:
+ if int(x.toDbDict()[x.id]["package"]) == int(id):
+ tmplist.append((x.id, x.toDbDict()[x.id]))
+ data.update(tmplist)
+
+ pack["links"] = data
+
+ return pack
+
+ #--------------------------------------------------------------------------
+ def getFileData(self, id):
+ """returns dict with file information"""
+ if id in self.cache:
+ return self.cache[id].toDbDict()
+
+ return self.db.getLinkData(id)
+
+ #--------------------------------------------------------------------------
+ def getFile(self, id):
+ """returns pyfile instance"""
+ if id in self.cache:
+ return self.cache[id]
+ else:
+ return self.db.getFile(id)
+
+ #--------------------------------------------------------------------------
+ @lock
+ def getJob(self, occ):
+ """get suitable job"""
+
+ #@TODO clean mess
+ #@TODO improve selection of valid jobs
+
+ if occ in self.jobCache:
+ if self.jobCache[occ]:
+ id = self.jobCache[occ].pop()
+ if id == "empty":
+ pyfile = None
+ self.jobCache[occ].append("empty")
+ else:
+ pyfile = self.getFile(id)
+ else:
+ jobs = self.db.getJob(occ)
+ jobs.reverse()
+ if not jobs:
+ self.jobCache[occ].append("empty")
+ pyfile = None
+ else:
+ self.jobCache[occ].extend(jobs)
+ pyfile = self.getFile(self.jobCache[occ].pop())
+
+ else:
+ self.jobCache = {} #better not caching to much
+ jobs = self.db.getJob(occ)
+ jobs.reverse()
+ self.jobCache[occ] = jobs
+
+ if not jobs:
+ self.jobCache[occ].append("empty")
+ pyfile = None
+ else:
+ pyfile = self.getFile(self.jobCache[occ].pop())
+
+ #@TODO: maybe the new job has to be approved...
+
+
+ #pyfile = self.getFile(self.jobCache[occ].pop())
+ return pyfile
+
+ @lock
+ def getDecryptJob(self):
+ """return job for decrypting"""
+ if "decrypt" in self.jobCache:
+ return None
+
+ plugins = self.core.pluginManager.crypterPlugins.keys() + self.core.pluginManager.containerPlugins.keys()
+ plugins = str(tuple(plugins))
+
+ jobs = self.db.getPluginJob(plugins)
+ if jobs:
+ return self.getFile(jobs[0])
+ else:
+ self.jobCache["decrypt"] = "empty"
+ return None
+
+ def getFileCount(self):
+ """returns number of files"""
+
+ if self.filecount == -1:
+ self.filecount = self.db.filecount(1)
+
+ return self.filecount
+
+ def getQueueCount(self, force=False):
+ """number of files that have to be processed"""
+ if self.queuecount == -1 or force:
+ self.queuecount = self.db.queuecount(1)
+
+ return self.queuecount
+
+ def checkAllLinksFinished(self):
+ """checks if all files are finished and dispatch event"""
+
+ if not self.getQueueCount(True):
+ self.core.addonManager.dispatchEvent("all_downloads-finished")
+ self.core.log.debug("All downloads finished")
+ return True
+
+ return False
+
+ def checkAllLinksProcessed(self, fid):
+ """checks if all files was processed and pyload would idle now, needs fid which will be ignored when counting"""
+
+ # reset count so statistic will update (this is called when dl was processed)
+ self.resetCount()
+
+ if not self.db.processcount(1, fid):
+ self.core.addonManager.dispatchEvent("all_downloads-processed")
+ self.core.log.debug("All downloads processed")
+ return True
+
+ return False
+
+ def resetCount(self):
+ self.queuecount = -1
+
+ @lock
+ @change
+ def restartPackage(self, id):
+ """restart package"""
+ pyfiles = self.cache.values()
+ for pyfile in pyfiles:
+ if pyfile.packageid == id:
+ self.restartFile(pyfile.id)
+
+ self.db.restartPackage(id)
+
+ if id in self.packageCache:
+ self.packageCache[id].setFinished = False
+
+ e = UpdateEvent("pack", id, "collector" if not self.getPackage(id).queue else "queue")
+ self.core.pullManager.addEvent(e)
+
+ @lock
+ @change
+ def restartFile(self, id):
+ """ restart file"""
+ if id in self.cache:
+ self.cache[id].status = 3
+ self.cache[id].name = self.cache[id].url
+ self.cache[id].error = ""
+ self.cache[id].abortDownload()
+
+
+ self.db.restartFile(id)
+
+ e = UpdateEvent("file", id, "collector" if not self.getFile(id).package().queue else "queue")
+ self.core.pullManager.addEvent(e)
+
+ @lock
+ @change
+ def setPackageLocation(self, id, queue):
+ """push package to queue"""
+
+ p = self.db.getPackage(id)
+ oldorder = p.order
+
+ e = RemoveEvent("pack", id, "collector" if not p.queue else "queue")
+ self.core.pullManager.addEvent(e)
+
+ self.db.clearPackageOrder(p)
+
+ p = self.db.getPackage(id)
+
+ p.queue = queue
+ self.db.updatePackage(p)
+
+ self.db.reorderPackage(p, -1, True)
+
+ packs = self.packageCache.values()
+ for pack in packs:
+ if pack.queue != queue and pack.order > oldorder:
+ pack.order -= 1
+ pack.notifyChange()
+
+ self.db.commit()
+ self.releasePackage(id)
+ p = self.getPackage(id)
+
+ e = InsertEvent("pack", id, p.order, "collector" if not p.queue else "queue")
+ self.core.pullManager.addEvent(e)
+
+ @lock
+ @change
+ def reorderPackage(self, id, position):
+ p = self.getPackage(id)
+
+ e = RemoveEvent("pack", id, "collector" if not p.queue else "queue")
+ self.core.pullManager.addEvent(e)
+ self.db.reorderPackage(p, position)
+
+ packs = self.packageCache.values()
+ for pack in packs:
+ if pack.queue != p.queue or pack.order < 0 or pack == p: continue
+ if p.order > position:
+ if pack.order >= position and pack.order < p.order:
+ pack.order += 1
+ pack.notifyChange()
+ elif p.order < position:
+ if pack.order <= position and pack.order > p.order:
+ pack.order -= 1
+ pack.notifyChange()
+
+ p.order = position
+ self.db.commit()
+
+ e = InsertEvent("pack", id, position, "collector" if not p.queue else "queue")
+ self.core.pullManager.addEvent(e)
+
+ @lock
+ @change
+ def reorderFile(self, id, position):
+ f = self.getFileData(id)
+ f = f[id]
+
+ e = RemoveEvent("file", id, "collector" if not self.getPackage(f["package"]).queue else "queue")
+ self.core.pullManager.addEvent(e)
+
+ self.db.reorderLink(f, position)
+
+ pyfiles = self.cache.values()
+ for pyfile in pyfiles:
+ if pyfile.packageid != f["package"] or pyfile.order < 0: continue
+ if f["order"] > position:
+ if pyfile.order >= position and pyfile.order < f["order"]:
+ pyfile.order += 1
+ pyfile.notifyChange()
+ elif f["order"] < position:
+ if pyfile.order <= position and pyfile.order > f["order"]:
+ pyfile.order -= 1
+ pyfile.notifyChange()
+
+ if id in self.cache:
+ self.cache[id].order = position
+
+ self.db.commit()
+
+ e = InsertEvent("file", id, position, "collector" if not self.getPackage(f["package"]).queue else "queue")
+ self.core.pullManager.addEvent(e)
+
+ @change
+ def updateFileInfo(self, data, pid):
+ """ updates file info (name, size, status, url)"""
+ ids = self.db.updateLinkInfo(data)
+ e = UpdateEvent("pack", pid, "collector" if not self.getPackage(pid).queue else "queue")
+ self.core.pullManager.addEvent(e)
+
+ def checkPackageFinished(self, pyfile):
+ """ checks if package is finished and calls AddonManager """
+
+ ids = self.db.getUnfinished(pyfile.packageid)
+ if not ids or (pyfile.id in ids and len(ids) == 1):
+ if not pyfile.package().setFinished:
+ self.core.log.info(_("Package finished: %s") % pyfile.package().name)
+ self.core.addonManager.packageFinished(pyfile.package())
+ pyfile.package().setFinished = True
+
+
+ def reCheckPackage(self, pid):
+ """ recheck links in package """
+ data = self.db.getPackageData(pid)
+
+ urls = []
+
+ for pyfile in data.itervalues():
+ if pyfile["status"] not in (0, 12, 13):
+ urls.append((pyfile["url"], pyfile["plugin"]))
+
+ self.core.threadManager.createInfoThread(urls, pid)
+
+ @lock
+ @change
+ def deleteFinishedLinks(self):
+ """ deletes finished links and packages, return deleted packages """
+
+ old_packs = self.getInfoData(0)
+ old_packs.update(self.getInfoData(1))
+
+ self.db.deleteFinished()
+
+ new_packs = self.db.getAllPackages(0)
+ new_packs.update(self.db.getAllPackages(1))
+ #get new packages only from db
+
+ deleted = []
+ for id in old_packs.iterkeys():
+ if id not in new_packs:
+ deleted.append(id)
+ self.deletePackage(int(id))
+
+ return deleted
+
+ @lock
+ @change
+ def restartFailed(self):
+ """ restart all failed links """
+ self.db.restartFailed()
+
+class FileMethods(object):
+ @style.queue
+ def filecount(self, queue):
+ """returns number of files in queue"""
+ self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=?", (queue,))
+ return self.c.fetchone()[0]
+
+ @style.queue
+ def queuecount(self, queue):
+ """ number of files in queue not finished yet"""
+ self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? AND l.status NOT IN (0, 4)", (queue,))
+ return self.c.fetchone()[0]
+
+ @style.queue
+ def processcount(self, queue, fid):
+ """ number of files which have to be proccessed """
+ self.c.execute("SELECT COUNT(*) FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? AND l.status IN (2, 3, 5, 7, 12) AND l.id != ?", (queue, str(fid)))
+ return self.c.fetchone()[0]
+
+ @style.inner
+ def _nextPackageOrder(self, queue=0):
+ self.c.execute('SELECT MAX(packageorder) FROM packages WHERE queue=?', (queue,))
+ max = self.c.fetchone()[0]
+ if max is not None:
+ return max + 1
+ else:
+ return 0
+
+ @style.inner
+ def _nextFileOrder(self, package):
+ self.c.execute('SELECT MAX(linkorder) FROM links WHERE package=?', (package,))
+ max = self.c.fetchone()[0]
+ if max is not None:
+ return max + 1
+ else:
+ return 0
+
+ @style.queue
+ def addLink(self, url, name, plugin, package):
+ order = self._nextFileOrder(package)
+ self.c.execute('INSERT INTO links(url, name, plugin, package, linkorder) VALUES(?,?,?,?,?)', (url, name, (plugintype, pluginname), package, order))
+ return self.c.lastrowid
+
+ @style.queue
+ def addLinks(self, links, package):
+ """ links is a list of tupels (url, plugin)"""
+ order = self._nextFileOrder(package)
+ orders = [order + x for x in range(len(links))]
+ links = [(x[0], x[0], (x[1], x[2]), package, o) for x, o in zip(links, orders)]
+ self.c.executemany('INSERT INTO links(url, name, plugin, package, linkorder) VALUES(?,?,?,?,?)', links)
+
+ @style.queue
+ def addPackage(self, name, folder, queue):
+ order = self._nextPackageOrder(queue)
+ self.c.execute('INSERT INTO packages(name, folder, queue, packageorder) VALUES(?,?,?,?)', (name, folder, queue, order))
+ return self.c.lastrowid
+
+ @style.queue
+ def deletePackage(self, p):
+
+ self.c.execute('DELETE FROM links WHERE package=?', (str(p.id),))
+ self.c.execute('DELETE FROM packages WHERE id=?', (str(p.id),))
+ self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder > ? AND queue=?', (p.order, p.queue))
+
+ @style.queue
+ def deleteLink(self, f):
+
+ self.c.execute('DELETE FROM links WHERE id=?', (str(f.id),))
+ self.c.execute('UPDATE links SET linkorder=linkorder-1 WHERE linkorder > ? AND package=?', (f.order, str(f.packageid)))
+
+
+ @style.queue
+ def getAllLinks(self, q):
+ """return information about all links in queue q
+
+ q0 queue
+ q1 collector
+
+ format:
+
+ {
+ id: {'name': name, ... 'package': id }, ...
+ }
+
+ """
+ self.c.execute('SELECT l.id, l.url, l.name, l.size, l.status, l.error, l.plugin, l.package, l.linkorder FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE p.queue=? ORDER BY l.linkorder', (q,))
+ data = {}
+ for r in self.c:
+ data[r[0]] = {
+ 'id': r[0],
+ 'url': r[1],
+ 'name': r[2],
+ 'size': r[3],
+ 'format_size': formatSize(r[3]),
+ 'status': r[4],
+ 'statusmsg': self.manager.statusMsg[r[4]],
+ 'error': r[5],
+ 'plugin': r[6],
+ 'package': r[7],
+ 'order': r[8],
+ }
+
+ return data
+
+ @style.queue
+ def getAllPackages(self, q):
+ """return information about packages in queue q
+ (only useful in get all data)
+
+ q0 queue
+ q1 collector
+
+ format:
+
+ {
+ id: {'name': name ... 'links': {}}, ...
+ }
+ """
+ self.c.execute('SELECT p.id, p.name, p.folder, p.site, p.password, p.queue, p.packageorder, s.sizetotal, s.sizedone, s.linksdone, s.linkstotal \
+ FROM packages p JOIN pstats s ON p.id = s.id \
+ WHERE p.queue=? ORDER BY p.packageorder', str(q))
+
+ data = {}
+ for r in self.c:
+ data[r[0]] = {
+ 'id': r[0],
+ 'name': r[1],
+ 'folder': r[2],
+ 'site': r[3],
+ 'password': r[4],
+ 'queue': r[5],
+ 'order': r[6],
+ 'sizetotal': int(r[7]),
+ 'sizedone': r[8] if r[8] else 0, #these can be None
+ 'linksdone': r[9] if r[9] else 0,
+ 'linkstotal': r[10],
+ 'links': {}
+ }
+
+ return data
+
+ @style.queue
+ def getLinkData(self, id):
+ """get link information as dict"""
+ self.c.execute('SELECT id, url, name, size, status, error, plugin, package, linkorder FROM links WHERE id=?', (str(id),))
+ data = {}
+ r = self.c.fetchone()
+ if not r:
+ return None
+ data[r[0]] = {
+ 'id': r[0],
+ 'url': r[1],
+ 'name': r[2],
+ 'size': r[3],
+ 'format_size': formatSize(r[3]),
+ 'status': r[4],
+ 'statusmsg': self.manager.statusMsg[r[4]],
+ 'error': r[5],
+ 'plugin': r[6],
+ 'package': r[7],
+ 'order': r[8],
+ }
+
+ return data
+
+ @style.queue
+ def getPackageData(self, id):
+ """get data about links for a package"""
+ self.c.execute('SELECT id, url, name, size, status, error, plugin, package, linkorder FROM links WHERE package=? ORDER BY linkorder', (str(id),))
+
+ data = {}
+ for r in self.c:
+ data[r[0]] = {
+ 'id': r[0],
+ 'url': r[1],
+ 'name': r[2],
+ 'size': r[3],
+ 'format_size': formatSize(r[3]),
+ 'status': r[4],
+ 'statusmsg': self.manager.statusMsg[r[4]],
+ 'error': r[5],
+ 'plugin': r[6],
+ 'package': r[7],
+ 'order': r[8],
+ }
+
+ return data
+
+
+ @style.async
+ def updateLink(self, f):
+ self.c.execute('UPDATE links SET url=?, name=?, size=?, status=?, error=?, package=? WHERE id=?', (f.url, f.name, f.size, f.status, f.error, str(f.packageid), str(f.id)))
+
+ @style.queue
+ def updatePackage(self, p):
+ self.c.execute('UPDATE packages SET name=?, folder=?, site=?, password=?, queue=? WHERE id=?', (p.name, p.folder, p.site, p.password, p.queue, str(p.id)))
+
+ @style.queue
+ def updateLinkInfo(self, data):
+ """ data is list of tupels (name, size, status, url) """
+ self.c.executemany('UPDATE links SET name=?, size=?, status=? WHERE url=? AND status IN (1, 2, 3, 14)', data)
+ ids = []
+ self.c.execute('SELECT id FROM links WHERE url IN (\'%s\')' % "','".join([x[3] for x in data]))
+ for r in self.c:
+ ids.append(int(r[0]))
+ return ids
+
+ @style.queue
+ def reorderPackage(self, p, position, noMove=False):
+ if position == -1:
+ position = self._nextPackageOrder(p.queue)
+ if not noMove:
+ if p.order > position:
+ self.c.execute('UPDATE packages SET packageorder=packageorder+1 WHERE packageorder >= ? AND packageorder < ? AND queue=? AND packageorder >= 0', (position, p.order, p.queue))
+ elif p.order < position:
+ self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder <= ? AND packageorder > ? AND queue=? AND packageorder >= 0', (position, p.order, p.queue))
+
+ self.c.execute('UPDATE packages SET packageorder=? WHERE id=?', (position, str(p.id)))
+
+ @style.queue
+ def reorderLink(self, f, position):
+ """ reorder link with f as dict for pyfile """
+ if f["order"] > position:
+ self.c.execute('UPDATE links SET linkorder=linkorder+1 WHERE linkorder >= ? AND linkorder < ? AND package=?', (position, f["order"], f["package"]))
+ elif f["order"] < position:
+ self.c.execute('UPDATE links SET linkorder=linkorder-1 WHERE linkorder <= ? AND linkorder > ? AND package=?', (position, f["order"], f["package"]))
+
+ self.c.execute('UPDATE links SET linkorder=? WHERE id=?', (position, f["id"]))
+
+ @style.queue
+ def clearPackageOrder(self, p):
+ self.c.execute('UPDATE packages SET packageorder=? WHERE id=?', (-1, str(p.id)))
+ self.c.execute('UPDATE packages SET packageorder=packageorder-1 WHERE packageorder > ? AND queue=? AND id != ?', (p.order, p.queue, str(p.id)))
+
+ @style.async
+ def restartFile(self, id):
+ self.c.execute('UPDATE links SET status=3, error="" WHERE id=?', (str(id),))
+
+ @style.async
+ def restartPackage(self, id):
+ self.c.execute('UPDATE links SET status=3 WHERE package=?', (str(id),))
+
+ @style.queue
+ def getPackage(self, id):
+ """return package instance from id"""
+ self.c.execute("SELECT name, folder, site, password, queue, packageorder FROM packages WHERE id=?", (str(id),))
+ r = self.c.fetchone()
+ if not r: return None
+ return PyPackage(self.manager, id, * r)
+
+ #--------------------------------------------------------------------------
+ @style.queue
+ def getFile(self, id):
+ """return link instance from id"""
+ self.c.execute("SELECT url, name, size, status, error, plugin, package, linkorder FROM links WHERE id=?", (str(id),))
+ r = self.c.fetchone()
+ if not r: return None
+ return PyFile(self.manager, id, * r)
+
+
+ @style.queue
+ def getJob(self, occ):
+ """return pyfile ids, which are suitable for download and dont use a occupied plugin"""
+
+ #@TODO improve this hardcoded method
+ pre = "('CCF', 'DLC', 'LinkList', 'RSDF', 'TXT')" #plugins which are processed in collector
+
+ cmd = "("
+ for i, item in enumerate(occ):
+ if i: cmd += ", "
+ cmd += "'%s'" % item
+
+ cmd += ")"
+
+ cmd = "SELECT l.id FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE ((p.queue=1 AND l.plugin NOT IN %s) OR l.plugin IN %s) AND l.status IN (2, 3, 14) ORDER BY p.packageorder ASC, l.linkorder ASC LIMIT 5" % (cmd, pre)
+
+ self.c.execute(cmd) # very bad!
+
+ return [x[0] for x in self.c]
+
+ @style.queue
+ def getPluginJob(self, plugins):
+ """returns pyfile ids with suited plugins"""
+ cmd = "SELECT l.id FROM links as l INNER JOIN packages as p ON l.package=p.id WHERE l.plugin IN %s AND l.status IN (2, 3, 14) ORDER BY p.packageorder ASC, l.linkorder ASC LIMIT 5" % plugins
+
+ self.c.execute(cmd) # very bad!
+
+ return [x[0] for x in self.c]
+
+ @style.queue
+ def getUnfinished(self, pid):
+ """return list of max length 3 ids with pyfiles in package not finished or processed"""
+
+ self.c.execute("SELECT id FROM links WHERE package=? AND status NOT IN (0, 4, 13) LIMIT 3", (str(pid),))
+ return [r[0] for r in self.c]
+
+ @style.queue
+ def deleteFinished(self):
+ self.c.execute("DELETE FROM links WHERE status IN (0, 4)")
+ self.c.execute("DELETE FROM packages WHERE NOT EXISTS(SELECT 1 FROM links WHERE packages.id=links.package)")
+
+ @style.queue
+ def restartFailed(self):
+ self.c.execute("UPDATE links SET status=3, error='' WHERE status IN (6, 8, 9)")
+
+ @style.queue
+ def findDuplicates(self, id, folder, filename):
+ """ checks if filename exists with different id and same package """
+ self.c.execute("SELECT l.plugin FROM links as l INNER JOIN packages as p ON l.package=p.id AND p.folder=? WHERE l.id!=? AND l.status=0 AND l.name=?", (folder, id, filename))
+ return self.c.fetchone()
+
+ @style.queue
+ def purgeLinks(self):
+ self.c.execute("DELETE FROM links;")
+ self.c.execute("DELETE FROM packages;")
+
+DatabaseBackend.registerSub(FileMethods)
diff --git a/module/database/Storage.py b/pyload/database/Storage.py
index 75e166d39..75e166d39 100644
--- a/module/database/Storage.py
+++ b/pyload/database/Storage.py
diff --git a/module/database/User.py b/pyload/database/User.py
index 67cb62ab9..67cb62ab9 100644
--- a/module/database/User.py
+++ b/pyload/database/User.py
diff --git a/module/database/__init__.py b/pyload/database/__init__.py
index 64f049be1..64f049be1 100644
--- a/module/database/__init__.py
+++ b/pyload/database/__init__.py
diff --git a/module/datatype/File.py b/pyload/datatype/File.py
index 1df0a8590..1df0a8590 100644
--- a/module/datatype/File.py
+++ b/pyload/datatype/File.py
diff --git a/module/datatype/Package.py b/pyload/datatype/Package.py
index bf3edffea..bf3edffea 100644
--- a/module/datatype/Package.py
+++ b/pyload/datatype/Package.py
diff --git a/module/datatype/__init__.py b/pyload/datatype/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/datatype/__init__.py
+++ b/pyload/datatype/__init__.py
diff --git a/module/manager/Account.py b/pyload/manager/Account.py
index 3acf70311..3acf70311 100644
--- a/module/manager/Account.py
+++ b/pyload/manager/Account.py
diff --git a/module/manager/Addon.py b/pyload/manager/Addon.py
index d293109c7..d293109c7 100644
--- a/module/manager/Addon.py
+++ b/pyload/manager/Addon.py
diff --git a/module/manager/Captcha.py b/pyload/manager/Captcha.py
index e54eacf30..e54eacf30 100644
--- a/module/manager/Captcha.py
+++ b/pyload/manager/Captcha.py
diff --git a/module/manager/Event.py b/pyload/manager/Event.py
index 20897290e..20897290e 100644
--- a/module/manager/Event.py
+++ b/pyload/manager/Event.py
diff --git a/module/manager/Plugin.py b/pyload/manager/Plugin.py
index 879430be2..879430be2 100644
--- a/module/manager/Plugin.py
+++ b/pyload/manager/Plugin.py
diff --git a/module/manager/Remote.py b/pyload/manager/Remote.py
index 910881164..910881164 100644
--- a/module/manager/Remote.py
+++ b/pyload/manager/Remote.py
diff --git a/module/manager/Thread.py b/pyload/manager/Thread.py
index 2ace9c789..2ace9c789 100644
--- a/module/manager/Thread.py
+++ b/pyload/manager/Thread.py
diff --git a/module/manager/__init__.py b/pyload/manager/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/manager/__init__.py
+++ b/pyload/manager/__init__.py
diff --git a/module/manager/event/Scheduler.py b/pyload/manager/event/Scheduler.py
index fd428a956..fd428a956 100644
--- a/module/manager/event/Scheduler.py
+++ b/pyload/manager/event/Scheduler.py
diff --git a/module/manager/event/__init__.py b/pyload/manager/event/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/manager/event/__init__.py
+++ b/pyload/manager/event/__init__.py
diff --git a/module/manager/thread/Addon.py b/pyload/manager/thread/Addon.py
index 7feec227e..7feec227e 100644
--- a/module/manager/thread/Addon.py
+++ b/pyload/manager/thread/Addon.py
diff --git a/module/manager/thread/Decrypter.py b/pyload/manager/thread/Decrypter.py
index 51544d1b9..51544d1b9 100644
--- a/module/manager/thread/Decrypter.py
+++ b/pyload/manager/thread/Decrypter.py
diff --git a/module/manager/thread/Download.py b/pyload/manager/thread/Download.py
index c7d21a4ba..c7d21a4ba 100644
--- a/module/manager/thread/Download.py
+++ b/pyload/manager/thread/Download.py
diff --git a/module/manager/thread/Info.py b/pyload/manager/thread/Info.py
index 4526a07ed..4526a07ed 100644
--- a/module/manager/thread/Info.py
+++ b/pyload/manager/thread/Info.py
diff --git a/module/manager/thread/Plugin.py b/pyload/manager/thread/Plugin.py
index 20d57c933..20d57c933 100644
--- a/module/manager/thread/Plugin.py
+++ b/pyload/manager/thread/Plugin.py
diff --git a/module/manager/thread/Server.py b/pyload/manager/thread/Server.py
index f3f174e74..f3f174e74 100644
--- a/module/manager/thread/Server.py
+++ b/pyload/manager/thread/Server.py
diff --git a/module/manager/thread/__init__.py b/pyload/manager/thread/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/manager/thread/__init__.py
+++ b/pyload/manager/thread/__init__.py
diff --git a/module/network/Browser.py b/pyload/network/Browser.py
index 89341ff25..89341ff25 100644
--- a/module/network/Browser.py
+++ b/pyload/network/Browser.py
diff --git a/module/network/Bucket.py b/pyload/network/Bucket.py
index 408a1e240..408a1e240 100644
--- a/module/network/Bucket.py
+++ b/pyload/network/Bucket.py
diff --git a/module/network/CookieJar.py b/pyload/network/CookieJar.py
index a2b302776..a2b302776 100644
--- a/module/network/CookieJar.py
+++ b/pyload/network/CookieJar.py
diff --git a/module/network/HTTPChunk.py b/pyload/network/HTTPChunk.py
index 41752b940..41752b940 100644
--- a/module/network/HTTPChunk.py
+++ b/pyload/network/HTTPChunk.py
diff --git a/module/network/HTTPDownload.py b/pyload/network/HTTPDownload.py
index 3b2bf26ca..3b2bf26ca 100644
--- a/module/network/HTTPDownload.py
+++ b/pyload/network/HTTPDownload.py
diff --git a/module/network/HTTPRequest.py b/pyload/network/HTTPRequest.py
index eac03a365..eac03a365 100644
--- a/module/network/HTTPRequest.py
+++ b/pyload/network/HTTPRequest.py
diff --git a/module/network/JsEngine.py b/pyload/network/JsEngine.py
index 2e98fa37d..2e98fa37d 100644
--- a/module/network/JsEngine.py
+++ b/pyload/network/JsEngine.py
diff --git a/module/network/RequestFactory.py b/pyload/network/RequestFactory.py
index 579eafea7..579eafea7 100644
--- a/module/network/RequestFactory.py
+++ b/pyload/network/RequestFactory.py
diff --git a/module/network/XDCCRequest.py b/pyload/network/XDCCRequest.py
index c49f418c4..c49f418c4 100644
--- a/module/network/XDCCRequest.py
+++ b/pyload/network/XDCCRequest.py
diff --git a/module/network/__init__.py b/pyload/network/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/network/__init__.py
+++ b/pyload/network/__init__.py
diff --git a/module/plugins/Account.py b/pyload/plugin/Account.py
index f8014908f..f8014908f 100644
--- a/module/plugins/Account.py
+++ b/pyload/plugin/Account.py
diff --git a/pyload/plugin/Addon.py b/pyload/plugin/Addon.py
new file mode 100644
index 000000000..3525d4e4d
--- /dev/null
+++ b/pyload/plugin/Addon.py
@@ -0,0 +1,182 @@
+# -*- coding: utf-8 -*-
+
+from traceback import print_exc
+
+from pyload.plugin.Plugin import Base
+from pyload.utils import has_method
+
+
+class Expose(object):
+ """ used for decoration to declare rpc services """
+
+ def __new__(cls, f, *args, **kwargs):
+ addonManager.addRPC(f.__module__, f.func_name, f.func_doc)
+ return f
+
+
+def threaded(fn):
+
+ def run(*args,**kwargs):
+ addonManager.startThread(fn, *args, **kwargs)
+
+ return run
+
+
+class Addon(Base):
+ __name__ = "Addon"
+ __type__ = "addon"
+ __version__ = "0.01"
+
+ __config__ = [] #: [("name", "type", "desc", "default")]
+
+ __description__ = """Base addon plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("mkaay", "mkaay@mkaay.de"),
+ ("RaNaN", "RaNaN@pyload.org")]
+
+
+ #: automatically register event listeners for functions, attribute will be deleted dont use it yourself
+ event_map = {}
+
+ # Deprecated alternative to event_map
+ #: List of events the plugin can handle, name the functions exactly like eventname.
+ event_list = [] #@NOTE: dont make duplicate entries in event_map
+
+
+ def __init__(self, core, manager):
+ Base.__init__(self, core)
+
+ #: Provide information in dict here, usable by API `getInfo`
+ self.info = {}
+
+ #: Callback of periodical job task, used by AddonManager
+ self.cb = None
+ self.interval = 60
+
+ #: `AddonManager`
+ self.manager = manager
+
+ #register events
+ if self.event_map:
+ for event, funcs in self.event_map.iteritems():
+ if type(funcs) in (list, tuple):
+ for f in funcs:
+ self.manager.addEvent(event, getattr(self,f))
+ else:
+ self.manager.addEvent(event, getattr(self,funcs))
+
+ #delete for various reasons
+ self.event_map = None
+
+ if self.event_list:
+ for f in self.event_list:
+ self.manager.addEvent(f, getattr(self,f))
+
+ self.event_list = None
+
+ self.setup()
+
+ # self.initPeriodical()
+
+
+ def initPeriodical(self, delay=0, threaded=False):
+ self.cb = self.core.scheduler.addJob(delay, self._periodical, args=[threaded], threaded=threaded)
+
+
+ def _periodical(self, threaded):
+ if self.interval < 0:
+ self.cb = None
+ return
+
+ try:
+ self.periodical()
+
+ except Exception, e:
+ self.logError(_("Error executing addon: %s") % e)
+ if self.core.debug:
+ print_exc()
+
+ self.cb = self.core.scheduler.addJob(self.interval, self._periodical, threaded=threaded)
+
+
+ def __repr__(self):
+ return "<Addon %s>" % self.__name__
+
+
+ def setup(self):
+ """ more init stuff if needed """
+ pass
+
+
+ def deactivate(self):
+ """ called when addon was deactivated """
+ if has_method(self.__class__, "unload"):
+ self.unload()
+
+ def unload(self): # Deprecated, use method deactivate() instead
+ pass
+
+
+ def isActivated(self):
+ """ checks if addon is activated"""
+ return self.core.config.getPlugin(self.__name__, "activated")
+
+
+ # Event methods - overwrite these if needed
+ def activate(self):
+ """ called when addon was activated """
+ if has_method(self.__class__, "coreReady"):
+ self.coreReady()
+
+ def coreReady(self): # Deprecated, use method activate() instead
+ pass
+
+
+ def exit(self):
+ """ called by core.shutdown just before pyLoad exit """
+ if has_method(self.__class__, "coreExiting"):
+ self.coreExiting()
+
+ def coreExiting(self): # Deprecated, use method exit() instead
+ pass
+
+
+ def downloadPreparing(self, pyfile):
+ pass
+
+
+ def downloadFinished(self, pyfile):
+ pass
+
+
+ def downloadFailed(self, pyfile):
+ pass
+
+
+ def packageFinished(self, pypack):
+ pass
+
+
+ def beforeReconnecting(self, ip):
+ pass
+
+
+ def afterReconnecting(self, ip):
+ pass
+
+
+ def periodical(self):
+ pass
+
+
+ def captchaTask(self, task):
+ """ new captcha task for the plugin, it MUST set the handler and timeout or will be ignored """
+ pass
+
+
+ def captchaCorrect(self, task):
+ pass
+
+
+ def captchaInvalid(self, task):
+ pass
diff --git a/pyload/plugin/Captcha.py b/pyload/plugin/Captcha.py
new file mode 100644
index 000000000..36b60f026
--- /dev/null
+++ b/pyload/plugin/Captcha.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.Plugin import Base
+
+
+#@TODO: Extend Plugin class; remove all `html` args
+class Captcha(Base):
+ __name__ = "Captcha"
+ __type__ = "captcha"
+ __version__ = "0.25"
+
+ __description__ = """Base captcha service plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ def __init__(self, plugin):
+ self.plugin = plugin
+ self.key = None #: last key detected
+ super(CaptchaService, self).__init__(plugin.core)
+
+
+ def detect_key(self, html=None):
+ raise NotImplementedError
+
+
+ def challenge(self, key=None, html=None):
+ raise NotImplementedError
+
+
+ def result(self, server, challenge):
+ raise NotImplementedError
diff --git a/module/plugins/Container.py b/pyload/plugin/Container.py
index bfc5713a7..bfc5713a7 100644
--- a/module/plugins/Container.py
+++ b/pyload/plugin/Container.py
diff --git a/module/plugins/Crypter.py b/pyload/plugin/Crypter.py
index f93ee254a..f93ee254a 100644
--- a/module/plugins/Crypter.py
+++ b/pyload/plugin/Crypter.py
diff --git a/pyload/plugin/Extractor.py b/pyload/plugin/Extractor.py
new file mode 100644
index 000000000..27573f860
--- /dev/null
+++ b/pyload/plugin/Extractor.py
@@ -0,0 +1,140 @@
+# -*- coding: utf-8 -*-
+
+import os
+
+from pyload.datatype.File import PyFile
+from pyload.plugin.Plugin import Base
+
+
+class ArchiveError(Exception):
+ pass
+
+
+class CRCError(Exception):
+ pass
+
+
+class PasswordError(Exception):
+ pass
+
+
+class Extractor(Base):
+ __name__ = "Extractor"
+ __version__ = "0.20"
+
+ __description__ = """Base extractor plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "ranan@pyload.org"),
+ ("Walter Purcaro", "vuolter@gmail.com"),
+ ("Immenz", "immenz@gmx.net")]
+
+
+ EXTENSIONS = []
+ VERSION = ""
+
+
+ @classmethod
+ def isArchive(cls, filename):
+ name = os.path.basename(filename).lower()
+ return any(name.endswith(ext) for ext in cls.EXTENSIONS) and not cls.isMultipart(filename)
+
+
+ @classmethod
+ def isMultipart(cls,filename):
+ return False
+
+
+ @classmethod
+ def isUsable(cls):
+ """ Check if system statisfy dependencies
+ :return: boolean
+ """
+ return None
+
+
+ @classmethod
+ def getTargets(cls, files_ids):
+ """ Filter suited targets from list of filename id tuple list
+ :param files_ids: List of filepathes
+ :return: List of targets, id tuple list
+ """
+ return [(fname, id, fout) for fname, id, fout in files_ids if cls.isArchive(fname)]
+
+
+ def __init__(self, manager, filename, out,
+ fullpath=True,
+ overwrite=False,
+ excludefiles=[],
+ renice=0,
+ delete=False,
+ keepbroken=False,
+ fid=None):
+ """ Initialize extractor for specific file """
+ self.manager = manager
+ self.filename = filename
+ self.out = out
+ self.fullpath = fullpath
+ self.overwrite = overwrite
+ self.excludefiles = excludefiles
+ self.renice = renice
+ self.delete = delete
+ self.keepbroken = keepbroken
+ self.files = [] #: Store extracted files here
+
+ pyfile = self.manager.core.files.getFile(fid) if fid else None
+ self.notifyProgress = lambda x: pyfile.setProgress(x) if pyfile else lambda x: None
+
+
+ def init(self):
+ """ Initialize additional data structures """
+ pass
+
+
+ def check(self):
+ """Check if password if needed. Raise ArchiveError if integrity is
+ questionable.
+
+ :return: boolean
+ :raises ArchiveError
+ """
+ raise PasswordError
+
+
+ def isPassword(self, password):
+ """ Check if the given password is/might be correct.
+ If it can not be decided at this point return true.
+
+ :param password:
+ :return: boolean
+ """
+ return None
+
+
+ def repair(self):
+ return None
+
+
+ def extract(self, password=None):
+ """Extract the archive. Raise specific errors in case of failure.
+
+ :param progress: Progress function, call this to update status
+ :param password password to use
+ :raises PasswordError
+ :raises CRCError
+ :raises ArchiveError
+ :return:
+ """
+ raise NotImplementedError
+
+
+ def getDeleteFiles(self):
+ """Return list of files to delete, do *not* delete them here.
+
+ :return: List with paths of files to delete
+ """
+ return [self.filename]
+
+
+ def list(self, password=None):
+ """Populate self.files at some point while extracting"""
+ return self.files
diff --git a/pyload/plugin/Hook.py b/pyload/plugin/Hook.py
new file mode 100644
index 000000000..58dda9d8b
--- /dev/null
+++ b/pyload/plugin/Hook.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.Addon import Addon, threaded
+
+
+class Hook(Addon):
+ __name__ = "Hook"
+ __type__ = "hook"
+ __version__ = "0.03"
+
+ __config__ = [] #: [("name", "type", "desc", "default")]
+
+ __description__ = """Base hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
diff --git a/module/plugins/Hoster.py b/pyload/plugin/Hoster.py
index 2d43ee845..2d43ee845 100644
--- a/module/plugins/Hoster.py
+++ b/pyload/plugin/Hoster.py
diff --git a/pyload/plugin/OCR.py b/pyload/plugin/OCR.py
new file mode 100644
index 000000000..623f02865
--- /dev/null
+++ b/pyload/plugin/OCR.py
@@ -0,0 +1,319 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+try:
+ from PIL import Image, GifImagePlugin, JpegImagePlugin, PngImagePlugin, TiffImagePlugin
+
+except ImportError:
+ import Image, GifImagePlugin, JpegImagePlugin, PngImagePlugin, TiffImagePlugin
+
+import logging
+import os
+import subprocess
+#import tempfile
+
+from pyload.plugin.Plugin import Base
+from pyload.utils import safe_join
+
+
+class OCR(Base):
+ __name__ = "OCR"
+ __type__ = "ocr"
+ __version__ = "0.11"
+
+ __description__ = """OCR base plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("pyLoad Team", "admin@pyload.org")]
+
+
+ def __init__(self):
+ self.logger = logging.getLogger("log")
+
+
+ def load_image(self, image):
+ self.image = Image.open(image)
+ self.pixels = self.image.load()
+ self.result_captcha = ''
+
+
+ def deactivate(self):
+ """delete all tmp images"""
+ pass
+
+
+ def threshold(self, value):
+ self.image = self.image.point(lambda a: a * value + 10)
+
+
+ def run(self, command):
+ """Run a command"""
+
+ popen = subprocess.Popen(command, bufsize=-1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ popen.wait()
+ output = popen.stdout.read() + " | " + popen.stderr.read()
+ popen.stdout.close()
+ popen.stderr.close()
+ self.logger.debug("Tesseract ReturnCode %s Output: %s" % (popen.returncode, output))
+
+
+ def run_tesser(self, subset=False, digits=True, lowercase=True, uppercase=True):
+ #tmpTif = tempfile.NamedTemporaryFile(suffix=".tif")
+ try:
+ tmpTif = open(safe_join("tmp", "tmpTif_%s.tif" % self.__name__), "wb")
+ tmpTif.close()
+
+ #tmpTxt = tempfile.NamedTemporaryFile(suffix=".txt")
+ tmpTxt = open(safe_join("tmp", "tmpTxt_%s.txt" % self.__name__), "wb")
+ tmpTxt.close()
+
+ except IOError, e:
+ self.logError(e)
+ return
+
+ self.logger.debug("save tiff")
+ self.image.save(tmpTif.name, 'TIFF')
+
+ if os.name == "nt":
+ tessparams = [os.path.join(pypath, "tesseract", "tesseract.exe")]
+ else:
+ tessparams = ["tesseract"]
+
+ tessparams.extend([os.path.abspath(tmpTif.name), os.path.abspath(tmpTxt.name).replace(".txt", "")] )
+
+ if subset and (digits or lowercase or uppercase):
+ #tmpSub = tempfile.NamedTemporaryFile(suffix=".subset")
+ with open(safe_join("tmp", "tmpSub_%s.subset" % self.__name__), "wb") as tmpSub:
+ tmpSub.write("tessedit_char_whitelist ")
+
+ if digits:
+ tmpSub.write("0123456789")
+ if lowercase:
+ tmpSub.write("abcdefghijklmnopqrstuvwxyz")
+ if uppercase:
+ tmpSub.write("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
+
+ tmpSub.write("\n")
+ tessparams.append("nobatch")
+ tessparams.append(os.path.abspath(tmpSub.name))
+
+ self.logger.debug("run tesseract")
+ self.run(tessparams)
+ self.logger.debug("read txt")
+
+ try:
+ with open(tmpTxt.name, 'r') as f:
+ self.result_captcha = f.read().replace("\n", "")
+ except Exception:
+ self.result_captcha = ""
+
+ self.logger.debug(self.result_captcha)
+ try:
+ os.remove(tmpTif.name)
+ os.remove(tmpTxt.name)
+ if subset and (digits or lowercase or uppercase):
+ os.remove(tmpSub.name)
+ except Exception:
+ pass
+
+
+ def get_captcha(self, name):
+ raise NotImplementedError
+
+
+ def to_greyscale(self):
+ if self.image.mode != 'L':
+ self.image = self.image.convert('L')
+
+ self.pixels = self.image.load()
+
+
+ def eval_black_white(self, limit):
+ self.pixels = self.image.load()
+ w, h = self.image.size
+ for x in xrange(w):
+ for y in xrange(h):
+ if self.pixels[x, y] > limit:
+ self.pixels[x, y] = 255
+ else:
+ self.pixels[x, y] = 0
+
+
+ def clean(self, allowed):
+ pixels = self.pixels
+
+ w, h = self.image.size
+
+ for x in xrange(w):
+ for y in xrange(h):
+ if pixels[x, y] == 255:
+ continue
+ # No point in processing white pixels since we only want to remove black pixel
+ count = 0
+
+ try:
+ if pixels[x - 1, y - 1] != 255:
+ count += 1
+ if pixels[x - 1, y] != 255:
+ count += 1
+ if pixels[x - 1, y + 1] != 255:
+ count += 1
+ if pixels[x, y + 1] != 255:
+ count += 1
+ if pixels[x + 1, y + 1] != 255:
+ count += 1
+ if pixels[x + 1, y] != 255:
+ count += 1
+ if pixels[x + 1, y - 1] != 255:
+ count += 1
+ if pixels[x, y - 1] != 255:
+ count += 1
+ except Exception:
+ pass
+
+ # not enough neighbors are dark pixels so mark this pixel
+ # to be changed to white
+ if count < allowed:
+ pixels[x, y] = 1
+
+ # second pass: this time set all 1's to 255 (white)
+ for x in xrange(w):
+ for y in xrange(h):
+ if pixels[x, y] == 1:
+ pixels[x, y] = 255
+
+ self.pixels = pixels
+
+
+ def derotate_by_average(self):
+ """rotate by checking each angle and guess most suitable"""
+
+ w, h = self.image.size
+ pixels = self.pixels
+
+ for x in xrange(w):
+ for y in xrange(h):
+ if pixels[x, y] == 0:
+ pixels[x, y] = 155
+
+ highest = {}
+ counts = {}
+
+ for angle in xrange(-45, 45):
+
+ tmpimage = self.image.rotate(angle)
+
+ pixels = tmpimage.load()
+
+ w, h = self.image.size
+
+ for x in xrange(w):
+ for y in xrange(h):
+ if pixels[x, y] == 0:
+ pixels[x, y] = 255
+
+ count = {}
+
+ for x in xrange(w):
+ count[x] = 0
+ for y in xrange(h):
+ if pixels[x, y] == 155:
+ count[x] += 1
+
+ sum = 0
+ cnt = 0
+
+ for x in count.values():
+ if x != 0:
+ sum += x
+ cnt += 1
+
+ avg = sum / cnt
+ counts[angle] = cnt
+ highest[angle] = 0
+ for x in count.values():
+ if x > highest[angle]:
+ highest[angle] = x
+
+ highest[angle] = highest[angle] - avg
+
+ hkey = 0
+ hvalue = 0
+
+ for key, value in highest.iteritems():
+ if value > hvalue:
+ hkey = key
+ hvalue = value
+
+ self.image = self.image.rotate(hkey)
+ pixels = self.image.load()
+
+ for x in xrange(w):
+ for y in xrange(h):
+ if pixels[x, y] == 0:
+ pixels[x, y] = 255
+
+ if pixels[x, y] == 155:
+ pixels[x, y] = 0
+
+ self.pixels = pixels
+
+
+ def split_captcha_letters(self):
+ captcha = self.image
+ started = False
+ letters = []
+ width, height = captcha.size
+ bottomY, topY = 0, height
+ pixels = captcha.load()
+
+ for x in xrange(width):
+ black_pixel_in_col = False
+ for y in xrange(height):
+ if pixels[x, y] != 255:
+ if not started:
+ started = True
+ firstX = x
+ lastX = x
+
+ if y > bottomY:
+ bottomY = y
+ if y < topY:
+ topY = y
+ if x > lastX:
+ lastX = x
+
+ black_pixel_in_col = True
+
+ if black_pixel_in_col is False and started is True:
+ rect = (firstX, topY, lastX, bottomY)
+ new_captcha = captcha.crop(rect)
+
+ w, h = new_captcha.size
+ if w > 5 and h > 5:
+ letters.append(new_captcha)
+
+ started = False
+ bottomY, topY = 0, height
+
+ return letters
+
+
+ def correct(self, values, var=None):
+ if var:
+ result = var
+ else:
+ result = self.result_captcha
+
+ for key, item in values.iteritems():
+
+ if key.__class__ == str:
+ result = result.replace(key, item)
+ else:
+ for expr in key:
+ result = result.replace(expr, item)
+
+ if var:
+ return result
+ else:
+ self.result_captcha = result
diff --git a/module/plugins/Plugin.py b/pyload/plugin/Plugin.py
index 0a9c647fb..0a9c647fb 100644
--- a/module/plugins/Plugin.py
+++ b/pyload/plugin/Plugin.py
diff --git a/module/plugins/__init__.py b/pyload/plugin/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/plugins/__init__.py
+++ b/pyload/plugin/__init__.py
diff --git a/module/plugins/accounts/AlldebridCom.py b/pyload/plugin/account/AlldebridCom.py
index 7fc11e343..7fc11e343 100644
--- a/module/plugins/accounts/AlldebridCom.py
+++ b/pyload/plugin/account/AlldebridCom.py
diff --git a/pyload/plugin/account/BackinNet.py b/pyload/plugin/account/BackinNet.py
new file mode 100644
index 000000000..ac751c8fb
--- /dev/null
+++ b/pyload/plugin/account/BackinNet.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSAccount import XFSAccount
+
+
+class BackinNet(XFSAccount):
+ __name__ = "BackinNet"
+ __type__ = "account"
+ __version__ = "0.01"
+
+ __description__ = """Backin.net account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ HOSTER_DOMAIN = "backin.net"
diff --git a/module/plugins/accounts/BillionuploadsCom.py b/pyload/plugin/account/BillionuploadsCom.py
index a3325c427..a3325c427 100644
--- a/module/plugins/accounts/BillionuploadsCom.py
+++ b/pyload/plugin/account/BillionuploadsCom.py
diff --git a/module/plugins/accounts/BitshareCom.py b/pyload/plugin/account/BitshareCom.py
index 4774b9062..4774b9062 100644
--- a/module/plugins/accounts/BitshareCom.py
+++ b/pyload/plugin/account/BitshareCom.py
diff --git a/module/plugins/accounts/CatShareNet.py b/pyload/plugin/account/CatShareNet.py
index a604ebff1..a604ebff1 100644
--- a/module/plugins/accounts/CatShareNet.py
+++ b/pyload/plugin/account/CatShareNet.py
diff --git a/pyload/plugin/account/CloudzillaTo.py b/pyload/plugin/account/CloudzillaTo.py
new file mode 100644
index 000000000..a07621234
--- /dev/null
+++ b/pyload/plugin/account/CloudzillaTo.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.Account import Account
+
+
+class CloudzillaTo(Account):
+ __name__ = "CloudzillaTo"
+ __type__ = "account"
+ __version__ = "0.02"
+
+ __description__ = """Cloudzilla.to account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ PREMIUM_PATTERN = r'<h2>account type</h2>\s*Premium Account'
+
+
+ def loadAccountInfo(self, user, req):
+ html = req.load("http://www.cloudzilla.to/")
+
+ premium = True if re.search(self.PREMIUM_PATTERN, html) else False
+
+ return {'validuntil': -1, 'trafficleft': -1, 'premium': premium}
+
+
+ def login(self, user, data, req):
+ html = req.load("http://www.cloudzilla.to/",
+ post={'lusername': user,
+ 'lpassword': data['password'],
+ 'w' : "dologin"},
+ decode=True)
+
+ if "ERROR" in html:
+ self.wrongPassword()
diff --git a/module/plugins/accounts/CramitIn.py b/pyload/plugin/account/CramitIn.py
index 21503f625..21503f625 100644
--- a/module/plugins/accounts/CramitIn.py
+++ b/pyload/plugin/account/CramitIn.py
diff --git a/module/plugins/accounts/CzshareCom.py b/pyload/plugin/account/CzshareCom.py
index dfe78c21c..dfe78c21c 100644
--- a/module/plugins/accounts/CzshareCom.py
+++ b/pyload/plugin/account/CzshareCom.py
diff --git a/module/plugins/accounts/DebridItaliaCom.py b/pyload/plugin/account/DebridItaliaCom.py
index de97f6e64..de97f6e64 100644
--- a/module/plugins/accounts/DebridItaliaCom.py
+++ b/pyload/plugin/account/DebridItaliaCom.py
diff --git a/module/plugins/accounts/DepositfilesCom.py b/pyload/plugin/account/DepositfilesCom.py
index b3e896d31..b3e896d31 100644
--- a/module/plugins/accounts/DepositfilesCom.py
+++ b/pyload/plugin/account/DepositfilesCom.py
diff --git a/pyload/plugin/account/DropboxCom.py b/pyload/plugin/account/DropboxCom.py
new file mode 100644
index 000000000..862b7a8df
--- /dev/null
+++ b/pyload/plugin/account/DropboxCom.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class DropboxCom(SimpleHoster):
+ __name__ = "DropboxCom"
+ __type__ = "hoster"
+ __version__ = "0.04"
+
+ __pattern__ = r'https?://(?:www\.)?dropbox\.com/.+'
+
+ __description__ = """Dropbox.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
+
+
+ NAME_PATTERN = r'<title>Dropbox - (?P<N>.+?)<'
+ SIZE_PATTERN = r'&nbsp;&middot;&nbsp; (?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+
+ OFFLINE_PATTERN = r'<title>Dropbox - (404|Shared link error)<'
+
+ COOKIES = [("dropbox.com", "lang", "en")]
+
+
+ def setup(self):
+ self.multiDL = True
+ self.chunkLimit = 1
+ self.resumeDownload = True
+
+
+ def handleFree(self, pyfile):
+ self.download(pyfile.url, get={'dl': "1"})
diff --git a/module/plugins/accounts/EasybytezCom.py b/pyload/plugin/account/EasybytezCom.py
index c7d717474..c7d717474 100644
--- a/module/plugins/accounts/EasybytezCom.py
+++ b/pyload/plugin/account/EasybytezCom.py
diff --git a/module/plugins/accounts/EuroshareEu.py b/pyload/plugin/account/EuroshareEu.py
index b37fc68fa..b37fc68fa 100644
--- a/module/plugins/accounts/EuroshareEu.py
+++ b/pyload/plugin/account/EuroshareEu.py
diff --git a/pyload/plugin/account/ExashareCom.py b/pyload/plugin/account/ExashareCom.py
new file mode 100644
index 000000000..efd2587c0
--- /dev/null
+++ b/pyload/plugin/account/ExashareCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSAccount import XFSAccount
+
+
+class ExashareCom(XFSAccount):
+ __name__ = "ExashareCom"
+ __type__ = "account"
+ __version__ = "0.01"
+
+ __description__ = """Exashare.com account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ HOSTER_DOMAIN = "exashare.com"
diff --git a/module/plugins/accounts/FastixRu.py b/pyload/plugin/account/FastixRu.py
index 69f78c3d9..69f78c3d9 100644
--- a/module/plugins/accounts/FastixRu.py
+++ b/pyload/plugin/account/FastixRu.py
diff --git a/module/plugins/accounts/FastshareCz.py b/pyload/plugin/account/FastshareCz.py
index 8fe98438b..8fe98438b 100644
--- a/module/plugins/accounts/FastshareCz.py
+++ b/pyload/plugin/account/FastshareCz.py
diff --git a/module/plugins/accounts/File4SafeCom.py b/pyload/plugin/account/File4SafeCom.py
index c48956d38..c48956d38 100644
--- a/module/plugins/accounts/File4SafeCom.py
+++ b/pyload/plugin/account/File4SafeCom.py
diff --git a/module/plugins/accounts/FileParadoxIn.py b/pyload/plugin/account/FileParadoxIn.py
index 02b923519..02b923519 100644
--- a/module/plugins/accounts/FileParadoxIn.py
+++ b/pyload/plugin/account/FileParadoxIn.py
diff --git a/module/plugins/accounts/FilecloudIo.py b/pyload/plugin/account/FilecloudIo.py
index 6d2dcb92a..6d2dcb92a 100644
--- a/module/plugins/accounts/FilecloudIo.py
+++ b/pyload/plugin/account/FilecloudIo.py
diff --git a/module/plugins/accounts/FilefactoryCom.py b/pyload/plugin/account/FilefactoryCom.py
index 3395b3f90..3395b3f90 100644
--- a/module/plugins/accounts/FilefactoryCom.py
+++ b/pyload/plugin/account/FilefactoryCom.py
diff --git a/module/plugins/accounts/FilejungleCom.py b/pyload/plugin/account/FilejungleCom.py
index 2c476bffb..2c476bffb 100644
--- a/module/plugins/accounts/FilejungleCom.py
+++ b/pyload/plugin/account/FilejungleCom.py
diff --git a/module/plugins/accounts/FileomCom.py b/pyload/plugin/account/FileomCom.py
index 36a11e411..36a11e411 100644
--- a/module/plugins/accounts/FileomCom.py
+++ b/pyload/plugin/account/FileomCom.py
diff --git a/module/plugins/accounts/FilerNet.py b/pyload/plugin/account/FilerNet.py
index f3cc42367..f3cc42367 100644
--- a/module/plugins/accounts/FilerNet.py
+++ b/pyload/plugin/account/FilerNet.py
diff --git a/module/plugins/accounts/FilerioCom.py b/pyload/plugin/account/FilerioCom.py
index 1d9f8744b..1d9f8744b 100644
--- a/module/plugins/accounts/FilerioCom.py
+++ b/pyload/plugin/account/FilerioCom.py
diff --git a/module/plugins/accounts/FilesMailRu.py b/pyload/plugin/account/FilesMailRu.py
index e6afd0168..e6afd0168 100644
--- a/module/plugins/accounts/FilesMailRu.py
+++ b/pyload/plugin/account/FilesMailRu.py
diff --git a/module/plugins/accounts/FileserveCom.py b/pyload/plugin/account/FileserveCom.py
index 9aab88d2b..9aab88d2b 100644
--- a/module/plugins/accounts/FileserveCom.py
+++ b/pyload/plugin/account/FileserveCom.py
diff --git a/module/plugins/accounts/FourSharedCom.py b/pyload/plugin/account/FourSharedCom.py
index 127f9d58a..127f9d58a 100644
--- a/module/plugins/accounts/FourSharedCom.py
+++ b/pyload/plugin/account/FourSharedCom.py
diff --git a/module/plugins/accounts/FreakshareCom.py b/pyload/plugin/account/FreakshareCom.py
index 9c61ac513..9c61ac513 100644
--- a/module/plugins/accounts/FreakshareCom.py
+++ b/pyload/plugin/account/FreakshareCom.py
diff --git a/module/plugins/accounts/FreeWayMe.py b/pyload/plugin/account/FreeWayMe.py
index dcd9d34cf..dcd9d34cf 100644
--- a/module/plugins/accounts/FreeWayMe.py
+++ b/pyload/plugin/account/FreeWayMe.py
diff --git a/module/plugins/accounts/FshareVn.py b/pyload/plugin/account/FshareVn.py
index 282a17751..282a17751 100644
--- a/module/plugins/accounts/FshareVn.py
+++ b/pyload/plugin/account/FshareVn.py
diff --git a/module/plugins/accounts/Ftp.py b/pyload/plugin/account/Ftp.py
index 67cde2cdd..67cde2cdd 100644
--- a/module/plugins/accounts/Ftp.py
+++ b/pyload/plugin/account/Ftp.py
diff --git a/module/plugins/accounts/HellshareCz.py b/pyload/plugin/account/HellshareCz.py
index 94467b375..94467b375 100644
--- a/module/plugins/accounts/HellshareCz.py
+++ b/pyload/plugin/account/HellshareCz.py
diff --git a/module/plugins/accounts/Http.py b/pyload/plugin/account/Http.py
index 2571ef712..2571ef712 100644
--- a/module/plugins/accounts/Http.py
+++ b/pyload/plugin/account/Http.py
diff --git a/module/plugins/accounts/HugefilesNet.py b/pyload/plugin/account/HugefilesNet.py
index eb383fb17..eb383fb17 100644
--- a/module/plugins/accounts/HugefilesNet.py
+++ b/pyload/plugin/account/HugefilesNet.py
diff --git a/module/plugins/accounts/HundredEightyUploadCom.py b/pyload/plugin/account/HundredEightyUploadCom.py
index 72185a4bb..72185a4bb 100644
--- a/module/plugins/accounts/HundredEightyUploadCom.py
+++ b/pyload/plugin/account/HundredEightyUploadCom.py
diff --git a/pyload/plugin/account/JunkyvideoCom.py b/pyload/plugin/account/JunkyvideoCom.py
new file mode 100644
index 000000000..3380b8dc7
--- /dev/null
+++ b/pyload/plugin/account/JunkyvideoCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSAccount import XFSAccount
+
+
+class JunkyvideoCom(XFSAccount):
+ __name__ = "JunkyvideoCom"
+ __type__ = "account"
+ __version__ = "0.01"
+
+ __description__ = """Junkyvideo.com account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ HOSTER_DOMAIN = "junkyvideo.com"
diff --git a/module/plugins/accounts/JunocloudMe.py b/pyload/plugin/account/JunocloudMe.py
index 0ffa92eb6..0ffa92eb6 100644
--- a/module/plugins/accounts/JunocloudMe.py
+++ b/pyload/plugin/account/JunocloudMe.py
diff --git a/module/plugins/accounts/Keep2ShareCc.py b/pyload/plugin/account/Keep2ShareCc.py
index 7ed15dc62..7ed15dc62 100644
--- a/module/plugins/accounts/Keep2ShareCc.py
+++ b/pyload/plugin/account/Keep2ShareCc.py
diff --git a/module/plugins/accounts/LetitbitNet.py b/pyload/plugin/account/LetitbitNet.py
index d0f08d0bb..d0f08d0bb 100644
--- a/module/plugins/accounts/LetitbitNet.py
+++ b/pyload/plugin/account/LetitbitNet.py
diff --git a/module/plugins/accounts/LinestorageCom.py b/pyload/plugin/account/LinestorageCom.py
index 7a5d63a47..7a5d63a47 100644
--- a/module/plugins/accounts/LinestorageCom.py
+++ b/pyload/plugin/account/LinestorageCom.py
diff --git a/module/plugins/accounts/LinksnappyCom.py b/pyload/plugin/account/LinksnappyCom.py
index 0b1176ee9..0b1176ee9 100644
--- a/module/plugins/accounts/LinksnappyCom.py
+++ b/pyload/plugin/account/LinksnappyCom.py
diff --git a/module/plugins/accounts/MegaDebridEu.py b/pyload/plugin/account/MegaDebridEu.py
index c2e64bcc7..c2e64bcc7 100644
--- a/module/plugins/accounts/MegaDebridEu.py
+++ b/pyload/plugin/account/MegaDebridEu.py
diff --git a/module/plugins/accounts/MegaRapidCz.py b/pyload/plugin/account/MegaRapidCz.py
index 5596fd623..5596fd623 100644
--- a/module/plugins/accounts/MegaRapidCz.py
+++ b/pyload/plugin/account/MegaRapidCz.py
diff --git a/module/plugins/accounts/MegasharesCom.py b/pyload/plugin/account/MegasharesCom.py
index 53b854f65..53b854f65 100644
--- a/module/plugins/accounts/MegasharesCom.py
+++ b/pyload/plugin/account/MegasharesCom.py
diff --git a/module/plugins/accounts/MovReelCom.py b/pyload/plugin/account/MovReelCom.py
index 4d2855de1..4d2855de1 100644
--- a/module/plugins/accounts/MovReelCom.py
+++ b/pyload/plugin/account/MovReelCom.py
diff --git a/pyload/plugin/account/MultihostersCom.py b/pyload/plugin/account/MultihostersCom.py
new file mode 100644
index 000000000..3f5d90c4e
--- /dev/null
+++ b/pyload/plugin/account/MultihostersCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.account.ZeveraCom import ZeveraCom
+
+
+class MultihostersCom(ZeveraCom):
+ __name__ = "MultihostersCom"
+ __type__ = "account"
+ __version__ = "0.03"
+
+ __description__ = """Multihosters.com account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("tjeh", "tjeh@gmx.net")]
+
+
+ HOSTER_DOMAIN = "multihosters.com"
diff --git a/module/plugins/accounts/MultishareCz.py b/pyload/plugin/account/MultishareCz.py
index 9b4f4447b..9b4f4447b 100644
--- a/module/plugins/accounts/MultishareCz.py
+++ b/pyload/plugin/account/MultishareCz.py
diff --git a/module/plugins/accounts/MyfastfileCom.py b/pyload/plugin/account/MyfastfileCom.py
index 838a1eefd..838a1eefd 100644
--- a/module/plugins/accounts/MyfastfileCom.py
+++ b/pyload/plugin/account/MyfastfileCom.py
diff --git a/module/plugins/accounts/NetloadIn.py b/pyload/plugin/account/NetloadIn.py
index 68982e828..68982e828 100644
--- a/module/plugins/accounts/NetloadIn.py
+++ b/pyload/plugin/account/NetloadIn.py
diff --git a/pyload/plugin/account/NoPremiumPl.py b/pyload/plugin/account/NoPremiumPl.py
new file mode 100644
index 000000000..929e8f7d9
--- /dev/null
+++ b/pyload/plugin/account/NoPremiumPl.py
@@ -0,0 +1,82 @@
+# -*- coding: utf-8 -*-
+
+import hashlib
+
+from datetime import datetime
+from time import mktime
+
+from pyload.plugin.Account import Account
+from pyload.utils import json_loads
+
+
+class NoPremiumPl(Account):
+ __name__ = "NoPremiumPl"
+ __version__ = "0.01"
+ __type__ = "account"
+ __description__ = "NoPremium.pl account plugin"
+ __license__ = "GPLv3"
+ __authors__ = [("goddie", "dev@nopremium.pl")]
+
+ _api_url = "http://crypt.nopremium.pl"
+
+ _api_query = {
+ "site": "nopremium",
+ "username": "",
+ "password": "",
+ "output": "json",
+ "loc": "1",
+ "info": "1"
+ }
+
+ _req = None
+ _usr = None
+ _pwd = None
+
+ def loadAccountInfo(self, name, req):
+ self._req = req
+ try:
+ result = json_loads(self.runAuthQuery())
+ except Exception:
+ # todo: return or let it be thrown?
+ return
+
+ premium = False
+ valid_untill = -1
+
+ if "expire" in result.keys() and result["expire"]:
+ premium = True
+ valid_untill = mktime(datetime.fromtimestamp(int(result["expire"])).timetuple())
+ traffic_left = result["balance"] * 1024
+
+ return ({
+ "validuntil": valid_untill,
+ "trafficleft": traffic_left,
+ "premium": premium
+ })
+
+ def login(self, user, data, req):
+ self._usr = user
+ self._pwd = hashlib.sha1(hashlib.md5(data["password"]).hexdigest()).hexdigest()
+ self._req = req
+
+ try:
+ response = json_loads(self.runAuthQuery())
+ except Exception:
+ self.wrongPassword()
+
+ if "errno" in response.keys():
+ self.wrongPassword()
+ data['usr'] = self._usr
+ data['pwd'] = self._pwd
+
+ def createAuthQuery(self):
+ query = self._api_query
+ query["username"] = self._usr
+ query["password"] = self._pwd
+
+ return query
+
+ def runAuthQuery(self):
+ data = self._req.load(self._api_url, post=self.createAuthQuery())
+
+ return data \ No newline at end of file
diff --git a/module/plugins/accounts/NosuploadCom.py b/pyload/plugin/account/NosuploadCom.py
index 7fc8b49de..7fc8b49de 100644
--- a/module/plugins/accounts/NosuploadCom.py
+++ b/pyload/plugin/account/NosuploadCom.py
diff --git a/module/plugins/accounts/NovafileCom.py b/pyload/plugin/account/NovafileCom.py
index 71a7dc2dc..71a7dc2dc 100644
--- a/module/plugins/accounts/NovafileCom.py
+++ b/pyload/plugin/account/NovafileCom.py
diff --git a/module/plugins/accounts/NowVideoSx.py b/pyload/plugin/account/NowVideoSx.py
index 8359e0410..8359e0410 100644
--- a/module/plugins/accounts/NowVideoSx.py
+++ b/pyload/plugin/account/NowVideoSx.py
diff --git a/module/plugins/accounts/OboomCom.py b/pyload/plugin/account/OboomCom.py
index 012fb42c3..012fb42c3 100644
--- a/module/plugins/accounts/OboomCom.py
+++ b/pyload/plugin/account/OboomCom.py
diff --git a/module/plugins/accounts/OneFichierCom.py b/pyload/plugin/account/OneFichierCom.py
index 65ec841c4..65ec841c4 100644
--- a/module/plugins/accounts/OneFichierCom.py
+++ b/pyload/plugin/account/OneFichierCom.py
diff --git a/module/plugins/accounts/OverLoadMe.py b/pyload/plugin/account/OverLoadMe.py
index d945dd7bd..d945dd7bd 100644
--- a/module/plugins/accounts/OverLoadMe.py
+++ b/pyload/plugin/account/OverLoadMe.py
diff --git a/module/plugins/accounts/PremiumTo.py b/pyload/plugin/account/PremiumTo.py
index 04bbc10d5..04bbc10d5 100644
--- a/module/plugins/accounts/PremiumTo.py
+++ b/pyload/plugin/account/PremiumTo.py
diff --git a/module/plugins/accounts/PremiumizeMe.py b/pyload/plugin/account/PremiumizeMe.py
index 3cd15ce23..3cd15ce23 100644
--- a/module/plugins/accounts/PremiumizeMe.py
+++ b/pyload/plugin/account/PremiumizeMe.py
diff --git a/pyload/plugin/account/PutdriveCom.py b/pyload/plugin/account/PutdriveCom.py
new file mode 100644
index 000000000..b30fb6565
--- /dev/null
+++ b/pyload/plugin/account/PutdriveCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.account.ZeveraCom import ZeveraCom
+
+
+class PutdriveCom(ZeveraCom):
+ __name__ = "PutdriveCom"
+ __type__ = "account"
+ __version__ = "0.02"
+
+ __description__ = """Putdrive.com account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ HOSTER_DOMAIN = "putdrive.com"
diff --git a/module/plugins/accounts/QuickshareCz.py b/pyload/plugin/account/QuickshareCz.py
index 2bcde1c9d..2bcde1c9d 100644
--- a/module/plugins/accounts/QuickshareCz.py
+++ b/pyload/plugin/account/QuickshareCz.py
diff --git a/module/plugins/accounts/RPNetBiz.py b/pyload/plugin/account/RPNetBiz.py
index e0b35b68c..e0b35b68c 100644
--- a/module/plugins/accounts/RPNetBiz.py
+++ b/pyload/plugin/account/RPNetBiz.py
diff --git a/pyload/plugin/account/RapideoPl.py b/pyload/plugin/account/RapideoPl.py
new file mode 100644
index 000000000..b4b74fab5
--- /dev/null
+++ b/pyload/plugin/account/RapideoPl.py
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+
+import hashlib
+
+from datetime import datetime
+from time import mktime
+
+from pyload.plugin.Account import Account
+from pyload.utils import json_loads
+
+
+class RapideoPl(Account):
+ __name__ = "RapideoPl"
+ __version__ = "0.01"
+ __type__ = "account"
+ __description__ = "Rapideo.pl account plugin"
+ __license__ = "GPLv3"
+ __authors__ = [("goddie", "dev@rapideo.pl")]
+
+ _api_url = "http://enc.rapideo.pl"
+
+ _api_query = {
+ "site": "newrd",
+ "username": "",
+ "password": "",
+ "output": "json",
+ "loc": "1",
+ "info": "1"
+ }
+
+ _req = None
+ _usr = None
+ _pwd = None
+
+ def loadAccountInfo(self, name, req):
+ self._req = req
+ try:
+ result = json_loads(self.runAuthQuery())
+ except Exception:
+ # todo: return or let it be thrown?
+ return
+
+ premium = False
+ valid_untill = -1
+ if "expire" in result.keys() and result["expire"]:
+ premium = True
+ valid_untill = mktime(datetime.fromtimestamp(int(result["expire"])).timetuple())
+
+ traffic_left = result["balance"]
+
+ return ({
+ "validuntil": valid_untill,
+ "trafficleft": traffic_left,
+ "premium": premium
+ })
+
+ def login(self, user, data, req):
+ self._usr = user
+ self._pwd = hashlib.md5(data["password"]).hexdigest()
+ self._req = req
+ try:
+ response = json_loads(self.runAuthQuery())
+ except Exception:
+ self.wrongPassword()
+
+ if "errno" in response.keys():
+ self.wrongPassword()
+ data['usr'] = self._usr
+ data['pwd'] = self._pwd
+
+ def createAuthQuery(self):
+ query = self._api_query
+ query["username"] = self._usr
+ query["password"] = self._pwd
+
+ return query
+
+ def runAuthQuery(self):
+ data = self._req.load(self._api_url, post=self.createAuthQuery())
+
+ return data \ No newline at end of file
diff --git a/module/plugins/accounts/RapidfileshareNet.py b/pyload/plugin/account/RapidfileshareNet.py
index ec0bf8db4..ec0bf8db4 100644
--- a/module/plugins/accounts/RapidfileshareNet.py
+++ b/pyload/plugin/account/RapidfileshareNet.py
diff --git a/module/plugins/accounts/RapidgatorNet.py b/pyload/plugin/account/RapidgatorNet.py
index 7643f07d2..7643f07d2 100644
--- a/module/plugins/accounts/RapidgatorNet.py
+++ b/pyload/plugin/account/RapidgatorNet.py
diff --git a/pyload/plugin/account/RapiduNet.py b/pyload/plugin/account/RapiduNet.py
new file mode 100644
index 000000000..5c165f486
--- /dev/null
+++ b/pyload/plugin/account/RapiduNet.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from time import time
+
+from pyload.plugin.Account import Account
+from pyload.utils import json_loads
+
+
+class RapiduNet(Account):
+ __name__ = "RapiduNet"
+ __type__ = "account"
+ __version__ = "0.05"
+
+ __description__ = """Rapidu.net account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("prOq", None),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ PREMIUM_PATTERN = r'>Account: <b>Premium'
+
+ VALID_UNTIL_PATTERN = r'>Account: <b>\w+ \((\d+)'
+
+ TRAFFIC_LEFT_PATTERN = r'class="tipsyS"><b>(.+?)<'
+
+
+ def loadAccountInfo(self, user, req):
+ validuntil = None
+ trafficleft = -1
+ premium = False
+
+ html = req.load("https://rapidu.net/", decode=True)
+
+ if re.search(self.PREMIUM_PATTERN, html):
+ premium = True
+
+ m = re.search(self.VALID_UNTIL_PATTERN, html)
+ if m:
+ validuntil = time() + (86400 * int(m.group(1)))
+
+ m = re.search(self.TRAFFIC_LEFT_PATTERN, html)
+ if m:
+ trafficleft = self.parseTraffic(m.group(1))
+
+ return {'validuntil': validuntil, 'trafficleft': trafficleft, 'premium': premium}
+
+
+ def login(self, user, data, req):
+ req.load("https://rapidu.net/ajax.php",
+ get={'a': "getChangeLang"},
+ post={'_go' : "",
+ 'lang': "en"})
+
+ json = json_loads(req.load("https://rapidu.net/ajax.php",
+ get={'a': "getUserLogin"},
+ post={'_go' : "",
+ 'login' : user,
+ 'pass' : data['password'],
+ 'remember': "1"}))
+
+ self.logDebug(json)
+
+ if not json['message'] == "success":
+ self.wrongPassword()
diff --git a/module/plugins/accounts/RarefileNet.py b/pyload/plugin/account/RarefileNet.py
index 1dc93681c..1dc93681c 100644
--- a/module/plugins/accounts/RarefileNet.py
+++ b/pyload/plugin/account/RarefileNet.py
diff --git a/module/plugins/accounts/RealdebridCom.py b/pyload/plugin/account/RealdebridCom.py
index 07ff70496..07ff70496 100644
--- a/module/plugins/accounts/RealdebridCom.py
+++ b/pyload/plugin/account/RealdebridCom.py
diff --git a/module/plugins/accounts/RehostTo.py b/pyload/plugin/account/RehostTo.py
index d62e1918a..d62e1918a 100644
--- a/module/plugins/accounts/RehostTo.py
+++ b/pyload/plugin/account/RehostTo.py
diff --git a/module/plugins/accounts/RyushareCom.py b/pyload/plugin/account/RyushareCom.py
index 466d971f6..466d971f6 100644
--- a/module/plugins/accounts/RyushareCom.py
+++ b/pyload/plugin/account/RyushareCom.py
diff --git a/module/plugins/accounts/SafesharingEu.py b/pyload/plugin/account/SafesharingEu.py
index f5cbf050e..f5cbf050e 100644
--- a/module/plugins/accounts/SafesharingEu.py
+++ b/pyload/plugin/account/SafesharingEu.py
diff --git a/module/plugins/accounts/SecureUploadEu.py b/pyload/plugin/account/SecureUploadEu.py
index bb47bcba3..bb47bcba3 100644
--- a/module/plugins/accounts/SecureUploadEu.py
+++ b/pyload/plugin/account/SecureUploadEu.py
diff --git a/module/plugins/accounts/SendmywayCom.py b/pyload/plugin/account/SendmywayCom.py
index d64658de3..d64658de3 100644
--- a/module/plugins/accounts/SendmywayCom.py
+++ b/pyload/plugin/account/SendmywayCom.py
diff --git a/module/plugins/accounts/ShareonlineBiz.py b/pyload/plugin/account/ShareonlineBiz.py
index 28bc3b9bc..28bc3b9bc 100644
--- a/module/plugins/accounts/ShareonlineBiz.py
+++ b/pyload/plugin/account/ShareonlineBiz.py
diff --git a/module/plugins/accounts/SimplyPremiumCom.py b/pyload/plugin/account/SimplyPremiumCom.py
index 298ad8d59..298ad8d59 100644
--- a/module/plugins/accounts/SimplyPremiumCom.py
+++ b/pyload/plugin/account/SimplyPremiumCom.py
diff --git a/module/plugins/accounts/SimplydebridCom.py b/pyload/plugin/account/SimplydebridCom.py
index a826e44c7..a826e44c7 100644
--- a/module/plugins/accounts/SimplydebridCom.py
+++ b/pyload/plugin/account/SimplydebridCom.py
diff --git a/pyload/plugin/account/SmoozedCom.py b/pyload/plugin/account/SmoozedCom.py
new file mode 100644
index 000000000..27249c7c2
--- /dev/null
+++ b/pyload/plugin/account/SmoozedCom.py
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+
+import hashlib
+
+from beaker.crypto.pbkdf2 import PBKDF2
+from time import time
+
+from pyload.utils import json_loads
+from pyload.plugin.Account import Account
+
+
+class SmoozedCom(Account):
+ __name__ = "SmoozedCom"
+ __type__ = "account"
+ __version__ = "0.03"
+
+ __description__ = """Smoozed.com account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("", "")]
+
+
+ def loadAccountInfo(self, user, req):
+ # Get user data from premiumize.me
+ status = self.getAccountStatus(user, req)
+
+ self.logDebug(status)
+
+ if status['state'] != 'ok':
+ info = {'validuntil' : None,
+ 'trafficleft': None,
+ 'premium' : False}
+ else:
+ # Parse account info
+ info = {'validuntil' : float(status["data"]["user"]["user_premium"]),
+ 'trafficleft': max(0, status["data"]["traffic"][1] - status["data"]["traffic"][0]),
+ 'session' : status["data"]["session_key"],
+ 'hosters' : [hoster["name"] for hoster in status["data"]["hoster"]]}
+
+ if info['validuntil'] < time():
+ info['premium'] = False
+ else:
+ info['premium'] = True
+
+ return info
+
+
+ def login(self, user, data, req):
+ # Get user data from premiumize.me
+ status = self.getAccountStatus(user, req)
+
+ # Check if user and password are valid
+ if status['state'] != 'ok':
+ self.wrongPassword()
+
+
+ def getAccountStatus(self, user, req):
+ password = self.getAccountData(user)['password']
+ salt = hashlib.sha256(password).hexdigest()
+ encrypted = PBKDF2(password, salt, iterations=1000).hexread(32)
+
+ return json_loads(req.load("http://www2.smoozed.com/api/login",
+ get={'auth': user, 'password': encrypted}))
diff --git a/module/plugins/accounts/StahnuTo.py b/pyload/plugin/account/StahnuTo.py
index ed8df3b77..ed8df3b77 100644
--- a/module/plugins/accounts/StahnuTo.py
+++ b/pyload/plugin/account/StahnuTo.py
diff --git a/module/plugins/accounts/StreamcloudEu.py b/pyload/plugin/account/StreamcloudEu.py
index 3ac74fbd0..3ac74fbd0 100644
--- a/module/plugins/accounts/StreamcloudEu.py
+++ b/pyload/plugin/account/StreamcloudEu.py
diff --git a/module/plugins/accounts/TurbobitNet.py b/pyload/plugin/account/TurbobitNet.py
index e3c07da2a..e3c07da2a 100644
--- a/module/plugins/accounts/TurbobitNet.py
+++ b/pyload/plugin/account/TurbobitNet.py
diff --git a/module/plugins/accounts/TusfilesNet.py b/pyload/plugin/account/TusfilesNet.py
index 84e9ef9c6..84e9ef9c6 100644
--- a/module/plugins/accounts/TusfilesNet.py
+++ b/pyload/plugin/account/TusfilesNet.py
diff --git a/module/plugins/accounts/UlozTo.py b/pyload/plugin/account/UlozTo.py
index 1570419b0..1570419b0 100644
--- a/module/plugins/accounts/UlozTo.py
+++ b/pyload/plugin/account/UlozTo.py
diff --git a/module/plugins/accounts/UnrestrictLi.py b/pyload/plugin/account/UnrestrictLi.py
index d8d7789bb..d8d7789bb 100644
--- a/module/plugins/accounts/UnrestrictLi.py
+++ b/pyload/plugin/account/UnrestrictLi.py
diff --git a/pyload/plugin/account/UploadableCh.py b/pyload/plugin/account/UploadableCh.py
new file mode 100644
index 000000000..9406118cd
--- /dev/null
+++ b/pyload/plugin/account/UploadableCh.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.Account import Account
+
+
+class UploadableCh(Account):
+ __name__ = "UploadableCh"
+ __type__ = "account"
+ __version__ = "0.03"
+
+ __description__ = """Uploadable.ch account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Sasch", "gsasch@gmail.com")]
+
+
+ def loadAccountInfo(self, user, req):
+ html = req.load("http://www.uploadable.ch/login.php")
+
+ premium = '<a href="/logout.php"' in html
+ trafficleft = -1 if premium else None
+
+ return {'validuntil': None, 'trafficleft': trafficleft, 'premium': premium} #@TODO: validuntil
+
+
+ def login(self, user, data, req):
+ html = req.load("http://www.uploadable.ch/login.php",
+ post={'userName' : user,
+ 'userPassword' : data["password"],
+ 'autoLogin' : "1",
+ 'action__login': "normalLogin"},
+ decode=True)
+
+ if "Login failed" in html:
+ self.wrongPassword()
diff --git a/module/plugins/accounts/UploadcCom.py b/pyload/plugin/account/UploadcCom.py
index 66863c456..66863c456 100644
--- a/module/plugins/accounts/UploadcCom.py
+++ b/pyload/plugin/account/UploadcCom.py
diff --git a/module/plugins/accounts/UploadedTo.py b/pyload/plugin/account/UploadedTo.py
index 3b0d957a5..3b0d957a5 100644
--- a/module/plugins/accounts/UploadedTo.py
+++ b/pyload/plugin/account/UploadedTo.py
diff --git a/module/plugins/accounts/UploadheroCom.py b/pyload/plugin/account/UploadheroCom.py
index c73fc30f5..c73fc30f5 100644
--- a/module/plugins/accounts/UploadheroCom.py
+++ b/pyload/plugin/account/UploadheroCom.py
diff --git a/module/plugins/accounts/UploadingCom.py b/pyload/plugin/account/UploadingCom.py
index 6d54469e8..6d54469e8 100644
--- a/module/plugins/accounts/UploadingCom.py
+++ b/pyload/plugin/account/UploadingCom.py
diff --git a/module/plugins/accounts/UptoboxCom.py b/pyload/plugin/account/UptoboxCom.py
index f7cb7a82e..f7cb7a82e 100644
--- a/module/plugins/accounts/UptoboxCom.py
+++ b/pyload/plugin/account/UptoboxCom.py
diff --git a/module/plugins/accounts/VidPlayNet.py b/pyload/plugin/account/VidPlayNet.py
index 390520a00..390520a00 100644
--- a/module/plugins/accounts/VidPlayNet.py
+++ b/pyload/plugin/account/VidPlayNet.py
diff --git a/pyload/plugin/account/WebshareCz.py b/pyload/plugin/account/WebshareCz.py
new file mode 100644
index 000000000..efa2a0045
--- /dev/null
+++ b/pyload/plugin/account/WebshareCz.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from hashlib import md5, sha1
+from passlib.hash import md5_crypt
+from time import mktime, strptime, time
+
+from pyload.plugin.Account import Account
+
+
+class WebshareCz(Account):
+ __name__ = "WebshareCz"
+ __type__ = "account"
+ __version__ = "0.07"
+
+ __description__ = """Webshare.cz account plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("rush", "radek.senfeld@gmail.com")]
+
+
+ VALID_UNTIL_PATTERN = r'<vip_until>(.+)</vip_until>'
+
+ TRAFFIC_LEFT_PATTERN = r'<bytes>(.+)</bytes>'
+
+
+ def loadAccountInfo(self, user, req):
+ html = req.load("https://webshare.cz/api/user_data/",
+ post={'wst': self.infos['wst']},
+ decode=True)
+
+ self.logDebug("Response: " + html)
+
+ expiredate = re.search(self.VALID_UNTIL_PATTERN, html).group(1)
+ self.logDebug("Expire date: " + expiredate)
+
+ validuntil = mktime(strptime(expiredate, "%Y-%m-%d %H:%M:%S"))
+ trafficleft = self.parseTraffic(re.search(self.TRAFFIC_LEFT_PATTERN, html).group(1))
+ premium = validuntil > time()
+
+ return {'validuntil': validuntil, 'trafficleft': -1, 'premium': premium}
+
+
+ def login(self, user, data, req):
+ salt = req.load("https://webshare.cz/api/salt/",
+ post={'username_or_email': user,
+ 'wst' : ""},
+ decode=True)
+
+ if "<status>OK</status>" not in salt:
+ self.wrongPassword()
+
+ salt = re.search('<salt>(.+)</salt>', salt).group(1)
+ password = sha1(md5_crypt.encrypt(data["password"], salt=salt)).hexdigest()
+ digest = md5(user + ":Webshare:" + password).hexdigest()
+
+ login = req.load("https://webshare.cz/api/login/",
+ post={'digest' : digest,
+ 'keep_logged_in' : 1,
+ 'password' : password,
+ 'username_or_email': user,
+ 'wst' : ""},
+ decode=True)
+
+ if "<status>OK</status>" not in login:
+ self.wrongPassword()
+
+ self.infos['wst'] = re.search('<token>(.+)</token>', login).group(1)
diff --git a/module/plugins/accounts/XFileSharingPro.py b/pyload/plugin/account/XFileSharingPro.py
index 216af5385..216af5385 100644
--- a/module/plugins/accounts/XFileSharingPro.py
+++ b/pyload/plugin/account/XFileSharingPro.py
diff --git a/module/plugins/accounts/YibaishiwuCom.py b/pyload/plugin/account/YibaishiwuCom.py
index 150b0d931..150b0d931 100644
--- a/module/plugins/accounts/YibaishiwuCom.py
+++ b/pyload/plugin/account/YibaishiwuCom.py
diff --git a/module/plugins/accounts/ZeveraCom.py b/pyload/plugin/account/ZeveraCom.py
index db23170f3..db23170f3 100644
--- a/module/plugins/accounts/ZeveraCom.py
+++ b/pyload/plugin/account/ZeveraCom.py
diff --git a/module/plugins/accounts/__init__.py b/pyload/plugin/account/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/plugins/accounts/__init__.py
+++ b/pyload/plugin/account/__init__.py
diff --git a/pyload/plugin/addon/AndroidPhoneNotify.py b/pyload/plugin/addon/AndroidPhoneNotify.py
new file mode 100644
index 000000000..2b4f8fcca
--- /dev/null
+++ b/pyload/plugin/addon/AndroidPhoneNotify.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+
+from time import time
+
+from pyload.network.RequestFactory import getURL
+from pyload.plugin.Addon import Addon
+
+
+class AndroidPhoneNotify(Addon):
+ __name__ = "AndroidPhoneNotify"
+ __type__ = "addon"
+ __version__ = "0.05"
+
+ __config__ = [("apikey" , "str" , "API key" , "" ),
+ ("notifycaptcha" , "bool", "Notify captcha request" , True ),
+ ("notifypackage" , "bool", "Notify package finished" , True ),
+ ("notifyprocessed", "bool", "Notify processed packages status" , True ),
+ ("timeout" , "int" , "Timeout between captchas in seconds" , 5 ),
+ ("force" , "bool", "Send notifications if client is connected", False)]
+
+ __description__ = """Send push notifications to your Android Phone using notifymyandroid.com"""
+ __license__ = "GPLv3"
+ __authors__ = [("Steven Kosyra", "steven.kosyra@gmail.com"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ event_list = ["allDownloadsProcessed"]
+
+
+ def setup(self):
+ self.info = {} #@TODO: Remove in 0.4.10
+ self.last_notify = 0
+
+
+ def newCaptchaTask(self, task):
+ if not self.getConfig("notifycaptcha"):
+ return False
+
+ if time() - self.last_notify < self.getConf("timeout"):
+ return False
+
+ self.notify(_("Captcha"), _("New request waiting user input"))
+
+
+ def packageFinished(self, pypack):
+ if self.getConfig("notifypackage"):
+ self.notify(_("Package finished"), pypack.name)
+
+
+ def allDownloadsProcessed(self):
+ if not self.getConfig("notifyprocessed"):
+ return False
+
+ if any(True for pdata in self.core.api.getQueue() if pdata.linksdone < pdata.linkstotal):
+ self.notify(_("Package failed"), _("One or more packages was not completed successfully"))
+ else:
+ self.notify(_("All packages finished"))
+
+
+ def notify(self, event, msg=""):
+ apikey = self.getConfig("apikey")
+
+ if not apikey:
+ return False
+
+ if self.core.isClientConnected() and not self.getConfig("force"):
+ return False
+
+ getURL("http://www.notifymyandroid.com/publicapi/notify",
+ get={'apikey' : apikey,
+ 'application': "pyLoad",
+ 'event' : event,
+ 'description': msg})
+
+ self.last_notify = time()
diff --git a/module/plugins/addon/Checksum.py b/pyload/plugin/addon/Checksum.py
index 35be60773..35be60773 100644
--- a/module/plugins/addon/Checksum.py
+++ b/pyload/plugin/addon/Checksum.py
diff --git a/pyload/plugin/addon/ClickAndLoad.py b/pyload/plugin/addon/ClickAndLoad.py
new file mode 100644
index 000000000..cd71e9972
--- /dev/null
+++ b/pyload/plugin/addon/ClickAndLoad.py
@@ -0,0 +1,119 @@
+# -*- coding: utf-8 -*-
+
+import socket
+
+from threading import Lock
+
+from pyload.plugin.Addon import Addon, threaded
+
+
+def forward(source, destination):
+ try:
+ bufsize = 1024
+ bufdata = source.recv(bufsize)
+ while bufdata:
+ destination.sendall(bufdata)
+ bufdata = source.recv(bufsize)
+ finally:
+ destination.shutdown(socket.SHUT_WR)
+
+
+#: create_connection wrapper for python 2.5 socket module
+def create_connection(address, timeout=object(), source_address=None):
+ if hasattr(socket, 'create_connection'):
+ if type(timeout) == object:
+ timeout = socket._GLOBAL_DEFAULT_TIMEOUT
+
+ return socket.create_connection(address, timeout, source_address)
+
+ else:
+ host, port = address
+ err = None
+ for res in getaddrinfo(host, port, 0, SOCK_STREAM):
+ af, socktype, proto, canonname, sa = res
+ sock = None
+ try:
+ sock = socket(af, socktype, proto)
+ if type(timeout) != object:
+ sock.settimeout(timeout)
+ if source_address:
+ sock.bind(source_address)
+ sock.connect(sa)
+ return sock
+
+ except socket.error, _:
+ err = _
+ if sock is not None:
+ sock.close()
+
+ if err is not None:
+ raise err
+ else:
+ raise socket.error("getaddrinfo returns an empty list")
+
+
+class ClickAndLoad(Addon):
+ __name__ = "ClickAndLoad"
+ __type__ = "addon"
+ __version__ = "0.35"
+
+ __config__ = [("activated", "bool", "Activated" , True),
+ ("port" , "int" , "Port" , 9666),
+ ("extern" , "bool", "Listen on the public network interface", True)]
+
+ __description__ = """Click'N'Load addon plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.de"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ def activate(self):
+ if not self.config['webinterface']['activated']:
+ return
+
+ ip = socket.gethostbyname(socket.gethostname()) if self.getConfig("extern") else "127.0.0.1"
+ webport = int(self.config['webinterface']['port'])
+ cnlport = self.getConfig('port')
+
+ self.proxy(ip, webport, cnlport)
+
+
+ @threaded
+ def proxy(self, ip, webport, cnlport):
+ self.manager.startThread(self._server, ip, webport, cnlport)
+ lock = Lock()
+ lock.acquire()
+ lock.acquire()
+
+
+ def _server(self, ip, webport, cnlport, thread):
+ try:
+ server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ server_socket.bind((ip, cnlport))
+ server_socket.listen(5)
+
+ while True:
+ client_socket = server_socket.accept()[0]
+ dock_socket = create_connection(("127.0.0.1", webport))
+
+ self.manager.startThread(forward, dock_socket, client_socket)
+ self.manager.startThread(forward, client_socket, dock_socket)
+
+ except socket.error, e:
+ self.logDebug(e)
+ self._server(ip, webport, cnlport, thread)
+
+ except Exception, e:
+ self.logError(e)
+
+ try:
+ client_socket.close()
+ dock_socket.close()
+ except Exception:
+ pass
+
+ try:
+ server_socket.close()
+ except Exception:
+ pass
diff --git a/module/plugins/addon/DeleteFinished.py b/pyload/plugin/addon/DeleteFinished.py
index 59f2e3321..59f2e3321 100644
--- a/module/plugins/addon/DeleteFinished.py
+++ b/pyload/plugin/addon/DeleteFinished.py
diff --git a/module/plugins/addon/DownloadScheduler.py b/pyload/plugin/addon/DownloadScheduler.py
index e5e25e389..e5e25e389 100644
--- a/module/plugins/addon/DownloadScheduler.py
+++ b/pyload/plugin/addon/DownloadScheduler.py
diff --git a/module/plugins/addon/ExternalScripts.py b/pyload/plugin/addon/ExternalScripts.py
index 5aebf2338..5aebf2338 100644
--- a/module/plugins/addon/ExternalScripts.py
+++ b/pyload/plugin/addon/ExternalScripts.py
diff --git a/pyload/plugin/addon/ExtractArchive.py b/pyload/plugin/addon/ExtractArchive.py
new file mode 100644
index 000000000..951434e3e
--- /dev/null
+++ b/pyload/plugin/addon/ExtractArchive.py
@@ -0,0 +1,504 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import os
+import sys
+
+from copy import copy
+from traceback import print_exc
+
+# monkey patch bug in python 2.6 and lower
+# http://bugs.python.org/issue6122 , http://bugs.python.org/issue1236 , http://bugs.python.org/issue1731717
+if sys.version_info < (2, 7) and os.name != "nt":
+ import errno
+
+ from subprocess import Popen
+
+ def _eintr_retry_call(func, *args):
+ while True:
+ try:
+ return func(*args)
+
+ except OSError, e:
+ if e.errno == errno.EINTR:
+ continue
+ raise
+
+
+ # unsued timeout option for older python version
+ def wait(self, timeout=0):
+ """Wait for child process to terminate. Returns returncode
+ attribute."""
+ if self.returncode is None:
+ try:
+ pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0)
+ except OSError, e:
+ if e.errno != errno.ECHILD:
+ raise
+ # This happens if SIGCLD is set to be ignored or waiting
+ # for child processes has otherwise been disabled for our
+ # process. This child is dead, we can't get the status.
+ sts = 0
+ self._handle_exitstatus(sts)
+ return self.returncode
+
+ Popen.wait = wait
+
+if os.name != "nt":
+ from grp import getgrnam
+ from pwd import getpwnam
+
+from pyload.plugin.Addon import Addon, threaded, Expose
+from pyload.plugin.internal.Extractor import ArchiveError, CRCError, PasswordError
+from pyload.plugin.internal.SimpleHoster import replace_patterns
+from pyload.utils import fs_encode, safe_join, uniqify
+
+
+class ArchiveQueue(object):
+
+ def __init__(self, plugin, storage):
+ self.plugin = plugin
+ self.storage = storage
+
+
+ def get(self):
+ try:
+ return [int(pid) for pid in self.plugin.getStorage("ExtractArchive:%s" % self.storage, "").decode('base64').split()]
+ except Exception:
+ return []
+
+
+ def set(self, value):
+ if isinstance(value, list):
+ item = str(value)[1:-1].replace(' ', '').replace(',', ' ')
+ else:
+ item = str(value).strip()
+ return self.plugin.setStorage("ExtractArchive:%s" % self.storage, item.encode('base64')[:-1])
+
+
+ def delete(self):
+ return self.plugin.delStorage("ExtractArchive:%s" % self.storage)
+
+
+ def add(self, item):
+ queue = self.get()
+ if item not in queue:
+ return self.set(queue + [item])
+ else:
+ return True
+
+
+ def remove(self, item):
+ queue = self.get()
+ try:
+ queue.remove(item)
+ except ValueError:
+ pass
+ if queue == []:
+ return self.delete()
+ return self.set(queue)
+
+
+
+class ExtractArchive(Addon):
+ __name__ = "ExtractArchive"
+ __type__ = "addon"
+ __version__ = "1.29"
+
+ __config__ = [("activated" , "bool" , "Activated" , True ),
+ ("fullpath" , "bool" , "Extract with full paths" , True ),
+ ("overwrite" , "bool" , "Overwrite files" , False ),
+ ("keepbroken" , "bool" , "Try to extract broken archives" , False ),
+ ("repair" , "bool" , "Repair broken archives" , True ),
+ ("usepasswordfile" , "bool" , "Use password file" , True ),
+ ("passwordfile" , "file" , "Password file" , "archive_password.txt" ),
+ ("delete" , "bool" , "Delete archive when successfully extracted", False ),
+ ("subfolder" , "bool" , "Create subfolder for each package" , False ),
+ ("destination" , "folder", "Extract files to folder" , "" ),
+ ("extensions" , "str" , "Extract the following extensions" , "7z,bz2,bzip2,gz,gzip,lha,lzh,lzma,rar,tar,taz,tbz,tbz2,tgz,xar,xz,z,zip"),
+ ("excludefiles" , "str" , "Don't extract the following files" , "*.nfo,*.DS_Store,index.dat,thumb.db" ),
+ ("recursive" , "bool" , "Extract archives in archives" , True ),
+ ("waitall" , "bool" , "Wait for all downloads to be finished" , False ),
+ ("renice" , "int" , "CPU priority" , 0 )]
+
+ __description__ = """Extract different kind of archives"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com"),
+ ("Immenz" , "immenz@gmx.net" )]
+
+
+ event_list = ["allDownloadsProcessed"]
+
+ NAME_REPLACEMENTS = [(r'\.part\d+\.rar$', ".part.rar")]
+
+
+ def setup(self):
+ self.queue = ArchiveQueue(self, "Queue")
+ self.failed = ArchiveQueue(self, "Failed")
+
+ self.interval = 60
+ self.extracting = False
+ self.extractors = []
+ self.passwords = []
+
+
+ def activate(self):
+ # self.extracting = False
+
+ for p in ("UnRar", "SevenZip", "UnZip"):
+ try:
+ module = self.core.pluginManager.loadModule("internal", p)
+ klass = getattr(module, p)
+ if klass.isUsable():
+ self.extractors.append(klass)
+
+ except OSError, e:
+ if e.errno == 2:
+ self.logInfo(_("No %s installed") % p)
+ else:
+ self.logWarning(_("Could not activate: %s") % p, e)
+ if self.core.debug:
+ print_exc()
+
+ except Exception, e:
+ self.logWarning(_("Could not activate: %s") % p, e)
+ if self.core.debug:
+ print_exc()
+
+ if self.extractors:
+ self.logInfo(_("Activated") + " " + "|".join("%s %s" % (Extractor.__name__,Extractor.VERSION) for Extractor in self.extractors))
+
+ if self.getConfig("waitall"):
+ self.extractPackage(*self.queue.get()) #: Resume unfinished extractions
+ else:
+ super(ExtractArchive, self).initPeriodical()
+
+ else:
+ self.logInfo(_("No Extract plugins activated"))
+
+
+ def periodical(self):
+ if not self.extracting:
+ self.extractPackage(*self.queue.get())
+
+
+ @Expose
+ def extractPackage(self, *ids):
+ """ Extract packages with given id"""
+ self.manager.startThread(self.extract, ids)
+
+
+ def packageFinished(self, pypack):
+ self.queue.add(pypack.id)
+
+
+ @threaded
+ def allDownloadsProcessed(self, thread):
+ if self.extract(self.queue.get(), thread): #@NOTE: check only if all gone fine, no failed reporting for now
+ self.manager.dispatchEvent("all_archives_extracted")
+
+ self.manager.dispatchEvent("all_archives_processed")
+
+
+ def extract(self, ids, thread=None):
+ if not ids:
+ return False
+
+ self.extracting = True
+
+ processed = []
+ extracted = []
+ failed = []
+
+ toList = lambda string: string.replace(' ', '').replace(',', '|').replace(';', '|').split('|')
+
+ destination = self.getConfig("destination")
+ subfolder = self.getConfig("subfolder")
+ fullpath = self.getConfig("fullpath")
+ overwrite = self.getConfig("overwrite")
+ renice = self.getConfig("renice")
+ recursive = self.getConfig("recursive")
+ delete = self.getConfig("delete")
+ keepbroken = self.getConfig("keepbroken")
+
+ extensions = [x.lstrip('.').lower() for x in toList(self.getConfig("extensions"))]
+ excludefiles = toList(self.getConfig("excludefiles"))
+
+ if extensions:
+ self.logDebug("Use for extensions: %s" % "|.".join(extensions))
+
+ # reload from txt file
+ self.reloadPasswords()
+
+ # dl folder
+ dl = self.config['general']['download_folder']
+
+ #iterate packages -> extractors -> targets
+ for pid in ids:
+ pypack = self.core.files.getPackage(pid)
+
+ if not pypack:
+ continue
+
+ self.logInfo(_("Check package: %s") % pypack.name)
+
+ # determine output folder
+ out = safe_join(dl, pypack.folder, destination, "") #: force trailing slash
+
+ if subfolder:
+ out = safe_join(out, pypack.folder)
+
+ if not os.path.exists(out):
+ os.makedirs(out)
+
+ matched = False
+ success = True
+ files_ids = [(safe_join(dl, pypack.folder, pylink['name']), pylink['id'], out) for pylink in pypack.getChildren().itervalues()]
+
+ # check as long there are unseen files
+ while files_ids:
+ new_files_ids = []
+
+ if extensions:
+ files_ids = [(fname, fid, fout) for fname, fid, fout in files_ids \
+ if filter(lambda ext: fname.lower().endswith(ext), extensions)]
+
+ for Extractor in self.extractors:
+ targets = Extractor.getTargets(files_ids)
+ if targets:
+ self.logDebug("Targets for %s: %s" % (Extractor.__name__, targets))
+ matched = True
+
+ for fname, fid, fout in targets:
+ name = os.path.basename(fname)
+
+ if not os.path.exists(fname):
+ self.logDebug(name, "File not found")
+ continue
+
+ self.logInfo(name, _("Extract to: %s") % fout)
+ try:
+ archive = Extractor(self,
+ fname,
+ fout,
+ fullpath,
+ overwrite,
+ excludefiles,
+ renice,
+ delete,
+ keepbroken,
+ fid)
+ archive.init()
+
+ new_files = self._extract(archive, fid, pypack.password, thread)
+
+ except Exception, e:
+ self.logError(name, e)
+ success = False
+ continue
+
+ files_ids.remove((fname, fid, fout)) # don't let other extractors spam log
+ self.logDebug("Extracted files: %s" % new_files)
+ self.setPermissions(new_files)
+
+ for filename in new_files:
+ file = fs_encode(safe_join(os.path.dirname(archive.filename), filename))
+ if not os.path.exists(file):
+ self.logDebug("New file %s does not exists" % filename)
+ continue
+
+ if recursive and os.path.isfile(file):
+ new_files_ids.append((filename, fid, os.path.dirname(filename))) # append as new target
+
+ files_ids = new_files_ids # also check extracted files
+
+ if matched:
+ if success:
+ extracted.append(pid)
+ self.manager.dispatchEvent("package_extracted", pypack)
+ else:
+ failed.append(pid)
+ self.manager.dispatchEvent("package_extract_failed", pypack)
+
+ self.failed.add(pid)
+ else:
+ self.logInfo(_("No files found to extract"))
+
+ if not matched or not success and subfolder:
+ try:
+ os.rmdir(out)
+
+ except OSError:
+ pass
+
+ self.queue.remove(pid)
+
+ self.extracting = False
+ return True if not failed else False
+
+
+ def _extract(self, archive, fid, password, thread):
+ pyfile = self.core.files.getFile(fid)
+ name = os.path.basename(archive.filename)
+
+ thread.addActive(pyfile)
+ pyfile.setStatus("processing")
+
+ encrypted = False
+ try:
+ try:
+ archive.check()
+
+ except CRCError, e:
+ self.logDebug(name, e)
+ self.logInfo(name, _("Header protected"))
+
+ if self.getConfig("repair"):
+ self.logWarning(name, _("Repairing..."))
+
+ pyfile.setCustomStatus(_("repairing"))
+ pyfile.setProgress(0)
+
+ repaired = archive.repair()
+
+ pyfile.setProgress(100)
+
+ if not repaired and not self.getConfig("keepbroken"):
+ raise CRCError("Archive damaged")
+
+ except PasswordError:
+ self.logInfo(name, _("Password protected"))
+ encrypted = True
+
+ except ArchiveError, e:
+ raise ArchiveError(e)
+
+ self.logDebug("Password: %s" % (password or "No provided"))
+
+ pyfile.setCustomStatus(_("extracting"))
+ pyfile.setProgress(0)
+
+ if not encrypted or not self.getConfig("usepasswordfile"):
+ archive.extract(password)
+ else:
+ for pw in filter(None, uniqify([password] + self.getPasswords(False))):
+ try:
+ self.logDebug("Try password: %s" % pw)
+
+ ispw = archive.isPassword(pw)
+ if ispw or ispw is None:
+ archive.extract(pw)
+ self.addPassword(pw)
+ break
+
+ except PasswordError:
+ self.logDebug("Password was wrong")
+ else:
+ raise PasswordError
+
+ pyfile.setProgress(100)
+ pyfile.setCustomStatus(_("finalizing"))
+
+ if self.core.debug:
+ self.logDebug("Would delete: %s" % ", ".join(archive.getDeleteFiles()))
+
+ if self.getConfig("delete"):
+ files = archive.getDeleteFiles()
+ self.logInfo(_("Deleting %s files") % len(files))
+ for f in files:
+ file = fs_encode(f)
+ if os.path.exists(file):
+ os.remove(file)
+ else:
+ self.logDebug("%s does not exists" % f)
+
+ self.logInfo(name, _("Extracting finished"))
+
+ extracted_files = archive.files or archive.list()
+ self.manager.dispatchEvent("archive_extracted", pyfile, archive.out, archive.filename, extracted_files)
+
+ return extracted_files
+
+ except PasswordError:
+ self.logError(name, _("Wrong password" if password else "No password found"))
+
+ except CRCError, e:
+ self.logError(name, _("CRC mismatch"), e)
+
+ except ArchiveError, e:
+ self.logError(name, _("Archive error"), e)
+
+ except Exception, e:
+ self.logError(name, _("Unknown error"), e)
+ if self.core.debug:
+ print_exc()
+
+ finally:
+ pyfile.finishIfDone()
+
+ self.manager.dispatchEvent("archive_extract_failed", pyfile)
+
+ raise Exception(_("Extract failed"))
+
+
+ @Expose
+ def getPasswords(self, reload=True):
+ """ List of saved passwords """
+ if reload:
+ self.reloadPasswords()
+
+ return self.passwords
+
+
+ def reloadPasswords(self):
+ try:
+ passwords = []
+
+ file = fs_encode(self.getConfig("passwordfile"))
+ with open(file) as f:
+ for pw in f.read().splitlines():
+ passwords.append(pw)
+
+ except IOError, e:
+ self.logError(e)
+
+ else:
+ self.passwords = passwords
+
+
+ @Expose
+ def addPassword(self, password):
+ """ Adds a password to saved list"""
+ try:
+ self.passwords = uniqify([password] + self.passwords)
+
+ file = fs_encode(self.getConfig("passwordfile"))
+ with open(file, "wb") as f:
+ for pw in self.passwords:
+ f.write(pw + '\n')
+
+ except IOError, e:
+ self.logError(e)
+
+
+ def setPermissions(self, files):
+ for f in files:
+ if not os.path.exists(f):
+ continue
+
+ try:
+ if self.config['permission']['change_file']:
+ if os.path.isfile(f):
+ os.chmod(f, int(self.config['permission']['file'], 8))
+
+ elif os.path.isdir(f):
+ os.chmod(f, int(self.config['permission']['folder'], 8))
+
+ if self.config['permission']['change_dl'] and os.name != "nt":
+ uid = getpwnam(self.config['permission']['user'])[2]
+ gid = getgrnam(self.config['permission']['group'])[2]
+ os.chown(f, uid, gid)
+
+ except Exception, e:
+ self.logWarning(_("Setting User and Group failed"), e)
diff --git a/module/plugins/addon/HotFolder.py b/pyload/plugin/addon/HotFolder.py
index eb607ac7e..eb607ac7e 100644
--- a/module/plugins/addon/HotFolder.py
+++ b/pyload/plugin/addon/HotFolder.py
diff --git a/module/plugins/addon/IRCInterface.py b/pyload/plugin/addon/IRCInterface.py
index 86d9ea688..86d9ea688 100644
--- a/module/plugins/addon/IRCInterface.py
+++ b/pyload/plugin/addon/IRCInterface.py
diff --git a/pyload/plugin/addon/JustPremium.py b/pyload/plugin/addon/JustPremium.py
new file mode 100644
index 000000000..d3c4d8eff
--- /dev/null
+++ b/pyload/plugin/addon/JustPremium.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.Addon import Addon
+
+
+class JustPremium(Addon):
+ __name__ = "JustPremium"
+ __type__ = "addon"
+ __version__ = "0.21"
+
+ __config__ = [("excluded", "str", "Exclude hosters (comma separated)", "")]
+
+ __description__ = """Remove all not premium links from urls added"""
+ __license__ = "GPLv3"
+ __authors__ = [("mazleu", "mazleica@gmail.com"),
+ ("Walter Purcaro", "vuolter@gmail.com"),
+ ("immenz", "immenz@gmx.net")]
+
+
+ event_list = ["linksAdded"]
+
+
+ def linksAdded(self, links, pid):
+ hosterdict = self.core.pluginManager.hosterPlugins
+ linkdict = self.core.api.checkURLs(links)
+
+ premiumplugins = set(account.type for account in self.core.api.getAccounts(False) \
+ if account.valid and account.premium)
+ multihosters = set(hoster for hoster in self.core.pluginManager.hosterPlugins \
+ if 'new_name' in hosterdict[hoster] \
+ and hosterdict[hoster]['new_name'] in premiumplugins)
+
+ #: Found at least one hoster with account or multihoster
+ if not any(True for pluginname in linkdict if pluginname in premiumplugins | multihosters):
+ return
+
+ excluded = map(lambda domain: "".join(part.capitalize() for part in re.split(r'(\.|\d+)', domain) if part != '.'),
+ self.getConfig('excluded').replace(' ', '').replace(',', '|').replace(';', '|').split('|'))
+
+ for pluginname in set(linkdict.keys()) - (premiumplugins | multihosters).union(excluded):
+ self.logInfo(_("Remove links of plugin: %s") % pluginname)
+ for link in linkdict[pluginname]:
+ self.logDebug("Remove link: %s" % link)
+ links.remove(link)
diff --git a/pyload/plugin/addon/MergeFiles.py b/pyload/plugin/addon/MergeFiles.py
new file mode 100644
index 000000000..11e869aee
--- /dev/null
+++ b/pyload/plugin/addon/MergeFiles.py
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import os
+import re
+
+from traceback import print_exc
+
+from pyload.plugin.Addon import Addon, threaded
+from pyload.utils import safe_join
+
+
+class MergeFiles(Addon):
+ __name__ = "MergeFiles"
+ __type__ = "addon"
+ __version__ = "0.14"
+
+ __config__ = [("activated", "bool", "Activated", True)]
+
+ __description__ = """Merges parts splitted with hjsplit"""
+ __license__ = "GPLv3"
+ __authors__ = [("and9000", "me@has-no-mail.com")]
+
+
+ BUFFER_SIZE = 4096
+
+
+ def setup(self):
+ pass
+
+
+ @threaded
+ def packageFinished(self, pack):
+ files = {}
+ fid_dict = {}
+ for fid, data in pack.getChildren().iteritems():
+ if re.search("\.\d{3}$", data['name']):
+ if data['name'][:-4] not in files:
+ files[data['name'][:-4]] = []
+ files[data['name'][:-4]].append(data['name'])
+ files[data['name'][:-4]].sort()
+ fid_dict[data['name']] = fid
+
+ download_folder = self.config['general']['download_folder']
+
+ if self.config['general']['folder_per_package']:
+ download_folder = safe_join(download_folder, pack.folder)
+
+ for name, file_list in files.iteritems():
+ self.logInfo(_("Starting merging of"), name)
+
+ final_file = open(safe_join(download_folder, name), "wb")
+ for splitted_file in file_list:
+ self.logDebug("Merging part", splitted_file)
+
+ pyfile = self.core.files.getFile(fid_dict[splitted_file])
+
+ pyfile.setStatus("processing")
+
+ try:
+ with open(safe_join(download_folder, splitted_file), "rb") as s_file:
+ size_written = 0
+ s_file_size = int(os.path.getsize(os.path.join(download_folder, splitted_file)))
+
+ while True:
+ f_buffer = s_file.read(self.BUFFER_SIZE)
+ if f_buffer:
+ final_file.write(f_buffer)
+ size_written += self.BUFFER_SIZE
+ pyfile.setProgress((size_written * 100) / s_file_size)
+ else:
+ break
+
+ self.logDebug("Finished merging part", splitted_file)
+
+ except Exception, e:
+ print_exc()
+
+ finally:
+ pyfile.setProgress(100)
+ pyfile.setStatus("finished")
+ pyfile.release()
+
+ self.logInfo(_("Finished merging of"), name)
diff --git a/module/plugins/addon/MultiHome.py b/pyload/plugin/addon/MultiHome.py
index 521749fc8..521749fc8 100644
--- a/module/plugins/addon/MultiHome.py
+++ b/pyload/plugin/addon/MultiHome.py
diff --git a/module/plugins/addon/RestartFailed.py b/pyload/plugin/addon/RestartFailed.py
index 2fe5f13bf..2fe5f13bf 100644
--- a/module/plugins/addon/RestartFailed.py
+++ b/pyload/plugin/addon/RestartFailed.py
diff --git a/module/plugins/addon/RestartSlow.py b/pyload/plugin/addon/RestartSlow.py
index 332047da7..332047da7 100644
--- a/module/plugins/addon/RestartSlow.py
+++ b/pyload/plugin/addon/RestartSlow.py
diff --git a/pyload/plugin/addon/SkipRev.py b/pyload/plugin/addon/SkipRev.py
new file mode 100644
index 000000000..efc96cb7b
--- /dev/null
+++ b/pyload/plugin/addon/SkipRev.py
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+
+from types import MethodType
+from urllib import unquote
+from urlparse import urlparse
+
+from pyload.datatype.File import PyFile
+from pyload.plugin.Addon import Addon
+from pyload.plugin.Plugin import SkipDownload
+
+
+def _setup(self):
+ self.pyfile.plugin._setup()
+ if self.pyfile.hasStatus("skipped"):
+ raise SkipDownload(self.pyfile.statusname or self.pyfile.pluginname)
+
+
+class SkipRev(Addon):
+ __name__ = "SkipRev"
+ __type__ = "addon"
+ __version__ = "0.25"
+
+ __config__ = [("tokeep", "int", "Number of rev files to keep for package (-1 to auto)", -1)]
+
+ __description__ = """Skip files ending with extension rev"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ def _pyname(self, pyfile):
+ if hasattr(pyfile.pluginmodule, "getInfo"):
+ return getattr(pyfile.pluginmodule, "getInfo")([pyfile.url]).next()[0]
+ else:
+ self.logWarning("Unable to grab file name")
+ return urlparse(unquote(pyfile.url)).path.split('/')[-1]
+
+
+ def _pyfile(self, link):
+ return PyFile(self.core.files,
+ link.fid,
+ link.url,
+ link.name,
+ link.size,
+ link.status,
+ link.error,
+ link.plugin,
+ link.packageID,
+ link.order)
+
+
+ def downloadPreparing(self, pyfile):
+ if pyfile.statusname is "unskipped" or not self._pyname(pyfile).endswith(".rev"):
+ return
+
+ tokeep = self.getConfig("tokeep")
+
+ if tokeep:
+ status_list = (1, 4, 8, 9, 14) if tokeep < 0 else (1, 3, 4, 8, 9, 14)
+
+ queued = [True for link in self.core.api.getPackageData(pyfile.package().id).links \
+ if link.name.endswith(".rev") and link.status not in status_list].count(True)
+
+ if not queued or queued < tokeep: #: keep one rev at least in auto mode
+ return
+
+ pyfile.setCustomStatus("SkipRev", "skipped")
+ pyfile.plugin._setup = pyfile.plugin.setup
+ pyfile.plugin.setup = MethodType(_setup, pyfile.plugin) #: work-around: inject status checker inside the preprocessing routine of the plugin
+
+
+ def downloadFailed(self, pyfile):
+ #: Check if pyfile is still "failed",
+ # maybe might has been restarted in meantime
+ if pyfile.status != 8:
+ return
+
+ tokeep = self.getConfig("tokeep")
+
+ if not tokeep:
+ return
+
+ for link in self.core.api.getPackageData(pyfile.package().id).links:
+ if link.status is 4 and link.name.endswith(".rev"):
+ pylink = self._pyfile(link)
+
+ if tokeep > -1 or pyfile.name.endswith(".rev"):
+ pylink.setStatus("queued")
+ else:
+ pylink.setCustomStatus("unskipped", "queued")
+
+ self.core.files.save()
+ pylink.release()
+ return
diff --git a/pyload/plugin/addon/UnSkipOnFail.py b/pyload/plugin/addon/UnSkipOnFail.py
new file mode 100644
index 000000000..7d787d1ed
--- /dev/null
+++ b/pyload/plugin/addon/UnSkipOnFail.py
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+
+from pyload.datatype.File import PyFile
+from pyload.plugin.Addon import Addon
+
+
+class UnSkipOnFail(Addon):
+ __name__ = "UnSkipOnFail"
+ __type__ = "addon"
+ __version__ = "0.05"
+
+ __config__ = [("activated", "bool", "Activated", True)]
+
+ __description__ = """Queue skipped duplicates when download fails"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ def downloadFailed(self, pyfile):
+ #: Check if pyfile is still "failed",
+ # maybe might has been restarted in meantime
+ if pyfile.status != 8:
+ return
+
+ msg = _("Looking for skipped duplicates of: %s (pid:%s)")
+ self.logInfo(msg % (pyfile.name, pyfile.package().id))
+
+ dup = self.findDuplicate(pyfile)
+ if dup:
+ self.logInfo(_("Queue found duplicate: %s (pid:%s)") % (dup.name, dup.packageID))
+
+ #: Change status of "link" to "new_status".
+ # "link" has to be a valid FileData object,
+ # "new_status" has to be a valid status name
+ # (i.e. "queued" for this Plugin)
+ # It creates a temporary PyFile object using
+ # "link" data, changes its status, and tells
+ # the core.files-manager to save its data.
+ pylink = _pyfile(link)
+
+ pylink.setCustomStatus("UnSkipOnFail", "queued")
+
+ self.core.files.save()
+ pylink.release()
+
+ else:
+ self.logInfo(_("No duplicates found"))
+
+
+ def findDuplicate(self, pyfile):
+ """ Search all packages for duplicate links to "pyfile".
+ Duplicates are links that would overwrite "pyfile".
+ To test on duplicity the package-folder and link-name
+ of twolinks are compared (link.name).
+ So this method returns a list of all links with equal
+ package-folders and filenames as "pyfile", but except
+ the data for "pyfile" iotselöf.
+ It does MOT check the link's status.
+ """
+ queue = self.core.api.getQueue() #: get packages (w/o files, as most file data is useless here)
+
+ for package in queue:
+ #: check if package-folder equals pyfile's package folder
+ if package.folder != pyfile.package().folder:
+ continue
+
+ #: now get packaged data w/ files/links
+ pdata = self.core.api.getPackageData(package.pid)
+ for link in pdata.links:
+ #: check if link is "skipped"
+ if link.status != 4:
+ continue
+
+ #: check if link name collides with pdata's name
+ #: AND at last check if it is not pyfile itself
+ if link.name == pyfile.name and link.fid != pyfile.id:
+ return link
+
+
+ def _pyfile(self, link):
+ return PyFile(self.core.files,
+ link.fid,
+ link.url,
+ link.name,
+ link.size,
+ link.status,
+ link.error,
+ link.plugin,
+ link.packageID,
+ link.order)
diff --git a/pyload/plugin/addon/UpdateManager.py b/pyload/plugin/addon/UpdateManager.py
new file mode 100644
index 000000000..cf138f64a
--- /dev/null
+++ b/pyload/plugin/addon/UpdateManager.py
@@ -0,0 +1,306 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import re
+import sys
+
+from operator import itemgetter
+from os import path, remove, stat
+
+from pyload.network.RequestFactory import getURL
+from pyload.plugin.Addon import Expose, Addon, threaded
+from pyload.utils import safe_join
+
+
+class UpdateManager(Addon):
+ __name__ = "UpdateManager"
+ __type__ = "addon"
+ __version__ = "0.43"
+
+ __config__ = [("activated" , "bool" , "Activated" , True ),
+ ("mode" , "pyLoad + plugins;plugins only", "Check updates for" , "pyLoad + plugins"),
+ ("interval" , "int" , "Check interval in hours" , 8 ),
+ ("autorestart" , "bool" , "Automatically restart pyLoad when required" , True ),
+ ("reloadplugins", "bool" , "Monitor plugins for code changes in debug mode", True ),
+ ("nodebugupdate", "bool" , "Don't check for updates in debug mode" , False )]
+
+ __description__ = """Check for updates"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ # event_list = ["pluginConfigChanged"]
+
+ SERVER_URL = "http://updatemanager.pyload.org"
+ VERSION = re.compile(r'__version__.*=.*("|\')([\d.]+)')
+ MIN_INTERVAL = 3 * 60 * 60 #: 3h minimum check interval (value is in seconds)
+
+
+ def pluginConfigChanged(self, plugin, name, value):
+ if name == "interval":
+ interval = value * 60 * 60
+ if self.MIN_INTERVAL <= interval != self.interval:
+ self.core.scheduler.removeJob(self.cb)
+ self.interval = interval
+ self.initPeriodical()
+ else:
+ self.logDebug("Invalid interval value, kept current")
+
+ elif name == "reloadplugins":
+ if self.cb2:
+ self.core.scheduler.removeJob(self.cb2)
+ if value is True and self.core.debug:
+ self.periodical2()
+
+
+ def activate(self):
+ self.pluginConfigChanged(self.__name__, "interval", self.getConfig("interval"))
+ x = lambda: self.pluginConfigChanged(self.__name__, "reloadplugins", self.getConfig("reloadplugins"))
+ self.core.scheduler.addJob(10, x, threaded=False)
+
+
+ def deactivate(self):
+ self.pluginConfigChanged(self.__name__, "reloadplugins", False)
+
+
+ def setup(self):
+ self.cb2 = None
+ self.interval = 0
+ self.updating = False
+ self.info = {'pyload': False, 'version': None, 'plugins': False}
+ self.mtimes = {} #: store modification time for each plugin
+
+
+ def periodical2(self):
+ if not self.updating:
+ self.autoreloadPlugins()
+
+ self.cb2 = self.core.scheduler.addJob(4, self.periodical2, threaded=False)
+
+
+ @Expose
+ def autoreloadPlugins(self):
+ """ reload and reindex all modified plugins """
+ modules = filter(
+ lambda m: m and (m.__name__.startswith("pyload.plugin.") or
+ m.__name__.startswith("userplugins.")) and
+ m.__name__.count(".") >= 2, sys.modules.itervalues()
+ )
+
+ reloads = []
+
+ for m in modules:
+ root, type, name = m.__name__.rsplit(".", 2)
+ id = (type, name)
+ if type in self.core.pluginManager.plugins:
+ f = m.__file__.replace(".pyc", ".py")
+ if not path.isfile(f):
+ continue
+
+ mtime = stat(f).st_mtime
+
+ if id not in self.mtimes:
+ self.mtimes[id] = mtime
+ elif self.mtimes[id] < mtime:
+ reloads.append(id)
+ self.mtimes[id] = mtime
+
+ return True if self.core.pluginManager.reloadPlugins(reloads) else False
+
+
+ def periodical(self):
+ if self.info['pyload'] or self.getConfig("nodebugupdate") and self.core.debug:
+ return
+
+ self.updateThread()
+
+
+ def server_request(self):
+ try:
+ return getURL(self.SERVER_URL, get={'v': self.core.api.getServerVersion()}).splitlines()
+ except Exception:
+ self.logWarning(_("Unable to contact server to get updates"))
+
+
+ @threaded
+ def updateThread(self):
+ self.updating = True
+
+ status = self.update(onlyplugin=self.getConfig("mode") == "plugins only")
+
+ if status is 2 and self.getConfig("autorestart"):
+ self.core.api.restart()
+ else:
+ self.updating = False
+
+
+ @Expose
+ def updatePlugins(self):
+ """ simple wrapper for calling plugin update quickly """
+ return self.update(onlyplugin=True)
+
+
+ @Expose
+ def update(self, onlyplugin=False):
+ """ check for updates """
+ data = self.server_request()
+
+ if not data:
+ exitcode = 0
+
+ elif data[0] == "None":
+ self.logInfo(_("No new pyLoad version available"))
+ updates = data[1:]
+ exitcode = self._updatePlugins(updates)
+
+ elif onlyplugin:
+ exitcode = 0
+
+ else:
+ newversion = data[0]
+ self.logInfo(_("*** New pyLoad Version %s available ***") % newversion)
+ self.logInfo(_("*** Get it here: https://github.com/pyload/pyload/releases ***"))
+ exitcode = 3
+ self.info['pyload'] = True
+ self.info['version'] = newversion
+
+ return exitcode #: 0 = No plugins updated; 1 = Plugins updated; 2 = Plugins updated, but restart required; 3 = No plugins updated, new pyLoad version available
+
+
+ def _updatePlugins(self, updates):
+ """ check for plugin updates """
+
+ if self.info['plugins']:
+ return False #: plugins were already updated
+
+ exitcode = 0
+ updated = []
+
+ url = updates[0]
+ schema = updates[1].split('|')
+
+ if "BLACKLIST" in updates:
+ blacklist = updates[updates.index('BLACKLIST') + 1:]
+ updates = updates[2:updates.index('BLACKLIST')]
+ else:
+ blacklist = None
+ updates = updates[2:]
+
+ upgradable = [dict(zip(schema, x.split('|'))) for x in updates]
+ blacklisted = [(x.split('|')[0], x.split('|')[1].rsplit('.', 1)[0]) for x in blacklist] if blacklist else []
+
+ if blacklist:
+ # Protect UpdateManager from self-removing
+ try:
+ blacklisted.remove(("addon", "UpdateManager"))
+ except Exception:
+ pass
+
+ for t, n in blacklisted:
+ for idx, plugin in enumerate(upgradable):
+ if n == plugin['name'] and t == plugin['type']:
+ upgradable.pop(idx)
+ break
+
+ for t, n in self.removePlugins(sorted(blacklisted)):
+ self.logInfo(_("Removed blacklisted plugin [%(type)s] %(name)s") % {
+ 'type': t,
+ 'name': n,
+ })
+
+ for plugin in sorted(upgradable, key=itemgetter("type", "name")):
+ filename = plugin['name']
+ type = plugin['type']
+ version = plugin['version']
+
+ if filename.endswith(".pyc"):
+ name = filename[:filename.find("_")]
+ else:
+ name = filename.replace(".py", "")
+
+ plugins = getattr(self.core.pluginManager, "%sPlugins" % type)
+
+ oldver = float(plugins[name]['version']) if name in plugins else None
+ newver = float(version)
+
+ if not oldver:
+ msg = "New plugin: [%(type)s] %(name)s (v%(newver).2f)"
+ elif newver > oldver:
+ msg = "New version of plugin: [%(type)s] %(name)s (v%(oldver).2f -> v%(newver).2f)"
+ else:
+ continue
+
+ self.logInfo(_(msg) % {'type' : type,
+ 'name' : name,
+ 'oldver': oldver,
+ 'newver': newver})
+ try:
+ content = getURL(url % plugin)
+ m = self.VERSION.search(content)
+
+ if m and m.group(2) == version:
+ with open(safe_join("userplugins", prefix, filename), "wb") as f:
+ f.write(content)
+
+ updated.append((prefix, name))
+ else:
+ raise Exception, _("Version mismatch")
+
+ except Exception, e:
+ self.logError(_("Error updating plugin: %s") % filename, str(e))
+
+ if updated:
+ reloaded = self.core.pluginManager.reloadPlugins(updated)
+ if reloaded:
+ self.logInfo(_("Plugins updated and reloaded"))
+ exitcode = 1
+ else:
+ self.logInfo(_("*** Plugins have been updated, but need a pyLoad restart to be reloaded ***"))
+ self.info['plugins'] = True
+ exitcode = 2
+ else:
+ self.logInfo(_("No plugin updates available"))
+
+ return exitcode #: 0 = No plugins updated; 1 = Plugins updated; 2 = Plugins updated, but restart required
+
+
+ @Expose
+ def removePlugins(self, type_plugins):
+ """ delete plugins from disk """
+
+ if not type_plugins:
+ return
+
+ self.logDebug("Requested deletion of plugins: %s" % type_plugins)
+
+ removed = []
+
+ for type, name in type_plugins:
+ err = False
+ file = name + ".py"
+
+ for root in ("userplugins", path.join(pypath, "pyload", "plugins")):
+
+ filename = safe_join(root, type, file)
+ try:
+ remove(filename)
+ except Exception, e:
+ self.logDebug("Error deleting: %s" % path.basename(filename), e)
+ err = True
+
+ filename += "c"
+ if path.isfile(filename):
+ try:
+ if type == "addon":
+ self.manager.deactivateAddon(name)
+ remove(filename)
+ except Exception, e:
+ self.logDebug("Error deleting: %s" % path.basename(filename), e)
+ err = True
+
+ if not err:
+ id = (type, name)
+ removed.append(id)
+
+ return removed #: return a list of the plugins successfully removed
diff --git a/pyload/plugin/addon/WindowsPhoneNotify.py b/pyload/plugin/addon/WindowsPhoneNotify.py
new file mode 100644
index 000000000..b9710c2f0
--- /dev/null
+++ b/pyload/plugin/addon/WindowsPhoneNotify.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+
+import httplib
+
+from time import time
+
+from pyload.plugin.Addon import Addon
+
+
+class WindowsPhoneNotify(Addon):
+ __name__ = "WindowsPhoneNotify"
+ __type__ = "addon"
+ __version__ = "0.07"
+
+ __config__ = [("id" , "str" , "Push ID" , "" ),
+ ("url" , "str" , "Push url" , "" ),
+ ("notifycaptcha" , "bool", "Notify captcha request" , True ),
+ ("notifypackage" , "bool", "Notify package finished" , True ),
+ ("notifyprocessed", "bool", "Notify processed packages status" , True ),
+ ("timeout" , "int" , "Timeout between captchas in seconds" , 5 ),
+ ("force" , "bool", "Send notifications if client is connected", False)]
+
+ __description__ = """Send push notifications to Windows Phone"""
+ __license__ = "GPLv3"
+ __authors__ = [("Andy Voigt", "phone-support@hotmail.de"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ event_list = ["allDownloadsProcessed"]
+
+
+ def setup(self):
+ self.info = {} #@TODO: Remove in 0.4.10
+ self.last_notify = 0
+
+
+ def newCaptchaTask(self, task):
+ if not self.getConfig("notifycaptcha"):
+ return False
+
+ if time() - self.last_notify < self.getConf("timeout"):
+ return False
+
+ self.notify(_("Captcha"), _("New request waiting user input"))
+
+
+ def packageFinished(self, pypack):
+ if self.getConfig("notifypackage"):
+ self.notify(_("Package finished"), pypack.name)
+
+
+ def allDownloadsProcessed(self):
+ if not self.getConfig("notifyprocessed"):
+ return False
+
+ if any(True for pdata in self.core.api.getQueue() if pdata.linksdone < pdata.linkstotal):
+ self.notify(_("Package failed"), _("One or more packages was not completed successfully"))
+ else:
+ self.notify(_("All packages finished"))
+
+
+ def getXmlData(self, msg):
+ return ("<?xml version='1.0' encoding='utf-8'?> <wp:Notification xmlns:wp='WPNotification'> "
+ "<wp:Toast> <wp:Text1>pyLoad</wp:Text1> <wp:Text2>%s</wp:Text2> "
+ "</wp:Toast> </wp:Notification>" % msg)
+
+
+ def notify(self, event, msg=""):
+ id = self.getConfig("id")
+ url = self.getConfig("url")
+
+ if not id or not url:
+ return False
+
+ if self.core.isClientConnected() and not self.getConfig("force"):
+ return False
+
+ request = self.getXmlData("%s: %s" % (event, msg) if msg else event)
+ webservice = httplib.HTTP(url)
+
+ webservice.putrequest("POST", id)
+ webservice.putheader("Host", url)
+ webservice.putheader("Content-type", "text/xml")
+ webservice.putheader("X-NotificationClass", "2")
+ webservice.putheader("X-WindowsPhone-Target", "toast")
+ webservice.putheader("Content-length", "%d" % len(request))
+ webservice.endheaders()
+ webservice.send(request)
+ webservice.close()
+
+ self.last_notify = time()
diff --git a/module/plugins/addon/XMPPInterface.py b/pyload/plugin/addon/XMPPInterface.py
index 77a49af6f..77a49af6f 100644
--- a/module/plugins/addon/XMPPInterface.py
+++ b/pyload/plugin/addon/XMPPInterface.py
diff --git a/module/plugins/addon/__init__.py b/pyload/plugin/addon/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/plugins/addon/__init__.py
+++ b/pyload/plugin/addon/__init__.py
diff --git a/pyload/plugin/captcha/AdYouLike.py b/pyload/plugin/captcha/AdYouLike.py
new file mode 100644
index 000000000..0ff1a799b
--- /dev/null
+++ b/pyload/plugin/captcha/AdYouLike.py
@@ -0,0 +1,108 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.Captcha import Captcha
+from pyload.utils import json_loads
+
+
+class AdYouLike(Captcha):
+ __name__ = "AdYouLike"
+ __version__ = "0.05"
+
+ __description__ = """AdYouLike captcha service plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ AYL_PATTERN = r'Adyoulike\.create\s*\((.+?)\)'
+ CALLBACK_PATTERN = r'(Adyoulike\.g\._jsonp_\d+)'
+
+
+ def detect_key(self, html=None):
+ if not html:
+ if hasattr(self.plugin, "html") and self.plugin.html:
+ html = self.plugin.html
+ else:
+ errmsg = _("AdYouLike html not found")
+ self.plugin.fail(errmsg)
+ raise TypeError(errmsg)
+
+ m = re.search(self.AYL_PATTERN, html)
+ n = re.search(self.CALLBACK_PATTERN, html)
+ if m and n:
+ self.key = (m.group(1).strip(), n.group(1).strip())
+ self.logDebug("Ayl|callback: %s | %s" % self.key)
+ return self.key #: key is the tuple(ayl, callback)
+ else:
+ self.logDebug("Ayl or callback not found")
+ return None
+
+
+ def challenge(self, key=None, html=None):
+ if not key:
+ if self.detect_key(html):
+ key = self.key
+ else:
+ errmsg = _("AdYouLike key not found")
+ self.plugin.fail(errmsg)
+ raise TypeError(errmsg)
+
+ ayl, callback = key
+
+ # {"adyoulike":{"key":"P~zQ~O0zV0WTiAzC-iw0navWQpCLoYEP"},
+ # "all":{"element_id":"ayl_private_cap_92300","lang":"fr","env":"prod"}}
+ ayl = json_loads(ayl)
+
+ html = self.plugin.req.load("http://api-ayl.appspot.com/challenge",
+ get={'key' : ayl['adyoulike']['key'],
+ 'env' : ayl['all']['env'],
+ 'callback': callback})
+ try:
+ challenge = json_loads(re.search(callback + r'\s*\((.+?)\)', html).group(1))
+
+ except AttributeError:
+ errmsg = _("AdYouLike challenge pattern not found")
+ self.plugin.fail(errmsg)
+ raise AttributeError(errmsg)
+
+ self.logDebug("Challenge: %s" % challenge)
+
+ return self.result(ayl, challenge), challenge
+
+
+ def result(self, server, challenge):
+ # Adyoulike.g._jsonp_5579316662423138
+ # ({"translations":{"fr":{"instructions_visual":"Recopiez « Soonnight » ci-dessous :"}},
+ # "site_under":true,"clickable":true,"pixels":{"VIDEO_050":[],"DISPLAY":[],"VIDEO_000":[],"VIDEO_100":[],
+ # "VIDEO_025":[],"VIDEO_075":[]},"medium_type":"image/adyoulike",
+ # "iframes":{"big":"<iframe src=\"http://www.soonnight.com/campagn.html\" scrolling=\"no\"
+ # height=\"250\" width=\"300\" frameborder=\"0\"></iframe>"},"shares":{},"id":256,
+ # "token":"e6QuI4aRSnbIZJg02IsV6cp4JQ9~MjA1","formats":{"small":{"y":300,"x":0,"w":300,"h":60},
+ # "big":{"y":0,"x":0,"w":300,"h":250},"hover":{"y":440,"x":0,"w":300,"h":60}},
+ # "tid":"SqwuAdxT1EZoi4B5q0T63LN2AkiCJBg5"})
+
+ if isinstance(server, basestring):
+ server = json_loads(server)
+
+ if isinstance(challenge, basestring):
+ challenge = json_loads(challenge)
+
+ try:
+ instructions_visual = challenge['translations'][server['all']['lang']]['instructions_visual']
+ result = re.search(u'«(.+?)»', instructions_visual).group(1).strip()
+
+ except AttributeError:
+ errmsg = _("AdYouLike result not found")
+ self.plugin.fail(errmsg)
+ raise AttributeError(errmsg)
+
+ result = {'_ayl_captcha_engine' : "adyoulike",
+ '_ayl_env' : server['all']['env'],
+ '_ayl_tid' : challenge['tid'],
+ '_ayl_token_challenge': challenge['token'],
+ '_ayl_response' : response}
+
+ self.logDebug("Result: %s" % result)
+
+ return result
diff --git a/pyload/plugin/captcha/AdsCaptcha.py b/pyload/plugin/captcha/AdsCaptcha.py
new file mode 100644
index 000000000..75852e36d
--- /dev/null
+++ b/pyload/plugin/captcha/AdsCaptcha.py
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from random import random
+
+from pyload.plugin.Captcha import Captcha
+
+
+class AdsCaptcha(Captcha):
+ __name__ = "AdsCaptcha"
+ __version__ = "0.08"
+
+ __description__ = """AdsCaptcha captcha service plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("pyLoad Team", "admin@pyload.org")]
+
+
+ CAPTCHAID_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*CaptchaId=(\d+)'
+ PUBLICKEY_PATTERN = r'api\.adscaptcha\.com/Get\.aspx\?[^"\']*PublicKey=([\w-]+)'
+
+
+ def detect_key(self, html=None):
+ if not html:
+ if hasattr(self.plugin, "html") and self.plugin.html:
+ html = self.plugin.html
+ else:
+ errmsg = _("AdsCaptcha html not found")
+ self.plugin.fail(errmsg)
+ raise TypeError(errmsg)
+
+ m = re.search(self.PUBLICKEY_PATTERN, html)
+ n = re.search(self.CAPTCHAID_PATTERN, html)
+ if m and n:
+ self.key = (m.group(1).strip(), n.group(1).strip()) #: key is the tuple(PublicKey, CaptchaId)
+ self.logDebug("Key|id: %s | %s" % self.key)
+ return self.key
+ else:
+ self.logDebug("Key or id not found")
+ return None
+
+
+ def challenge(self, key=None, html=None):
+ if not key:
+ if self.detect_key(html):
+ key = self.key
+ else:
+ errmsg = _("AdsCaptcha key not found")
+ self.plugin.fail(errmsg)
+ raise TypeError(errmsg)
+
+ PublicKey, CaptchaId = key
+
+ html = self.plugin.req.load("http://api.adscaptcha.com/Get.aspx",
+ get={'CaptchaId': CaptchaId,
+ 'PublicKey': PublicKey})
+ try:
+ challenge = re.search("challenge: '(.+?)',", html).group(1)
+ server = re.search("server: '(.+?)',", html).group(1)
+
+ except AttributeError:
+ errmsg = _("AdsCaptcha challenge pattern not found")
+ self.plugin.fail(errmsg)
+ raise AttributeError(errmsg)
+
+ self.logDebug("Challenge: %s" % challenge)
+
+ return self.result(server, challenge), challenge
+
+
+ def result(self, server, challenge):
+ result = self.plugin.decryptCaptcha("%sChallenge.aspx" % server,
+ get={'cid': challenge, 'dummy': random()},
+ cookies=True,
+ imgtype="jpg")
+
+ self.logDebug("Result: %s" % result)
+
+ return result
diff --git a/pyload/plugin/captcha/ReCaptcha.py b/pyload/plugin/captcha/ReCaptcha.py
new file mode 100644
index 000000000..295491bd8
--- /dev/null
+++ b/pyload/plugin/captcha/ReCaptcha.py
@@ -0,0 +1,208 @@
+# -*- coding: utf-8 -*-
+
+import re
+import time
+
+from base64 import b64encode
+from random import randint
+from urlparse import urljoin, urlparse
+
+from pyload.plugin.Captcha import Captcha
+
+
+class ReCaptcha(Captcha):
+ __name__ = "ReCaptcha"
+ __version__ = "0.14"
+
+ __description__ = """ReCaptcha captcha service plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("pyLoad Team", "admin@pyload.org"),
+ ("Walter Purcaro", "vuolter@gmail.com"),
+ ("zapp-brannigan", "fuerst.reinje@web.de")]
+
+
+ KEY_V2_PATTERN = r'(?:data-sitekey=["\']|["\']sitekey["\']:\s*["\'])([\w-]+)'
+ KEY_V1_PATTERN = r'(?:recaptcha(?:/api|\.net)/(?:challenge|noscript)\?k=|Recaptcha\.create\s*\(\s*["\'])([\w-]+)'
+
+
+ def detect_key(self, html=None):
+ if not html:
+ if hasattr(self.plugin, "html") and self.plugin.html:
+ html = self.plugin.html
+ else:
+ errmsg = _("ReCaptcha html not found")
+ self.plugin.fail(errmsg)
+ raise TypeError(errmsg)
+
+ m = re.search(self.KEY_V2_PATTERN, html) or re.search(self.KEY_V1_PATTERN, html)
+ if m:
+ self.key = m.group(1).strip()
+ self.logDebug("Key: %s" % self.key)
+ return self.key
+ else:
+ self.logDebug("Key not found")
+ return None
+
+
+ def challenge(self, key=None, html=None, version=None):
+ if not key:
+ if self.detect_key(html):
+ key = self.key
+ else:
+ errmsg = _("ReCaptcha key not found")
+ self.plugin.fail(errmsg)
+ raise TypeError(errmsg)
+
+ if version in (1, 2):
+ return getattr(self, "_challenge_v%s" % version)(key)
+
+ elif not html and hasattr(self.plugin, "html") and self.plugin.html:
+ version = 2 if re.search(self.KEY_V2_PATTERN, self.plugin.html) else 1
+ return self.challenge(key, self.plugin.html, version)
+
+ else:
+ errmsg = _("ReCaptcha html not found")
+ self.plugin.fail(errmsg)
+ raise TypeError(errmsg)
+
+
+ def _challenge_v1(self, key):
+ html = self.plugin.req.load("http://www.google.com/recaptcha/api/challenge",
+ get={'k': key})
+ try:
+ challenge = re.search("challenge : '(.+?)',", html).group(1)
+ server = re.search("server : '(.+?)',", html).group(1)
+
+ except AttributeError:
+ errmsg = _("ReCaptcha challenge pattern not found")
+ self.plugin.fail(errmsg)
+ raise AttributeError(errmsg)
+
+ self.logDebug("Challenge: %s" % challenge)
+
+ return self.result(server, challenge), challenge
+
+
+ def result(self, server, challenge):
+ result = self.plugin.decryptCaptcha("%simage" % server,
+ get={'c': challenge},
+ cookies=True,
+ forceUser=True,
+ imgtype="jpg")
+
+ self.logDebug("Result: %s" % result)
+
+ return result
+
+
+ def _collectApiInfo(self):
+ html = self.plugin.req.load("http://www.google.com/recaptcha/api.js")
+ a = re.search(r'po.src = \'(.*?)\';', html).group(1)
+ vers = a.split("/")[5]
+
+ self.logDebug("API version: %s" %vers)
+
+ language = a.split("__")[1].split(".")[0]
+
+ self.logDebug("API language: %s" % language)
+
+ html = self.plugin.req.load("https://apis.google.com/js/api.js")
+ b = re.search(r'"h":"(.*?)","', html).group(1)
+ jsh = b.decode('unicode-escape')
+
+ self.logDebug("API jsh-string: %s" % jsh)
+
+ return vers, language, jsh
+
+
+ def _prepareTimeAndRpc(self):
+ self.plugin.req.load("http://www.google.com/recaptcha/api2/demo")
+
+ millis = int(round(time.time() * 1000))
+
+ self.logDebug("Time: %s" % millis)
+
+ rand = randint(1, 99999999)
+ a = "0.%s" % str(rand * 2147483647)
+ rpc = int(100000000 * float(a))
+
+ self.logDebug("Rpc-token: %s" % rpc)
+
+ return millis, rpc
+
+
+ def _challenge_v2(self, key, parent=None):
+ if parent is None:
+ try:
+ parent = urljoin("http://", urlparse(self.plugin.pyfile.url).netloc)
+
+ except Exception:
+ parent = ""
+
+ botguardstring = "!A"
+ vers, language, jsh = self._collectApiInfo()
+ millis, rpc = self._prepareTimeAndRpc()
+
+ html = self.plugin.req.load("https://www.google.com/recaptcha/api2/anchor",
+ get={'k' : key,
+ 'hl' : language,
+ 'v' : vers,
+ 'usegapi' : "1",
+ 'jsh' : "%s#id=IO_%s" % (jsh, millis),
+ 'parent' : parent,
+ 'pfname' : "",
+ 'rpctoken': rpc})
+
+ token1 = re.search(r'id="recaptcha-token" value="(.*?)">', html)
+ self.logDebug("Token #1: %s" % token1.group(1))
+
+ html = self.plugin.req.load("https://www.google.com/recaptcha/api2/frame",
+ get={'c' : token1.group(1),
+ 'hl' : language,
+ 'v' : vers,
+ 'bg' : botguardstring,
+ 'k' : key,
+ 'usegapi': "1",
+ 'jsh' : jsh}).decode('unicode-escape')
+
+ token2 = re.search(r'"finput","(.*?)",', html)
+ self.logDebug("Token #2: %s" % token2.group(1))
+
+ token3 = re.search(r'."asconf".\s,".*?".\s,"(.*?)".', html)
+ self.logDebug("Token #3: %s" % token3.group(1))
+
+ html = self.plugin.req.load("https://www.google.com/recaptcha/api2/reload",
+ post={'k' : key,
+ 'c' : token2.group(1),
+ 'reason': "fi",
+ 'fbg' : token3.group(1)})
+
+ token4 = re.search(r'"rresp","(.*?)",', html)
+ self.logDebug("Token #4: %s" % token4.group(1))
+
+ millis_captcha_loading = int(round(time.time() * 1000))
+ captcha_response = self.plugin.decryptCaptcha("https://www.google.com/recaptcha/api2/payload",
+ get={'c':token4.group(1), 'k':key},
+ cookies=True,
+ forceUser=True)
+ response = b64encode('{"response":"%s"}' % captcha_response)
+
+ self.logDebug("Result: %s" % response)
+
+ timeToSolve = int(round(time.time() * 1000)) - millis_captcha_loading
+ timeToSolveMore = timeToSolve + int(float("0." + str(randint(1, 99999999))) * 500)
+
+ html = self.plugin.req.load("https://www.google.com/recaptcha/api2/userverify",
+ post={'k' : key,
+ 'c' : token4.group(1),
+ 'response': response,
+ 't' : timeToSolve,
+ 'ct' : timeToSolveMore,
+ 'bg' : botguardstring})
+
+ token5 = re.search(r'"uvresp","(.*?)",', html)
+ self.logDebug("Token #5: %s" % token5.group(1))
+
+ result = token5.group(1)
+
+ return result, None
diff --git a/pyload/plugin/captcha/SolveMedia.py b/pyload/plugin/captcha/SolveMedia.py
new file mode 100644
index 000000000..af45101b4
--- /dev/null
+++ b/pyload/plugin/captcha/SolveMedia.py
@@ -0,0 +1,113 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.Captcha import Captcha
+
+
+class SolveMedia(Captcha):
+ __name__ = "SolveMedia"
+ __version__ = "0.12"
+
+ __description__ = """SolveMedia captcha service plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("pyLoad Team", "admin@pyload.org")]
+
+
+ KEY_PATTERN = r'api\.solvemedia\.com/papi/challenge\.(?:no)?script\?k=(.+?)["\']'
+
+
+ def detect_key(self, html=None):
+ if not html:
+ if hasattr(self.plugin, "html") and self.plugin.html:
+ html = self.plugin.html
+ else:
+ errmsg = _("SolveMedia html not found")
+ self.plugin.fail(errmsg)
+ raise TypeError(errmsg)
+
+ m = re.search(self.KEY_PATTERN, html)
+ if m:
+ self.key = m.group(1).strip()
+ self.logDebug("Key: %s" % self.key)
+ return self.key
+ else:
+ self.logDebug("Key not found")
+ return None
+
+
+ def challenge(self, key=None, html=None):
+ if not key:
+ if self.detect_key(html):
+ key = self.key
+ else:
+ errmsg = _("SolveMedia key not found")
+ self.plugin.fail(errmsg)
+ raise TypeError(errmsg)
+
+ html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.noscript",
+ get={'k': key})
+ try:
+ challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="([^"]+)">',
+ html).group(1)
+ server = "http://api.solvemedia.com/papi/media"
+
+ except AttributeError:
+ errmsg = _("SolveMedia challenge pattern not found")
+ self.plugin.fail(errmsg)
+ raise AttributeError(errmsg)
+
+ self.logDebug("Challenge: %s" % challenge)
+
+ result = self.result(server, challenge)
+
+ try:
+ magic = re.search(r'name="magic" value="(.+?)"', html).group(1)
+
+ except AttributeError:
+ self.logDebug("Magic code not found")
+
+ else:
+ if not self._verify(key, magic, result, challenge):
+ self.logDebug("Captcha code was invalid")
+
+ return result, challenge
+
+
+ def _verify(self, key, magic, result, challenge, ref=None): #@TODO: Clean up
+ if ref is None:
+ try:
+ ref = self.plugin.pyfile.url
+
+ except Exception:
+ ref = ""
+
+ html = self.plugin.req.load("http://api.solvemedia.com/papi/verify.noscript",
+ post={'adcopy_response' : result,
+ 'k' : key,
+ 'l' : "en",
+ 't' : "img",
+ 's' : "standard",
+ 'magic' : magic,
+ 'adcopy_challenge' : challenge,
+ 'ref' : ref})
+ try:
+ html = self.plugin.req.load(re.search(r'URL=(.+?)">', html).group(1))
+ gibberish = re.search(r'id=gibberish>(.+?)</textarea>', html).group(1)
+
+ except Exception:
+ return False
+
+ else:
+ return True
+
+
+ def result(self, server, challenge):
+ result = self.plugin.decryptCaptcha(server,
+ get={'c': challenge},
+ cookies=True,
+ imgtype="gif")
+
+ self.logDebug("Result: %s" % result)
+
+ return result
diff --git a/module/plugins/captcha/__init__.py b/pyload/plugin/captcha/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/plugins/captcha/__init__.py
+++ b/pyload/plugin/captcha/__init__.py
diff --git a/pyload/plugin/container/CCF.py b/pyload/plugin/container/CCF.py
new file mode 100644
index 000000000..311eb2006
--- /dev/null
+++ b/pyload/plugin/container/CCF.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import re
+
+from urllib2 import build_opener
+
+from MultipartPostHandler import MultipartPostHandler
+
+from pyload.plugin.Container import Container
+from pyload.utils import fs_encode, safe_join
+
+
+class CCF(Container):
+ __name__ = "CCF"
+ __type__ = "container"
+ __version__ = "0.23"
+
+ __pattern__ = r'.+\.ccf$'
+
+ __description__ = """CCF container decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Willnix", "Willnix@pyload.org"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ def decrypt(self, pyfile):
+ file = fs_encode(pyfile.url.strip())
+ opener = build_opener(MultipartPostHandler)
+
+ dlc_content = opener.open('http://service.jdownloader.net/dlcrypt/getDLC.php',
+ {'src' : "ccf",
+ 'filename': "test.ccf",
+ 'upload' : open(file, "rb")}).read()
+
+ download_folder = self.config['general']['download_folder']
+ dlc_file = safe_join(download_folder, "tmp_%s.dlc" % pyfile.name)
+
+ try:
+ dlc = re.search(r'<dlc>(.+)</dlc>', dlc_content, re.S).group(1).decode('base64')
+
+ except AttributeError:
+ self.fail(_("Container is corrupted"))
+
+ with open(dlc_file, "w") as tempdlc:
+ tempdlc.write(dlc)
+
+ self.urls = [dlc_file]
diff --git a/pyload/plugin/container/DLC.py b/pyload/plugin/container/DLC.py
new file mode 100644
index 000000000..8b8a0199b
--- /dev/null
+++ b/pyload/plugin/container/DLC.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import re
+import xml.dom.minidom
+
+from Crypto.Cipher import AES
+
+from pyload.plugin.Container import Container
+from pyload.utils import decode, fs_encode
+
+
+class DLC(Container):
+ __name__ = "DLC"
+ __type__ = "container"
+ __version__ = "0.24"
+
+ __pattern__ = r'.+\.dlc$'
+
+ __description__ = """DLC container decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("spoob", "spoob@pyload.org"),
+ ("mkaay", "mkaay@mkaay.de"),
+ ("Schnusch", "Schnusch@users.noreply.github.com"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ KEY = "cb99b5cbc24db398"
+ IV = "9bc24cb995cb8db3"
+ API_URL = "http://service.jdownloader.org/dlcrypt/service.php?srcType=dlc&destType=pylo&data=%s"
+
+
+ def decrypt(self, pyfile):
+ file = fs_encode(pyfile.url.strip())
+ with open(file) as dlc:
+ data = dlc.read().strip()
+
+ data += '=' * (-len(data) % 4)
+
+ dlc_key = data[-88:]
+ dlc_data = data[:-88].decode('base64')
+ dlc_content = self.load(self.API_URL % dlc_key)
+
+ try:
+ rc = re.search(r'<rc>(.+)</rc>', dlc_content, re.S).group(1).decode('base64')
+
+ except AttributeError:
+ self.fail(_("Container is corrupted"))
+
+ cipher = AES.new(self.KEY, AES.MODE_CBC, self.IV).decrypt(rc)
+
+ self.data = AES.new(cipher, AES.MODE_CBC, cipher).decrypt(dlc_data).decode('base64')
+ self.packages = [(entry[0] if entry[0] else pyfile.name, entry[1], entry[0] if entry[0] else pyfile.name) \
+ for entry in self.getPackages()]
+
+
+ def getPackages(self):
+ root = xml.dom.minidom.parseString(self.data).documentElement
+ content = root.getElementsByTagName("content")[0]
+ return self.parsePackages(content)
+
+
+ def parsePackages(self, startNode):
+ return [(decode(node.getAttribute("name")).decode('base64'), self.parseLinks(node)) \
+ for node in startNode.getElementsByTagName("package")]
+
+
+ def parseLinks(self, startNode):
+ return [node.getElementsByTagName("url")[0].firstChild.data.decode('base64') \
+ for node in startNode.getElementsByTagName("file")]
diff --git a/pyload/plugin/container/RSDF.py b/pyload/plugin/container/RSDF.py
new file mode 100644
index 000000000..c4b743d14
--- /dev/null
+++ b/pyload/plugin/container/RSDF.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import binascii
+import re
+
+from Crypto.Cipher import AES
+
+from pyload.plugin.Container import Container
+from pyload.utils import fs_encode
+
+
+class RSDF(Container):
+ __name__ = "RSDF"
+ __type__ = "container"
+ __version__ = "0.27"
+
+ __pattern__ = r'.+\.rsdf$'
+
+ __description__ = """RSDF container decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("spoob", "spoob@pyload.org"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ KEY = "8C35192D964DC3182C6F84F3252239EB4A320D2500000000"
+ IV = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+
+
+ def decrypt(self, pyfile):
+ KEY = binascii.unhexlify(self.KEY)
+ IV = AES.new(Key, AES.MODE_ECB).encrypt(binascii.unhexlify(self.IV))
+
+ cipher = AES.new(KEY, AES.MODE_CFB, IV)
+
+ try:
+ file = fs_encode(pyfile.url.strip())
+ with open(file, 'r') as rsdf:
+ data = rsdf.read()
+
+ except IOError, e:
+ self.fail(e)
+
+ if re.search(r"<title>404 - Not Found</title>", data):
+ return
+
+ for link in binascii.unhexlify(''.join(data.split())).splitlines():
+ if link:
+ link = cipher.decrypt(link.decode('base64')).replace('CCF: ', '')
+ self.urls.append(link)
diff --git a/pyload/plugin/container/TXT.py b/pyload/plugin/container/TXT.py
new file mode 100644
index 000000000..2bf5bf2aa
--- /dev/null
+++ b/pyload/plugin/container/TXT.py
@@ -0,0 +1,69 @@
+# -*- coding: utf-8 -*-
+
+import codecs
+
+from pyload.plugin.Container import Container
+from pyload.utils import fs_encode
+
+
+class TXT(Container):
+ __name__ = "TXT"
+ __type__ = "container"
+ __version__ = "0.15"
+
+ __pattern__ = r'.+\.(txt|text)$'
+ __config__ = [("flush" , "bool" , "Flush list after adding", False ),
+ ("encoding", "string", "File encoding" , "utf-8")]
+
+ __description__ = """Read link lists in plain text formats"""
+ __license__ = "GPLv3"
+ __authors__ = [("spoob", "spoob@pyload.org"),
+ ("jeix", "jeix@hasnomail.com")]
+
+
+ def decrypt(self, pyfile):
+ try:
+ encoding = codecs.lookup(self.getConfig("encoding")).name
+
+ except Exception:
+ encoding = "utf-8"
+
+ file = fs_encode(pyfile.url.strip())
+ txt = codecs.open(file, 'r', encoding)
+ curPack = "Parsed links from %s" % pyfile.name
+ packages = {curPack:[],}
+
+ for link in txt.readlines():
+ link = link.strip()
+
+ if not link:
+ continue
+
+ if link.startswith(";"):
+ continue
+
+ if link.startswith("[") and link.endswith("]"):
+ # new package
+ curPack = link[1:-1]
+ packages[curPack] = []
+ continue
+
+ packages[curPack].append(link)
+
+ txt.close()
+
+ # empty packages fix
+ for key, value in packages.iteritems():
+ if not value:
+ packages.pop(key, None)
+
+ if self.getConfig("flush"):
+ try:
+ txt = open(file, 'wb')
+ txt.close()
+
+ except IOError:
+ self.logWarning(_("Failed to flush list"))
+
+ for name, links in packages.iteritems():
+ self.packages.append((name, links, name))
diff --git a/module/plugins/container/__init__.py b/pyload/plugin/container/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/plugins/container/__init__.py
+++ b/pyload/plugin/container/__init__.py
diff --git a/pyload/plugin/crypter/BitshareCom.py b/pyload/plugin/crypter/BitshareCom.py
new file mode 100644
index 000000000..524307127
--- /dev/null
+++ b/pyload/plugin/crypter/BitshareCom.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class BitshareCom(SimpleCrypter):
+ __name__ = "BitshareCom"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?bitshare\.com/\?d=\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Bitshare.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ LINK_PATTERN = r'<a href="(http://bitshare\.com/files/.+)">.+</a></td>'
+ NAME_PATTERN = r'View public folder "(?P<N>.+)"</h1>'
diff --git a/pyload/plugin/crypter/C1NeonCom.py b/pyload/plugin/crypter/C1NeonCom.py
new file mode 100644
index 000000000..dc1555b46
--- /dev/null
+++ b/pyload/plugin/crypter/C1NeonCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class C1NeonCom(DeadCrypter):
+ __name__ = "C1NeonCom"
+ __type__ = "crypter"
+ __version__ = "0.05"
+
+ __pattern__ = r'http://(?:www\.)?c1neon\.com/.+'
+ __config__ = []
+
+ __description__ = """C1neon.com decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("godofdream", "soilfiction@gmail.com")]
diff --git a/module/plugins/crypter/ChipDe.py b/pyload/plugin/crypter/ChipDe.py
index 2f47236e8..2f47236e8 100644
--- a/module/plugins/crypter/ChipDe.py
+++ b/pyload/plugin/crypter/ChipDe.py
diff --git a/pyload/plugin/crypter/CloudzillaTo.py b/pyload/plugin/crypter/CloudzillaTo.py
new file mode 100644
index 000000000..340892136
--- /dev/null
+++ b/pyload/plugin/crypter/CloudzillaTo.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urlparse import urljoin
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class CloudzillaTo(SimpleHoster):
+ __name__ = "CloudzillaTo"
+ __type__ = "crypter"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?cloudzilla\.to/share/folder/(?P<ID>[\w^_]+)'
+
+ __description__ = """Cloudzilla.to folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ INFO_PATTERN = r'<span class="name" title="(?P<N>.+?)"'
+ OFFLINE_PATTERN = r'>File not found...<'
+
+ LINK_PATTERN = r'<a href="(.+?)" class="item_href">'
+
+ PASSWORD_PATTERN = r'<div id="pwd_protected">'
+
+
+ def checkErrors(self):
+ m = re.search(self.PASSWORD_PATTERN, self.html)
+ if m:
+ self.html = self.load(self.pyfile.url, get={'key': self.getPassword()})
+
+ if re.search(self.PASSWORD_PATTERN, self.html):
+ self.retry(reason="Wrong password")
diff --git a/pyload/plugin/crypter/CrockoCom.py b/pyload/plugin/crypter/CrockoCom.py
new file mode 100644
index 000000000..c93f4afab
--- /dev/null
+++ b/pyload/plugin/crypter/CrockoCom.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class CrockoCom(SimpleCrypter):
+ __name__ = "CrockoCom"
+ __type__ = "crypter"
+ __version__ = "0.01"
+
+ __pattern__ = r'http://(?:www\.)?crocko\.com/f/.+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Crocko.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ LINK_PATTERN = r'<td class="last"><a href="([^"]+)">download</a>'
diff --git a/pyload/plugin/crypter/CryptItCom.py b/pyload/plugin/crypter/CryptItCom.py
new file mode 100644
index 000000000..0d72cba61
--- /dev/null
+++ b/pyload/plugin/crypter/CryptItCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class CryptItCom(DeadCrypter):
+ __name__ = "CryptItCom"
+ __type__ = "crypter"
+ __version__ = "0.11"
+
+ __pattern__ = r'http://(?:www\.)?crypt-it\.com/(s|e|d|c)/\w+'
+ __config__ = []
+
+ __description__ = """Crypt-it.com decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("jeix", "jeix@hasnomail.de")]
diff --git a/module/plugins/crypter/CzshareCom.py b/pyload/plugin/crypter/CzshareCom.py
index e527d683f..e527d683f 100644
--- a/module/plugins/crypter/CzshareCom.py
+++ b/pyload/plugin/crypter/CzshareCom.py
diff --git a/module/plugins/crypter/DDLMusicOrg.py b/pyload/plugin/crypter/DDLMusicOrg.py
index 2b6738799..2b6738799 100644
--- a/module/plugins/crypter/DDLMusicOrg.py
+++ b/pyload/plugin/crypter/DDLMusicOrg.py
diff --git a/module/plugins/crypter/DailymotionBatch.py b/pyload/plugin/crypter/DailymotionBatch.py
index c66c7c829..c66c7c829 100644
--- a/module/plugins/crypter/DailymotionBatch.py
+++ b/pyload/plugin/crypter/DailymotionBatch.py
diff --git a/pyload/plugin/crypter/DataHu.py b/pyload/plugin/crypter/DataHu.py
new file mode 100644
index 000000000..f69d6ee3e
--- /dev/null
+++ b/pyload/plugin/crypter/DataHu.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class DataHu(SimpleCrypter):
+ __name__ = "DataHu"
+ __type__ = "crypter"
+ __version__ = "0.06"
+
+ __pattern__ = r'http://(?:www\.)?data\.hu/dir/\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Data.hu folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("crash", ""),
+ ("stickell", "l.stickell@yahoo.it")]
+
+
+ LINK_PATTERN = r'<a href=\'(http://data\.hu/get/.+)\' target=\'_blank\'>\1</a>'
+ NAME_PATTERN = ur'<title>(?P<N>.+) Let\xf6lt\xe9se</title>'
+
+
+ def prepare(self):
+ super(DataHu, self).prepare()
+
+ if u'K\xe9rlek add meg a jelsz\xf3t' in self.html: # Password protected
+ password = self.getPassword()
+ if not password:
+ self.fail(_("Password required"))
+
+ self.logDebug("The folder is password protected', 'Using password: " + password)
+
+ self.html = self.load(self.pyfile.url, post={'mappa_pass': password}, decode=True)
+
+ if u'Hib\xe1s jelsz\xf3' in self.html: # Wrong password
+ self.fail(_("Wrong password"))
diff --git a/pyload/plugin/crypter/DdlstorageCom.py b/pyload/plugin/crypter/DdlstorageCom.py
new file mode 100644
index 000000000..f3744e15d
--- /dev/null
+++ b/pyload/plugin/crypter/DdlstorageCom.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class DdlstorageCom(DeadCrypter):
+ __name__ = "DdlstorageCom"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'https?://(?:www\.)?ddlstorage\.com/folder/\w+'
+ __config__ = []
+
+ __description__ = """DDLStorage.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("godofdream", "soilfiction@gmail.com"),
+ ("stickell", "l.stickell@yahoo.it")]
diff --git a/pyload/plugin/crypter/DepositfilesCom.py b/pyload/plugin/crypter/DepositfilesCom.py
new file mode 100644
index 000000000..24fa9134a
--- /dev/null
+++ b/pyload/plugin/crypter/DepositfilesCom.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class DepositfilesCom(SimpleCrypter):
+ __name__ = "DepositfilesCom"
+ __type__ = "crypter"
+ __version__ = "0.01"
+
+ __pattern__ = r'http://(?:www\.)?depositfiles\.com/folders/\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Depositfiles.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ LINK_PATTERN = r'<div class="progressName"[^>]*>\s*<a href="([^"]+)" title="[^"]*" target="_blank">'
diff --git a/pyload/plugin/crypter/Dereferer.py b/pyload/plugin/crypter/Dereferer.py
new file mode 100644
index 000000000..138282d02
--- /dev/null
+++ b/pyload/plugin/crypter/Dereferer.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.Crypter import Crypter
+
+
+class Dereferer(SimpleDereferer):
+ __name__ = "Dereferer"
+ __type__ = "crypter"
+ __version__ = "0.11"
+
+ __pattern__ = r'https?://([^/]+)/.*?(?P<LINK>(ht|f)tps?(://|%3A%2F%2F).+)'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Crypter for dereferers"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/crypter/DevhostSt.py b/pyload/plugin/crypter/DevhostSt.py
new file mode 100644
index 000000000..4d1a2ae09
--- /dev/null
+++ b/pyload/plugin/crypter/DevhostSt.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# http://d-h.st/users/shine/?fld_id=37263#files
+
+import re
+
+from urlparse import urljoin
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class DevhostSt(SimpleCrypter):
+ __name__ = "DevhostSt"
+ __type__ = "crypter"
+ __version__ = "0.04"
+
+ __pattern__ = r'http://(?:www\.)?d-h\.st/users/(?P<USER>\w+)(/\?fld_id=(?P<ID>\d+))?'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """d-h.st folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ LINK_PATTERN = r'(?:/> |;">)<a href="(.+?)"(?!>Back to \w+<)'
+ OFFLINE_PATTERN = r'"/cHP">test\.png<'
+
+
+ def getFileInfo(self):
+ if re.search(self.OFFLINE_PATTERN, self.html):
+ self.offline()
+
+ try:
+ id = re.match(self.__pattern__, self.pyfile.url).group('ID')
+ if id == "0":
+ raise
+
+ p = r'href="(.+?)">Back to \w+<'
+ m = re.search(p, self.html)
+ html = self.load(urljoin("http://d-h.st", m.group(1)),
+ cookies=False)
+
+ p = '\?fld_id=%s.*?">(.+?)<' % id
+ m = re.search(p, html)
+ name = folder = m.group(1)
+
+ except Exception, e:
+ self.logDebug(e)
+ name = folder = re.match(self.__pattern__, self.pyfile.url).group('USER')
+
+ return {'name': name, 'folder': folder}
diff --git a/pyload/plugin/crypter/DlProtectCom.py b/pyload/plugin/crypter/DlProtectCom.py
new file mode 100644
index 000000000..a5e104f70
--- /dev/null
+++ b/pyload/plugin/crypter/DlProtectCom.py
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from base64 import urlsafe_b64encode
+from time import time
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class DlProtectCom(SimpleCrypter):
+ __name__ = "DlProtectCom"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'https?://(?:www\.)?dl-protect\.com/((en|fr)/)?\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Dl-protect.com decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ COOKIES = [("dl-protect.com", "l", "en")]
+
+ OFFLINE_PATTERN = r'Unfortunately, the link you are looking for is not found'
+
+
+ def getLinks(self):
+ # Direct link with redirect
+ if not re.match(r"https?://(?:www\.)?dl-protect\.com/.+", self.req.http.lastEffectiveURL):
+ return [self.req.http.lastEffectiveURL]
+
+ post_req = {'key' : re.search(r'name="key" value="(.+?)"', self.html).group(1),
+ 'submitform': ""}
+
+ if "Please click on continue to see the content" in self.html:
+ post_req['submitform'] = "Continue"
+ self.wait(2)
+
+ else:
+ mstime = int(round(time() * 1000))
+ b64time = "_" + urlsafe_b64encode(str(mstime)).replace("=", "%3D")
+
+ post_req.update({'i' : b64time,
+ 'submitform': "Decrypt+link"})
+
+ if "Password :" in self.html:
+ post_req['pwd'] = self.getPassword()
+
+ if "Security Code" in self.html:
+ captcha_id = re.search(r'/captcha\.php\?uid=(.+?)"', self.html).group(1)
+ captcha_url = "http://www.dl-protect.com/captcha.php?uid=" + captcha_id
+ captcha_code = self.decryptCaptcha(captcha_url, imgtype="gif")
+
+ post_req['secure'] = captcha_code
+
+ self.html = self.load(self.pyfile.url, post=post_req)
+
+ for errmsg in ("The password is incorrect", "The security code is incorrect"):
+ if errmsg in self.html:
+ self.fail(_(errmsg[1:]))
+
+ return re.findall(r'<a href="([^/].+?)" target="_blank">', self.html)
diff --git a/pyload/plugin/crypter/DontKnowMe.py b/pyload/plugin/crypter/DontKnowMe.py
new file mode 100644
index 000000000..1e83ab853
--- /dev/null
+++ b/pyload/plugin/crypter/DontKnowMe.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.Crypter import Crypter
+
+
+class DontKnowMe(SimpleDereferer):
+ __name__ = "DontKnowMe"
+ __type__ = "crypter"
+ __version__ = "0.11"
+
+ __pattern__ = r'http://(?:www\.)?dontknow\.me/at/\?(?P<LINK>.+)'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """DontKnow.me decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("selaux", "")]
diff --git a/module/plugins/crypter/DuckCryptInfo.py b/pyload/plugin/crypter/DuckCryptInfo.py
index 55681fd5e..55681fd5e 100644
--- a/module/plugins/crypter/DuckCryptInfo.py
+++ b/pyload/plugin/crypter/DuckCryptInfo.py
diff --git a/pyload/plugin/crypter/DuploadOrg.py b/pyload/plugin/crypter/DuploadOrg.py
new file mode 100644
index 000000000..f92eb2ede
--- /dev/null
+++ b/pyload/plugin/crypter/DuploadOrg.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class DuploadOrg(DeadCrypter):
+ __name__ = "DuploadOrg"
+ __type__ = "crypter"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?dupload\.org/folder/\d+'
+ __config__ = []
+
+ __description__ = """Dupload.org folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
diff --git a/pyload/plugin/crypter/EasybytezCom.py b/pyload/plugin/crypter/EasybytezCom.py
new file mode 100644
index 000000000..c5c7b0193
--- /dev/null
+++ b/pyload/plugin/crypter/EasybytezCom.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSCrypter import XFSCrypter
+
+
+class EasybytezCom(XFSCrypter):
+ __name__ = "EasybytezCom"
+ __type__ = "crypter"
+ __version__ = "0.10"
+
+ __pattern__ = r'http://(?:www\.)?easybytez\.com/users/\d+/\d+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Easybytez.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ LOGIN_ACCOUNT = True
diff --git a/module/plugins/crypter/EmbeduploadCom.py b/pyload/plugin/crypter/EmbeduploadCom.py
index c94e7e106..c94e7e106 100644
--- a/module/plugins/crypter/EmbeduploadCom.py
+++ b/pyload/plugin/crypter/EmbeduploadCom.py
diff --git a/pyload/plugin/crypter/FilebeerInfo.py b/pyload/plugin/crypter/FilebeerInfo.py
new file mode 100644
index 000000000..e2e0e1e3c
--- /dev/null
+++ b/pyload/plugin/crypter/FilebeerInfo.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class FilebeerInfo(DeadCrypter):
+ __name__ = "FilebeerInfo"
+ __type__ = "crypter"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?filebeer\.info/\d*~f\w+'
+ __config__ = []
+
+ __description__ = """Filebeer.info folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/crypter/FilecloudIo.py b/pyload/plugin/crypter/FilecloudIo.py
new file mode 100644
index 000000000..f4c967a07
--- /dev/null
+++ b/pyload/plugin/crypter/FilecloudIo.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class FilecloudIo(SimpleCrypter):
+ __name__ = "FilecloudIo"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'https?://(?:www\.)?(filecloud\.io|ifile\.it)/_\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Filecloud.io folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ LINK_PATTERN = r'href="(http://filecloud\.io/\w+)" title'
+ NAME_PATTERN = r'>(?P<N>.+?) - filecloud\.io<'
diff --git a/pyload/plugin/crypter/FilecryptCc.py b/pyload/plugin/crypter/FilecryptCc.py
new file mode 100644
index 000000000..816a2d365
--- /dev/null
+++ b/pyload/plugin/crypter/FilecryptCc.py
@@ -0,0 +1,182 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# http://filecrypt.cc/Container/64E039F859.html
+
+import binascii
+import re
+
+from Crypto.Cipher import AES
+from urlparse import urljoin
+
+from pyload.plugin.Crypter import Crypter
+from pyload.plugin.internal.CaptchaService import ReCaptcha
+
+
+class FilecryptCc(Crypter):
+ __name__ = "FilecryptCc"
+ __type__ = "crypter"
+ __version__ = "0.11"
+
+ __pattern__ = r'https?://(?:www\.)?filecrypt\.cc/Container/\w+'
+
+ __description__ = """Filecrypt.cc decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
+
+
+ # URL_REPLACEMENTS = [(r'.html$', ""), (r'$', ".html")] #@TODO: Extend SimpleCrypter
+
+ DLC_LINK_PATTERN = r'<button class="dlcdownload" type="button" title="Download \*.dlc" onclick="DownloadDLC\(\'(.+)\'\);"><i></i><span>dlc<'
+ WEBLINK_PATTERN = r"openLink.?'([\w_-]*)',"
+
+ CAPTCHA_PATTERN = r'<img id="nc" src="(.+?)"'
+ CIRCLE_CAPTCHA_PATTERN = r'<input type="image" src="(.+?)"'
+
+ MIRROR_PAGE_PATTERN = r'"[\w]*" href="(http://filecrypt.cc/Container/\w+\.html\?mirror=\d+)">'
+
+
+ def setup(self):
+ self.links = []
+
+
+ def decrypt(self, pyfile):
+ self.html = self.load(pyfile.url, cookies=True)
+
+ if "content notfound" in self.html: #@NOTE: "content notfound" is NOT a typo
+ self.offline()
+
+ self.handlePasswordProtection()
+ self.handleCaptcha()
+ self.handleMirrorPages()
+
+ for handle in (self.handleCNL, self.handleWeblinks, self.handleDlcContainer):
+ handle()
+ if self.links:
+ self.packages = [(pyfile.package().name, self.links, pyfile.package().name)]
+ return
+
+
+ def handleMirrorPages(self):
+ if "mirror=" not in self.siteWithLinks:
+ return
+
+ mirror = re.findall(self.MIRROR_PAGE_PATTERN, self.siteWithLinks)
+
+ self.logInfo(_("Found %d mirrors") % len(mirror))
+
+ for i in mirror[1:]:
+ self.siteWithLinks = self.siteWithLinks + self.load(i, cookies=True).decode("utf-8", "replace")
+
+
+ def handlePasswordProtection(self):
+ if '<input type="text" name="password"' not in self.html:
+ return
+
+ self.logInfo(_("Folder is password protected"))
+
+ password = self.getPassword()
+
+ if not password:
+ self.fail(_("Please enter the password in package section and try again"))
+
+ self.html = self.load(self.pyfile.url, post={"password": password}, cookies=True)
+
+
+ def handleCaptcha(self):
+ m = re.search(self.CAPTCHA_PATTERN, self.html)
+ m2 = re.search(self.CIRCLE_CAPTCHA_PATTERN, self.html)
+
+ if m: #: normal captcha
+ self.logDebug("Captcha-URL: %s" % m.group(1))
+
+ captcha_code = self.decryptCaptcha(urljoin("http://filecrypt.cc", m.group(1)),
+ forceUser=True,
+ imgtype="gif")
+
+ self.siteWithLinks = self.load(self.pyfile.url,
+ post={'recaptcha_response_field': captcha_code},
+ cookies=True,
+ decode=True)
+ elif m2: #: circle captcha
+ self.logDebug("Captcha-URL: %s" % m2.group(1))
+
+ captcha_code = self.decryptCaptcha(urljoin("http://filecrypt.cc", m2.group(1)),
+ forceUser=True,
+ imgtype="gif",
+ result_type='positional')
+
+ self.siteWithLinks = self.load(self.pyfile.url,
+ post={'button.x': captcha_code[0], 'button.y': captcha_code[1]},
+ cookies=True,
+ decode=True)
+
+ else:
+ recaptcha = ReCaptcha(self)
+ captcha_key = recaptcha.detect_key()
+
+ if captcha_key:
+ response, challenge = recaptcha.challenge(captcha_key)
+ self.siteWithLinks = self.load(self.pyfile.url,
+ post={'g-recaptcha-response': response},
+ decode=True)
+ else:
+ self.logInfo(_("No captcha found"))
+ self.siteWithLinks = self.html
+
+ if "recaptcha_image" in self.siteWithLinks or "data-sitekey" in self.siteWithLinks:
+ self.invalidCaptcha()
+ self.retry()
+
+
+ def handleDlcContainer(self):
+ dlc = re.findall(self.DLC_LINK_PATTERN, self.siteWithLinks)
+
+ if not dlc:
+ return
+
+ for i in dlc:
+ self.links.append("http://filecrypt.cc/DLC/%s.dlc" % i)
+
+
+ def handleWeblinks(self):
+ try:
+ weblinks = re.findall(self.WEBLINK_PATTERN, self.siteWithLinks)
+
+ for link in weblinks:
+ res = self.load("http://filecrypt.cc/Link/%s.html" % link, cookies=True)
+ link2 = re.search('<iframe noresize src="(.*)"></iframe>', res)
+ res2 = self.load(link2.group(1), just_header=True, cookies=True)
+ self.links.append(res2['location'])
+
+ except Exception, e:
+ self.logDebug("Error decrypting weblinks: %s" % e)
+
+
+ def handleCNL(self):
+ try:
+ vjk = re.findall('<input type="hidden" name="jk" value="function f\(\){ return \'(.*)\';}">', self.siteWithLinks)
+ vcrypted = re.findall('<input type="hidden" name="crypted" value="(.*)">', self.siteWithLinks)
+
+ for i in xrange(len(vcrypted)):
+ self.links.extend(self._getLinks(vcrypted[i], vjk[i]))
+
+ except Exception, e:
+ self.logDebug("Error decrypting CNL: %s" % e)
+
+
+ def _getLinks(self, crypted, jk):
+ # Get key
+ key = binascii.unhexlify(str(jk))
+
+ # Decrypt
+ Key = key
+ IV = key
+ obj = AES.new(Key, AES.MODE_CBC, IV)
+ text = obj.decrypt(crypted.decode('base64'))
+
+ # Extract links
+ text = text.replace("\x00", "").replace("\r", "")
+ links = filter(bool, text.split('\n'))
+
+ return links
diff --git a/pyload/plugin/crypter/FilefactoryCom.py b/pyload/plugin/crypter/FilefactoryCom.py
new file mode 100644
index 000000000..40f4c1475
--- /dev/null
+++ b/pyload/plugin/crypter/FilefactoryCom.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class FilefactoryCom(SimpleCrypter):
+ __name__ = "FilefactoryCom"
+ __type__ = "crypter"
+ __version__ = "0.32"
+
+ __pattern__ = r'https?://(?:www\.)?filefactory\.com/(?:f|folder)/\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Filefactory.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ COOKIES = [("filefactory.com", "locale", "en_US.utf8")]
+
+ LINK_PATTERN = r'<td>\s*<a href="(.+?)"'
+ NAME_PATTERN = r'<h1>Files in <span>(?P<N>.+?)<'
+ PAGES_PATTERN = r'data-paginator-totalPages="(\d+)'
+
+
+ def loadPage(self, page_n):
+ return self.load(self.pyfile.url, get={'page': page_n, 'show': 100})
diff --git a/pyload/plugin/crypter/FilerNet.py b/pyload/plugin/crypter/FilerNet.py
new file mode 100644
index 000000000..45d0dd2ab
--- /dev/null
+++ b/pyload/plugin/crypter/FilerNet.py
@@ -0,0 +1,24 @@
+import re
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class FilerNet(SimpleCrypter):
+ __name__ = "FilerNet"
+ __type__ = "crypter"
+ __version__ = "0.42"
+
+ __pattern__ = r'https?://filer\.net/folder/\w{16}'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Filer.net decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("nath_schwarz", "nathan.notwhite@gmail.com"),
+ ("stickell", "l.stickell@yahoo.it")]
+
+
+ LINK_PATTERN = r'href="(/get/\w{16})">(?!<)'
+
+ NAME_PATTERN = r'<h3>(?P<N>.+?) - <small'
+ OFFLINE_PATTERN = r'Nicht gefunden'
diff --git a/module/plugins/crypter/FileserveCom.py b/pyload/plugin/crypter/FileserveCom.py
index ab0665fbd..ab0665fbd 100644
--- a/module/plugins/crypter/FileserveCom.py
+++ b/pyload/plugin/crypter/FileserveCom.py
diff --git a/pyload/plugin/crypter/FilesonicCom.py b/pyload/plugin/crypter/FilesonicCom.py
new file mode 100644
index 000000000..1ffaa9c01
--- /dev/null
+++ b/pyload/plugin/crypter/FilesonicCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class FilesonicCom(DeadCrypter):
+ __name__ = "FilesonicCom"
+ __type__ = "crypter"
+ __version__ = "0.12"
+
+ __pattern__ = r'http://(?:www\.)?filesonic\.com/folder/\w+'
+
+ __description__ = """Filesonic.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/crypter/FilestubeCom.py b/pyload/plugin/crypter/FilestubeCom.py
new file mode 100644
index 000000000..36e4a4caf
--- /dev/null
+++ b/pyload/plugin/crypter/FilestubeCom.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class FilestubeCom(SimpleCrypter):
+ __name__ = "FilestubeCom"
+ __type__ = "crypter"
+ __version__ = "0.05"
+
+ __pattern__ = r'http://(?:www\.)?filestube\.(?:com|to)/\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Filestube.com decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ LINK_PATTERN = r'<a class=\"file-link-main(?: noref)?\" [^>]* href=\"(http://[^\"]+)'
+ NAME_PATTERN = r'<h1\s*> (?P<N>.+) download\s*</h1>'
diff --git a/pyload/plugin/crypter/FiletramCom.py b/pyload/plugin/crypter/FiletramCom.py
new file mode 100644
index 000000000..700050a4b
--- /dev/null
+++ b/pyload/plugin/crypter/FiletramCom.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class FiletramCom(SimpleCrypter):
+ __name__ = "FiletramCom"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?filetram\.com/[^/]+/.+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Filetram.com decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("igel", "igelkun@myopera.com"),
+ ("stickell", "l.stickell@yahoo.it")]
+
+
+ LINK_PATTERN = r'\s+(http://.+)'
+ NAME_PATTERN = r'<title>(?P<N>.+?) - Free Download'
diff --git a/pyload/plugin/crypter/FiredriveCom.py b/pyload/plugin/crypter/FiredriveCom.py
new file mode 100644
index 000000000..e258ed42f
--- /dev/null
+++ b/pyload/plugin/crypter/FiredriveCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class FiredriveCom(DeadCrypter):
+ __name__ = "FiredriveCom"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'https?://(?:www\.)?(firedrive|putlocker)\.com/share/.+'
+ __config__ = []
+
+ __description__ = """Firedrive.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
diff --git a/module/plugins/crypter/FourChanOrg.py b/pyload/plugin/crypter/FourChanOrg.py
index 62fb9d3fe..62fb9d3fe 100644
--- a/module/plugins/crypter/FourChanOrg.py
+++ b/pyload/plugin/crypter/FourChanOrg.py
diff --git a/pyload/plugin/crypter/FreakhareCom.py b/pyload/plugin/crypter/FreakhareCom.py
new file mode 100644
index 000000000..cb766361c
--- /dev/null
+++ b/pyload/plugin/crypter/FreakhareCom.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class FreakhareCom(SimpleCrypter):
+ __name__ = "FreakhareCom"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?freakshare\.com/folder/.+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Freakhare.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ LINK_PATTERN = r'<a href="(http://freakshare\.com/files/[^"]+)" target="_blank">'
+ NAME_PATTERN = r'Folder:</b> (?P<N>.+)'
+ PAGES_PATTERN = r'Pages: +(\d+)'
+
+
+ def loadPage(self, page_n):
+ if not hasattr(self, 'f_id') and not hasattr(self, 'f_md5'):
+ m = re.search(r'http://freakshare.com/\?x=folder&f_id=(\d+)&f_md5=(\w+)', self.html)
+ if m:
+ self.f_id = m.group(1)
+ self.f_md5 = m.group(2)
+ return self.load('http://freakshare.com/', get={'x': 'folder',
+ 'f_id': self.f_id,
+ 'f_md5': self.f_md5,
+ 'entrys': '20',
+ 'page': page_n - 1,
+ 'order': ''}, decode=True)
diff --git a/pyload/plugin/crypter/FreetexthostCom.py b/pyload/plugin/crypter/FreetexthostCom.py
new file mode 100644
index 000000000..3b082ef7d
--- /dev/null
+++ b/pyload/plugin/crypter/FreetexthostCom.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class FreetexthostCom(SimpleCrypter):
+ __name__ = "FreetexthostCom"
+ __type__ = "crypter"
+ __version__ = "0.01"
+
+ __pattern__ = r'http://(?:www\.)?freetexthost\.com/\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Freetexthost.com decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ def getLinks(self):
+ m = re.search(r'<div id="contentsinner">\s*(.+)<div class="viewcount">', self.html, re.S)
+ if m is None:
+ self.error(_("Unable to extract links"))
+ links = m.group(1)
+ return links.strip().split("<br />\r\n")
diff --git a/pyload/plugin/crypter/FshareVn.py b/pyload/plugin/crypter/FshareVn.py
new file mode 100644
index 000000000..700f87ba4
--- /dev/null
+++ b/pyload/plugin/crypter/FshareVn.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class FshareVn(SimpleCrypter):
+ __name__ = "FshareVn"
+ __type__ = "crypter"
+ __version__ = "0.01"
+
+ __pattern__ = r'http://(?:www\.)?fshare\.vn/folder/.+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Fshare.vn folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ LINK_PATTERN = r'<li class="w_80pc"><a href="([^"]+)" target="_blank">'
diff --git a/pyload/plugin/crypter/Go4UpCom.py b/pyload/plugin/crypter/Go4UpCom.py
new file mode 100644
index 000000000..5bae6e93a
--- /dev/null
+++ b/pyload/plugin/crypter/Go4UpCom.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urlparse import urljoin
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class Go4UpCom(SimpleCrypter):
+ __name__ = "Go4UpCom"
+ __type__ = "crypter"
+ __version__ = "0.11"
+
+ __pattern__ = r'http://go4up\.com/(dl/\w{12}|rd/\w{12}/\d+)'
+
+ __description__ = """Go4Up.com decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("rlindner81", "rlindner81@gmail.com"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ LINK_PATTERN = r'(http://go4up\.com/rd/.+?)<'
+
+ NAME_PATTERN = r'<title>Download (.+?)<'
+
+ OFFLINE_PATTERN = r'>\s*(404 Page Not Found|File not Found|Mirror does not exist)'
+
+
+ def getLinks(self
+ links = []
+
+ m = re.search(r'(/download/gethosts/.+?)"')
+ if m:
+ self.html = self.load(urljoin("http://go4up.com/", m.group(1)))
+ pages = [self.load(url) for url in re.findall(self.LINK_PATTERN, self.html)]
+ else:
+ pages = [self.html]
+
+ for html in pages:
+ try:
+ links.append(re.search(r'<b><a href="(.+?)"', html).group(1))
+ except Exception:
+ continue
+
+ return links
diff --git a/module/plugins/crypter/GooGl.py b/pyload/plugin/crypter/GooGl.py
index 13ffce505..13ffce505 100644
--- a/module/plugins/crypter/GooGl.py
+++ b/pyload/plugin/crypter/GooGl.py
diff --git a/module/plugins/crypter/HoerbuchIn.py b/pyload/plugin/crypter/HoerbuchIn.py
index a12d7c02a..a12d7c02a 100644
--- a/module/plugins/crypter/HoerbuchIn.py
+++ b/pyload/plugin/crypter/HoerbuchIn.py
diff --git a/pyload/plugin/crypter/HotfileCom.py b/pyload/plugin/crypter/HotfileCom.py
new file mode 100644
index 000000000..8085aa797
--- /dev/null
+++ b/pyload/plugin/crypter/HotfileCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class HotfileCom(DeadCrypter):
+ __name__ = "HotfileCom"
+ __type__ = "crypter"
+ __version__ = "0.30"
+
+ __pattern__ = r'https?://(?:www\.)?hotfile\.com/list/\w+/\w+'
+ __config__ = []
+
+ __description__ = """Hotfile.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org")]
diff --git a/pyload/plugin/crypter/ILoadTo.py b/pyload/plugin/crypter/ILoadTo.py
new file mode 100644
index 000000000..f333e262f
--- /dev/null
+++ b/pyload/plugin/crypter/ILoadTo.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class ILoadTo(DeadCrypter):
+ __name__ = "ILoadTo"
+ __type__ = "crypter"
+ __version__ = "0.11"
+
+ __pattern__ = r'http://(?:www\.)?iload\.to/go/\d+-[\w.-]+/'
+ __config__ = []
+
+ __description__ = """Iload.to decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("hzpz", "")]
diff --git a/pyload/plugin/crypter/ImgurComAlbum.py b/pyload/plugin/crypter/ImgurComAlbum.py
new file mode 100644
index 000000000..d2ca38d40
--- /dev/null
+++ b/pyload/plugin/crypter/ImgurComAlbum.py
@@ -0,0 +1,27 @@
+import re
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+from pyload.utils import uniqify
+
+
+class ImgurComAlbum(SimpleCrypter):
+ __name__ = "ImgurComAlbum"
+ __type__ = "crypter"
+ __version__ = "0.51"
+
+ __pattern__ = r'https?://(?:www\.|m\.)?imgur\.com/(a|gallery|)/?\w{5,7}'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Imgur.com decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("nath_schwarz", "nathan.notwhite@gmail.com")]
+
+
+ NAME_PATTERN = r'(?P<N>.+?) - Imgur'
+ LINK_PATTERN = r'i\.imgur\.com/\w{7}s?\.(?:jpeg|jpg|png|gif|apng)'
+
+
+ def getLinks(self):
+ f = lambda url: "http://" + re.sub(r'(\w{7})s\.', r'\1.', url)
+ return uniqify(map(f, re.findall(self.LINK_PATTERN, self.html)))
diff --git a/module/plugins/crypter/LetitbitNet.py b/pyload/plugin/crypter/LetitbitNet.py
index 24bc196b3..24bc196b3 100644
--- a/module/plugins/crypter/LetitbitNet.py
+++ b/pyload/plugin/crypter/LetitbitNet.py
diff --git a/module/plugins/crypter/LinkCryptWs.py b/pyload/plugin/crypter/LinkCryptWs.py
index a3eb4f179..a3eb4f179 100644
--- a/module/plugins/crypter/LinkCryptWs.py
+++ b/pyload/plugin/crypter/LinkCryptWs.py
diff --git a/pyload/plugin/crypter/LinkSaveIn.py b/pyload/plugin/crypter/LinkSaveIn.py
new file mode 100644
index 000000000..b303303a0
--- /dev/null
+++ b/pyload/plugin/crypter/LinkSaveIn.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleDereferer import SimpleDereferer
+
+
+class LinkSaveIn(SimpleDereferer):
+ __name__ = "LinkSaveIn"
+ __type__ = "crypter"
+ __version__ = "2.03"
+
+ __pattern__ = r'https?://(?:www\.)?linksave\.in/\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """LinkSave.in decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ COOKIES = [("linksave.in", "Linksave_Language", "english")]
+
+ OFFLINE_PATTERN = r'>(Error )?404 -'
diff --git a/module/plugins/crypter/LinkdecrypterCom.py b/pyload/plugin/crypter/LinkdecrypterCom.py
index facec37d5..facec37d5 100644
--- a/module/plugins/crypter/LinkdecrypterCom.py
+++ b/pyload/plugin/crypter/LinkdecrypterCom.py
diff --git a/module/plugins/crypter/LixIn.py b/pyload/plugin/crypter/LixIn.py
index 4b978723f..4b978723f 100644
--- a/module/plugins/crypter/LixIn.py
+++ b/pyload/plugin/crypter/LixIn.py
diff --git a/pyload/plugin/crypter/LofCc.py b/pyload/plugin/crypter/LofCc.py
new file mode 100644
index 000000000..076ab59d7
--- /dev/null
+++ b/pyload/plugin/crypter/LofCc.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class LofCc(DeadCrypter):
+ __name__ = "LofCc"
+ __type__ = "crypter"
+ __version__ = "0.21"
+
+ __pattern__ = r'http://(?:www\.)?lof\.cc/(.+)'
+ __config__ = []
+
+ __description__ = """Lof.cc decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("mkaay", "mkaay@mkaay.de")]
diff --git a/pyload/plugin/crypter/MBLinkInfo.py b/pyload/plugin/crypter/MBLinkInfo.py
new file mode 100644
index 000000000..7e7be2029
--- /dev/null
+++ b/pyload/plugin/crypter/MBLinkInfo.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class MBLinkInfo(DeadCrypter):
+ __name__ = "MBLinkInfo"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?mblink\.info/?\?id=(\d+)'
+ __config__ = []
+
+ __description__ = """MBLink.info decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Gummibaer", "Gummibaer@wiki-bierkiste.de"),
+ ("stickell", "l.stickell@yahoo.it")]
diff --git a/module/plugins/crypter/MediafireCom.py b/pyload/plugin/crypter/MediafireCom.py
index a7360a6db..a7360a6db 100644
--- a/module/plugins/crypter/MediafireCom.py
+++ b/pyload/plugin/crypter/MediafireCom.py
diff --git a/pyload/plugin/crypter/MegaCoNz.py b/pyload/plugin/crypter/MegaCoNz.py
new file mode 100644
index 000000000..3f1d10a5a
--- /dev/null
+++ b/pyload/plugin/crypter/MegaCoNz.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.Crypter import Crypter
+
+
+class MegaCoNz(Crypter):
+ __name__ = "MegaCoNz"
+ __type__ = "crypter"
+ __version__ = "0.04"
+
+ __pattern__ = r'(?:https?://(?:www\.)?mega\.co\.nz/|mega:|chrome:.+?)#F!(?P<ID>[\w^_]+)!(?P<KEY>[\w,\\-]+)'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Mega.co.nz folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ def setup(self):
+ self.req.setOption("timeout", 300)
+
+
+ def decrypt(self, pyfile):
+ url = "https://mega.co.nz/#F!%s!%s" % re.match(self.__pattern__, pyfile.url).groups()
+ self.html = self.load("http://rapidgen.org/linkfinder", post={'linklisturl': url})
+ self.urls = re.findall(r'(https://mega.co.nz/#N!.+?)<', self.html)
+
+ if not self.urls: #@TODO: Remove in 0.4.10
+ self.fail(_("No link grabbed"))
diff --git a/pyload/plugin/crypter/MegaRapidCz.py b/pyload/plugin/crypter/MegaRapidCz.py
new file mode 100644
index 000000000..79900c08a
--- /dev/null
+++ b/pyload/plugin/crypter/MegaRapidCz.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class MegaRapidCz(SimpleCrypter):
+ __name__ = "MegaRapidCz"
+ __type__ = "crypter"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?(share|mega)rapid\.cz/slozka/\d+/\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Share-Rapid.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ LINK_PATTERN = r'<td class="soubor"[^>]*><a href="([^"]+)">'
diff --git a/pyload/plugin/crypter/MegauploadCom.py b/pyload/plugin/crypter/MegauploadCom.py
new file mode 100644
index 000000000..72e0268dd
--- /dev/null
+++ b/pyload/plugin/crypter/MegauploadCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class MegauploadCom(DeadCrypter):
+ __name__ = "MegauploadCom"
+ __type__ = "crypter"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?megaupload\.com/(\?f|xml/folderfiles\.php\?.*&?folderid)=\w+'
+
+ __description__ = """Megaupload.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/crypter/Movie2KTo.py b/pyload/plugin/crypter/Movie2KTo.py
new file mode 100644
index 000000000..f8ff4e756
--- /dev/null
+++ b/pyload/plugin/crypter/Movie2KTo.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class Movie2KTo(DeadCrypter):
+ __name__ = "Movie2KTo"
+ __type__ = "crypter"
+ __version__ = "0.51"
+
+ __pattern__ = r'http://(?:www\.)?movie2k\.to/(.+)\.html'
+ __config__ = []
+
+ __description__ = """Movie2k.to decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("4Christopher", "4Christopher@gmx.de")]
diff --git a/pyload/plugin/crypter/MultiUpOrg.py b/pyload/plugin/crypter/MultiUpOrg.py
new file mode 100644
index 000000000..1585ac1c8
--- /dev/null
+++ b/pyload/plugin/crypter/MultiUpOrg.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+
+import re
+from urlparse import urljoin
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class MultiUpOrg(SimpleCrypter):
+ __name__ = "MultiUpOrg"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?multiup\.org/(en|fr)/(?P<TYPE>project|download|miror)/\w+(/\w+)?'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """MultiUp.org decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ NAME_PATTERN = r'<title>.*(?:Project|Projet|ownload|élécharger) (?P<N>.+?) (\(|- )'
+
+
+ def getLinks(self):
+ m_type = re.match(self.__pattern__, self.pyfile.url).group('TYPE')
+
+ if m_type == "project":
+ pattern = r'\n(http://www\.multiup\.org/(?:en|fr)/download/.*)'
+ else:
+ pattern = r'style="width:97%;text-align:left".*\n.*href="(.*)"'
+ if m_type == "download":
+ dl_pattern = r'href="(.*)">.*\n.*<h5>DOWNLOAD</h5>'
+ miror_page = urljoin("http://www.multiup.org", re.search(dl_pattern, self.html).group(1))
+ self.html = self.load(miror_page)
+
+ return re.findall(pattern, self.html)
diff --git a/module/plugins/crypter/MultiloadCz.py b/pyload/plugin/crypter/MultiloadCz.py
index 856a94a25..856a94a25 100644
--- a/module/plugins/crypter/MultiloadCz.py
+++ b/pyload/plugin/crypter/MultiloadCz.py
diff --git a/pyload/plugin/crypter/MultiuploadCom.py b/pyload/plugin/crypter/MultiuploadCom.py
new file mode 100644
index 000000000..9127140f1
--- /dev/null
+++ b/pyload/plugin/crypter/MultiuploadCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class MultiuploadCom(DeadCrypter):
+ __name__ = "MultiuploadCom"
+ __type__ = "crypter"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?multiupload\.(com|nl)/\w+'
+
+ __description__ = """MultiUpload.com decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/module/plugins/crypter/NCryptIn.py b/pyload/plugin/crypter/NCryptIn.py
index 29b45b11a..29b45b11a 100644
--- a/module/plugins/crypter/NCryptIn.py
+++ b/pyload/plugin/crypter/NCryptIn.py
diff --git a/pyload/plugin/crypter/NetfolderIn.py b/pyload/plugin/crypter/NetfolderIn.py
new file mode 100644
index 000000000..a24a5270f
--- /dev/null
+++ b/pyload/plugin/crypter/NetfolderIn.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class NetfolderIn(SimpleCrypter):
+ __name__ = "NetfolderIn"
+ __type__ = "crypter"
+ __version__ = "0.72"
+
+ __pattern__ = r'http://(?:www\.)?netfolder\.in/(folder\.php\?folder_id=)?(?P<ID>\w+)(?(1)|/\w+)'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """NetFolder.in decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("fragonib", "fragonib[AT]yahoo[DOT]es")]
+
+
+ NAME_PATTERN = r'<div class="Text">Inhalt des Ordners <span.*>(?P<N>.+)</span></div>'
+
+
+ def prepare(self):
+ super(NetfolderIn, self).prepare()
+
+ # Check for password protection
+ if self.isPasswordProtected():
+ self.html = self.submitPassword()
+ if not self.html:
+ self.fail(_("Incorrect password, please set right password on Add package form and retry"))
+
+
+ def isPasswordProtected(self):
+ if '<input type="password" name="password"' in self.html:
+ self.logDebug("Links are password protected")
+ return True
+ return False
+
+
+ def submitPassword(self):
+ # Gather data
+ try:
+ m = re.match(self.__pattern__, self.pyfile.url)
+ id = m.group('ID')
+ except AttributeError:
+ self.logDebug("Unable to get package id from url [%s]" % self.pyfile.url)
+ return
+ url = "http://netfolder.in/folder.php?folder_id=" + id
+ password = self.getPassword()
+
+ # Submit package password
+ post = {'password': password, 'save': 'Absenden'}
+ self.logDebug("Submitting password [%s] for protected links with id [%s]" % (password, id))
+ html = self.load(url, {}, post)
+
+ # Check for invalid password
+ if '<div class="InPage_Error">' in html:
+ self.logDebug("Incorrect password, please set right password on Edit package form and retry")
+ return None
+
+ return html
+
+
+ def getLinks(self):
+ links = re.search(r'name="list" value="(.*?)"', self.html).group(1).split(",")
+ self.logDebug("Package has %d links" % len(links))
+ return links
diff --git a/pyload/plugin/crypter/NosvideoCom.py b/pyload/plugin/crypter/NosvideoCom.py
new file mode 100644
index 000000000..d048ec956
--- /dev/null
+++ b/pyload/plugin/crypter/NosvideoCom.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class NosvideoCom(SimpleCrypter):
+ __name__ = "NosvideoCom"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?nosvideo\.com/\?v=\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Nosvideo.com decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("igel", "igelkun@myopera.com")]
+
+
+ LINK_PATTERN = r'href="(http://(?:w{3}\.)?nosupload\.com/\?d=\w+)"'
+ NAME_PATTERN = r'<[tT]itle>Watch (?P<N>.+?)<'
diff --git a/module/plugins/crypter/OneKhDe.py b/pyload/plugin/crypter/OneKhDe.py
index 323214df8..323214df8 100644
--- a/module/plugins/crypter/OneKhDe.py
+++ b/pyload/plugin/crypter/OneKhDe.py
diff --git a/pyload/plugin/crypter/OronCom.py b/pyload/plugin/crypter/OronCom.py
new file mode 100644
index 000000000..257e0e046
--- /dev/null
+++ b/pyload/plugin/crypter/OronCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class OronCom(DeadCrypter):
+ __name__ = "OronCom"
+ __type__ = "crypter"
+ __version__ = "0.11"
+
+ __pattern__ = r'http://(?:www\.)?oron\.com/folder/\w+'
+ __config__ = []
+
+ __description__ = """Oron.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("DHMH", "webmaster@pcProfil.de")]
diff --git a/pyload/plugin/crypter/PastebinCom.py b/pyload/plugin/crypter/PastebinCom.py
new file mode 100644
index 000000000..43a818cf1
--- /dev/null
+++ b/pyload/plugin/crypter/PastebinCom.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class PastebinCom(SimpleCrypter):
+ __name__ = "PastebinCom"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?pastebin\.com/\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Pastebin.com decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ LINK_PATTERN = r'<div class="de\d+">(https?://[^ <]+)(?:[^<]*)</div>'
+ NAME_PATTERN = r'<div class="paste_box_line1" title="(?P<N>[^"]+)">'
diff --git a/module/plugins/crypter/QuickshareCz.py b/pyload/plugin/crypter/QuickshareCz.py
index 8cd4b9c02..8cd4b9c02 100644
--- a/module/plugins/crypter/QuickshareCz.py
+++ b/pyload/plugin/crypter/QuickshareCz.py
diff --git a/pyload/plugin/crypter/RSLayerCom.py b/pyload/plugin/crypter/RSLayerCom.py
new file mode 100644
index 000000000..8ea8a4369
--- /dev/null
+++ b/pyload/plugin/crypter/RSLayerCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class RSLayerCom(DeadCrypter):
+ __name__ = "RSLayerCom"
+ __type__ = "crypter"
+ __version__ = "0.21"
+
+ __pattern__ = r'http://(?:www\.)?rs-layer\.com/directory-'
+ __config__ = []
+
+ __description__ = """RS-Layer.com decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("hzpz", "")]
diff --git a/pyload/plugin/crypter/RelinkUs.py b/pyload/plugin/crypter/RelinkUs.py
new file mode 100644
index 000000000..0c27c29b5
--- /dev/null
+++ b/pyload/plugin/crypter/RelinkUs.py
@@ -0,0 +1,293 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import binascii
+import re
+import os
+
+from Crypto.Cipher import AES
+from pyload.plugin.Crypter import Crypter
+from pyload.utils import safe_join
+
+
+class RelinkUs(Crypter):
+ __name__ = "RelinkUs"
+ __type__ = "crypter"
+ __version__ = "3.12"
+
+ __pattern__ = r'http://(?:www\.)?relink\.us/(f/|((view|go)\.php\?id=))(?P<ID>.+)'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Relink.us decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("fragonib", "fragonib[AT]yahoo[DOT]es"),
+ ("AndroKev", "neureither.kevin@gmail.com")]
+
+
+ PREFERRED_LINK_SOURCES = ["cnl2", "dlc", "web"]
+
+ OFFLINE_TOKEN = r'<title>Tattooside'
+
+ PASSWORD_TOKEN = r'container_password.php'
+ PASSWORD_ERROR_ROKEN = r'You have entered an incorrect password'
+ PASSWORD_SUBMIT_URL = r'http://www.relink.us/container_password.php'
+
+ CAPTCHA_TOKEN = r'container_captcha.php'
+ CAPTCHA_ERROR_ROKEN = r'You have solved the captcha wrong'
+ CAPTCHA_IMG_URL = r'http://www.relink.us/core/captcha/circlecaptcha.php'
+ CAPTCHA_SUBMIT_URL = r'http://www.relink.us/container_captcha.php'
+
+ FILE_TITLE_REGEX = r'<th>Title</th><td>(.*)</td></tr>'
+ FILE_NOTITLE = r'No title'
+
+ CNL2_FORM_REGEX = r'<form id="cnl_form-(.*?)</form>'
+ CNL2_FORMINPUT_REGEX = r'<input.*?name="%s".*?value="(.*?)"'
+ CNL2_JK_KEY = "jk"
+ CNL2_CRYPTED_KEY = "crypted"
+
+ DLC_LINK_REGEX = r'<a href=".*?" class="dlc_button" target="_blank">'
+ DLC_DOWNLOAD_URL = r'http://www.relink.us/download.php'
+
+ WEB_FORWARD_REGEX = r'getFile\(\'(.+)\'\)'
+ WEB_FORWARD_URL = r'http://www.relink.us/frame.php'
+ WEB_LINK_REGEX = r'<iframe name="Container" height="100%" frameborder="no" width="100%" src="(.+)"></iframe>'
+
+
+ def setup(self):
+ self.fileid = None
+ self.package = None
+ self.captcha = False
+
+
+ def decrypt(self, pyfile):
+ # Init
+ self.initPackage(pyfile)
+
+ # Request package
+ self.requestPackage()
+
+ # Check for online
+ if not self.isOnline():
+ self.offline()
+
+ # Check for protection
+ if self.isPasswordProtected():
+ self.unlockPasswordProtection()
+ self.handleErrors()
+
+ if self.isCaptchaProtected():
+ self.captcha = True
+ self.unlockCaptchaProtection()
+ self.handleErrors()
+
+ # Get package name and folder
+ (package_name, folder_name) = self.getPackageInfo()
+
+ # Extract package links
+ package_links = []
+ for sources in self.PREFERRED_LINK_SOURCES:
+ package_links.extend(self.handleLinkSource(sources))
+ if package_links: # use only first source which provides links
+ break
+ package_links = set(package_links)
+
+ # Pack
+ if package_links:
+ self.packages = [(package_name, package_links, folder_name)]
+
+
+ def initPackage(self, pyfile):
+ self.fileid = re.match(self.__pattern__, pyfile.url).group('ID')
+ self.package = pyfile.package()
+
+
+ def requestPackage(self):
+ self.html = self.load(self.pyfile.url, decode=True)
+
+
+ def isOnline(self):
+ if self.OFFLINE_TOKEN in self.html:
+ self.logDebug("File not found")
+ return False
+ return True
+
+
+ def isPasswordProtected(self):
+ if self.PASSWORD_TOKEN in self.html:
+ self.logDebug("Links are password protected")
+ return True
+
+
+ def isCaptchaProtected(self):
+ if self.CAPTCHA_TOKEN in self.html:
+ self.logDebug("Links are captcha protected")
+ return True
+ return False
+
+
+ def unlockPasswordProtection(self):
+ password = self.getPassword()
+
+ self.logDebug("Submitting password [%s] for protected links" % password)
+
+ if password:
+ passwd_url = self.PASSWORD_SUBMIT_URL + "?id=%s" % self.fileid
+ passwd_data = {'id': self.fileid, 'password': password, 'pw': 'submit'}
+ self.html = self.load(passwd_url, post=passwd_data, decode=True)
+
+
+ def unlockCaptchaProtection(self):
+ self.logDebug("Request user positional captcha resolving")
+ captcha_img_url = self.CAPTCHA_IMG_URL + "?id=%s" % self.fileid
+ coords = self.decryptCaptcha(captcha_img_url, forceUser=True, imgtype="png", result_type='positional')
+ self.logDebug("Captcha resolved, coords [%s]" % str(coords))
+ captcha_post_url = self.CAPTCHA_SUBMIT_URL + "?id=%s" % self.fileid
+ captcha_post_data = {'button.x': coords[0], 'button.y': coords[1], 'captcha': 'submit'}
+ self.html = self.load(captcha_post_url, post=captcha_post_data, decode=True)
+
+
+ def getPackageInfo(self):
+ name = folder = None
+
+ # Try to get info from web
+ m = re.search(self.FILE_TITLE_REGEX, self.html)
+ if m is not None:
+ title = m.group(1).strip()
+ if not self.FILE_NOTITLE in title:
+ name = folder = title
+ self.logDebug("Found name [%s] and folder [%s] in package info" % (name, folder))
+
+ # Fallback to defaults
+ if not name or not folder:
+ name = self.package.name
+ folder = self.package.folder
+ self.logDebug("Package info not found, defaulting to pyfile name [%s] and folder [%s]" % (name, folder))
+
+ # Return package info
+ return name, folder
+
+
+ def handleErrors(self):
+ if self.PASSWORD_ERROR_ROKEN in self.html:
+ msg = "Incorrect password, please set right password on 'Edit package' form and retry"
+ self.logDebug(msg)
+ self.fail(_(msg))
+
+ if self.captcha:
+ if self.CAPTCHA_ERROR_ROKEN in self.html:
+ self.invalidCaptcha()
+ self.retry()
+ else:
+ self.correctCaptcha()
+
+
+ def handleLinkSource(self, source):
+ if source == 'cnl2':
+ return self.handleCNL2Links()
+ elif source == 'dlc':
+ return self.handleDLCLinks()
+ elif source == 'web':
+ return self.handleWEBLinks()
+ else:
+ self.error(_('Unknown source type "%s"') % source)
+
+
+ def handleCNL2Links(self):
+ self.logDebug("Search for CNL2 links")
+ package_links = []
+ m = re.search(self.CNL2_FORM_REGEX, self.html, re.S)
+ if m is not None:
+ cnl2_form = m.group(1)
+ try:
+ (vcrypted, vjk) = self._getCipherParams(cnl2_form)
+ for (crypted, jk) in zip(vcrypted, vjk):
+ package_links.extend(self._getLinks(crypted, jk))
+ except Exception:
+ self.logDebug("Unable to decrypt CNL2 links")
+ return package_links
+
+
+ def handleDLCLinks(self):
+ self.logDebug("Search for DLC links")
+ package_links = []
+ m = re.search(self.DLC_LINK_REGEX, self.html)
+ if m is not None:
+ container_url = self.DLC_DOWNLOAD_URL + "?id=%s&dlc=1" % self.fileid
+ self.logDebug("Downloading DLC container link [%s]" % container_url)
+ try:
+ dlc = self.load(container_url)
+ dlc_filename = self.fileid + ".dlc"
+ dlc_filepath = safe_join(self.config['general']['download_folder'], dlc_filename)
+ with open(dlc_filepath, "wb") as f:
+ f.write(dlc)
+ package_links.append(dlc_filepath)
+
+ except Exception:
+ self.fail(_("Unable to download DLC container"))
+
+ return package_links
+
+
+ def handleWEBLinks(self):
+ self.logDebug("Search for WEB links")
+
+ package_links = []
+ params = re.findall(self.WEB_FORWARD_REGEX, self.html)
+
+ self.logDebug("Decrypting %d Web links" % len(params))
+
+ for index, param in enumerate(params):
+ try:
+ url = self.WEB_FORWARD_URL + "?%s" % param
+
+ self.logDebug("Decrypting Web link %d, %s" % (index + 1, url))
+
+ res = self.load(url, decode=True)
+ link = re.search(self.WEB_LINK_REGEX, res).group(1)
+
+ package_links.append(link)
+
+ except Exception, detail:
+ self.logDebug("Error decrypting Web link %s, %s" % (index, detail))
+
+ self.setWait(4)
+ self.wait()
+
+ return package_links
+
+
+ def _getCipherParams(self, cnl2_form):
+ # Get jk
+ jk_re = self.CNL2_FORMINPUT_REGEX % self.CNL2_JK_KEY
+ vjk = re.findall(jk_re, cnl2_form, re.I)
+
+ # Get crypted
+ crypted_re = self.CNL2_FORMINPUT_REGEX % RelinkUs.CNL2_CRYPTED_KEY
+ vcrypted = re.findall(crypted_re, cnl2_form, re.I)
+
+ # Log and return
+ self.logDebug("Detected %d crypted blocks" % len(vcrypted))
+ return vcrypted, vjk
+
+
+ def _getLinks(self, crypted, jk):
+ # Get key
+ jreturn = self.js.eval("%s f()" % jk)
+ self.logDebug("JsEngine returns value [%s]" % jreturn)
+ key = binascii.unhexlify(jreturn)
+
+ # Decrypt
+ Key = key
+ IV = key
+ obj = AES.new(Key, AES.MODE_CBC, IV)
+ text = obj.decrypt(crypted.decode('base64'))
+
+ # Extract links
+ text = text.replace("\x00", "").replace("\r", "")
+ links = filter(bool, text.split('\n'))
+
+ # Log and return
+ self.logDebug("Package has %d links" % len(links))
+ return links
diff --git a/module/plugins/crypter/SafelinkingNet.py b/pyload/plugin/crypter/SafelinkingNet.py
index 2d5d273ed..2d5d273ed 100644
--- a/module/plugins/crypter/SafelinkingNet.py
+++ b/pyload/plugin/crypter/SafelinkingNet.py
diff --git a/pyload/plugin/crypter/SecuredIn.py b/pyload/plugin/crypter/SecuredIn.py
new file mode 100644
index 000000000..b0b8eb6d3
--- /dev/null
+++ b/pyload/plugin/crypter/SecuredIn.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class SecuredIn(DeadCrypter):
+ __name__ = "SecuredIn"
+ __type__ = "crypter"
+ __version__ = "0.21"
+
+ __pattern__ = r'http://(?:www\.)?secured\.in/download-[\d]+-\w{8}\.html'
+ __config__ = []
+
+ __description__ = """Secured.in decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("mkaay", "mkaay@mkaay.de")]
diff --git a/module/plugins/crypter/SexuriaCom.py b/pyload/plugin/crypter/SexuriaCom.py
index 10101cd7a..10101cd7a 100644
--- a/module/plugins/crypter/SexuriaCom.py
+++ b/pyload/plugin/crypter/SexuriaCom.py
diff --git a/module/plugins/crypter/ShareLinksBiz.py b/pyload/plugin/crypter/ShareLinksBiz.py
index 1328e86aa..1328e86aa 100644
--- a/module/plugins/crypter/ShareLinksBiz.py
+++ b/pyload/plugin/crypter/ShareLinksBiz.py
diff --git a/pyload/plugin/crypter/SharingmatrixCom.py b/pyload/plugin/crypter/SharingmatrixCom.py
new file mode 100644
index 000000000..7db09b246
--- /dev/null
+++ b/pyload/plugin/crypter/SharingmatrixCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class SharingmatrixCom(DeadCrypter):
+ __name__ = "SharingmatrixCom"
+ __type__ = "crypter"
+ __version__ = "0.01"
+
+ __pattern__ = r'http://(?:www\.)?sharingmatrix\.com/folder/\w+'
+
+ __description__ = """Sharingmatrix.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/crypter/SpeedLoadOrg.py b/pyload/plugin/crypter/SpeedLoadOrg.py
new file mode 100644
index 000000000..95c8864dc
--- /dev/null
+++ b/pyload/plugin/crypter/SpeedLoadOrg.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class SpeedLoadOrg(DeadCrypter):
+ __name__ = "SpeedLoadOrg"
+ __type__ = "crypter"
+ __version__ = "0.30"
+
+ __pattern__ = r'http://(?:www\.)?speedload\.org/(\d+~f$|folder/\d+/)'
+ __config__ = []
+
+ __description__ = """Speedload decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
diff --git a/pyload/plugin/crypter/StealthTo.py b/pyload/plugin/crypter/StealthTo.py
new file mode 100644
index 000000000..23747be1b
--- /dev/null
+++ b/pyload/plugin/crypter/StealthTo.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class StealthTo(DeadCrypter):
+ __name__ = "StealthTo"
+ __type__ = "crypter"
+ __version__ = "0.20"
+
+ __pattern__ = r'http://(?:www\.)?stealth\.to/folder/.+'
+ __config__ = []
+
+ __description__ = """Stealth.to decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("spoob", "spoob@pyload.org")]
diff --git a/pyload/plugin/crypter/TnyCz.py b/pyload/plugin/crypter/TnyCz.py
new file mode 100644
index 000000000..d73f6de63
--- /dev/null
+++ b/pyload/plugin/crypter/TnyCz.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+import re
+
+
+class TnyCz(SimpleCrypter):
+ __name__ = "TnyCz"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?tny\.cz/\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Tny.cz decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ NAME_PATTERN = r'<title>(?P<N>.+) - .+</title>'
+
+
+ def getLinks(self):
+ m = re.search(r'<a id=\'save_paste\' href="(.+save\.php\?hash=.+)">', self.html)
+ return re.findall(".+", self.load(m.group(1), decode=True)) if m else None
diff --git a/pyload/plugin/crypter/TrailerzoneInfo.py b/pyload/plugin/crypter/TrailerzoneInfo.py
new file mode 100644
index 000000000..06894054b
--- /dev/null
+++ b/pyload/plugin/crypter/TrailerzoneInfo.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class TrailerzoneInfo(DeadCrypter):
+ __name__ = "TrailerzoneInfo"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?trailerzone\.info/.+'
+ __config__ = []
+
+ __description__ = """TrailerZone.info decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("godofdream", "soilfiction@gmail.com")]
diff --git a/pyload/plugin/crypter/TurbobitNet.py b/pyload/plugin/crypter/TurbobitNet.py
new file mode 100644
index 000000000..d6b6d7b38
--- /dev/null
+++ b/pyload/plugin/crypter/TurbobitNet.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+from pyload.utils import json_loads
+
+
+class TurbobitNet(SimpleCrypter):
+ __name__ = "TurbobitNet"
+ __type__ = "crypter"
+ __version__ = "0.05"
+
+ __pattern__ = r'http://(?:www\.)?turbobit\.net/download/folder/(?P<ID>\w+)'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Turbobit.net folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ NAME_PATTERN = r'src=\'/js/lib/grid/icon/folder.png\'> <span>(?P<N>.+?)</span>'
+
+
+ def _getLinks(self, id, page=1):
+ gridFile = self.load("http://turbobit.net/downloadfolder/gridFile",
+ get={"rootId": id, "rows": 200, "page": page}, decode=True)
+ grid = json_loads(gridFile)
+
+ if grid['rows']:
+ for i in grid['rows']:
+ yield i['id']
+ for id in self._getLinks(id, page + 1):
+ yield id
+ else:
+ return
+
+
+ def getLinks(self):
+ id = re.match(self.__pattern__, self.pyfile.url).group('ID')
+ fixurl = lambda id: "http://turbobit.net/%s.html" % id
+ return map(fixurl, self._getLinks(id))
diff --git a/pyload/plugin/crypter/TusfilesNet.py b/pyload/plugin/crypter/TusfilesNet.py
new file mode 100644
index 000000000..39d5dee9d
--- /dev/null
+++ b/pyload/plugin/crypter/TusfilesNet.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+
+import math
+import re
+from urlparse import urljoin
+
+from pyload.plugin.internal.XFSCrypter import XFSCrypter
+
+
+class TusfilesNet(XFSCrypter):
+ __name__ = "TusfilesNet"
+ __type__ = "crypter"
+ __version__ = "0.08"
+
+ __pattern__ = r'https?://(?:www\.)?tusfiles\.net/go/(?P<ID>\w+)'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Tusfiles.net folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com"),
+ ("stickell", "l.stickell@yahoo.it")]
+
+
+ PAGES_PATTERN = r'>\((\d+) \w+\)<'
+
+ URL_REPLACEMENTS = [(__pattern__ + ".*", r'https://www.tusfiles.net/go/\g<ID>/')]
+
+
+ def loadPage(self, page_n):
+ return self.load(urljoin(self.pyfile.url, str(page_n)), decode=True)
+
+
+ def handlePages(self, pyfile):
+ pages = re.search(self.PAGES_PATTERN, self.html)
+ if pages:
+ pages = int(math.ceil(int(pages.group('pages')) / 25.0))
+ else:
+ return
+
+ for p in xrange(2, pages + 1):
+ self.html = self.loadPage(p)
+ self.links += self.getLinks()
diff --git a/module/plugins/crypter/UlozTo.py b/pyload/plugin/crypter/UlozTo.py
index 81fbee172..81fbee172 100644
--- a/module/plugins/crypter/UlozTo.py
+++ b/pyload/plugin/crypter/UlozTo.py
diff --git a/pyload/plugin/crypter/UploadableCh.py b/pyload/plugin/crypter/UploadableCh.py
new file mode 100644
index 000000000..f5fb0c3bc
--- /dev/null
+++ b/pyload/plugin/crypter/UploadableCh.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class UploadableCh(SimpleCrypter):
+ __name__ = "UploadableCh"
+ __type__ = "crypter"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?uploadable\.ch/list/\w+'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Uploadable.ch folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("guidobelix", "guidobelix@hotmail.it"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ LINK_PATTERN = r'"(.+?)" class="icon_zipfile">'
+ NAME_PATTERN = r'<div class="folder"><span>&nbsp;</span>(?P<N>.+?)</div>'
+ OFFLINE_PATTERN = r'We are sorry... The URL you entered cannot be found on the server.'
+ TEMP_OFFLINE_PATTERN = r'<div class="icon_err">'
diff --git a/pyload/plugin/crypter/UploadedTo.py b/pyload/plugin/crypter/UploadedTo.py
new file mode 100644
index 000000000..282f82be7
--- /dev/null
+++ b/pyload/plugin/crypter/UploadedTo.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urlparse import urljoin
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class UploadedTo(SimpleCrypter):
+ __name__ = "UploadedTo"
+ __type__ = "crypter"
+ __version__ = "0.42"
+
+ __pattern__ = r'http://(?:www\.)?(uploaded|ul)\.(to|net)/(f|folder|list)/(?P<ID>\w+)'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """UploadedTo decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ PLAIN_PATTERN = r'<small class="date"><a href="([\w/]+)" onclick='
+ NAME_PATTERN = r'<title>(?P<N>.+?)<'
+
+
+ def getLinks(self):
+ m = re.search(self.PLAIN_PATTERN, self.html)
+ if m is None:
+ self.error(_("PLAIN_PATTERN not found"))
+
+ plain_link = urljoin("http://uploaded.net/", m.group(1))
+ return self.load(plain_link).split('\n')[:-1]
diff --git a/pyload/plugin/crypter/WiiReloadedOrg.py b/pyload/plugin/crypter/WiiReloadedOrg.py
new file mode 100644
index 000000000..4190cb340
--- /dev/null
+++ b/pyload/plugin/crypter/WiiReloadedOrg.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class WiiReloadedOrg(DeadCrypter):
+ __name__ = "WiiReloadedOrg"
+ __type__ = "crypter"
+ __version__ = "0.11"
+
+ __pattern__ = r'http://(?:www\.)?wii-reloaded\.org/protect/get\.php\?i=.+'
+ __config__ = []
+
+ __description__ = """Wii-Reloaded.org decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("hzpz", "")]
diff --git a/pyload/plugin/crypter/WuploadCom.py b/pyload/plugin/crypter/WuploadCom.py
new file mode 100644
index 000000000..fb00cb136
--- /dev/null
+++ b/pyload/plugin/crypter/WuploadCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadCrypter import DeadCrypter
+
+
+class WuploadCom(DeadCrypter):
+ __name__ = "WuploadCom"
+ __type__ = "crypter"
+ __version__ = "0.01"
+
+ __pattern__ = r'http://(?:www\.)?wupload\.com/folder/\w+'
+
+ __description__ = """Wupload.com folder decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/crypter/XFileSharingPro.py b/pyload/plugin/crypter/XFileSharingPro.py
new file mode 100644
index 000000000..3dc2e8f70
--- /dev/null
+++ b/pyload/plugin/crypter/XFileSharingPro.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.XFSCrypter import XFSCrypter
+
+
+class XFileSharingPro(XFSCrypter):
+ __name__ = "XFileSharingPro"
+ __type__ = "crypter"
+ __version__ = "0.04"
+
+ __pattern__ = r'^unmatchable$'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """XFileSharingPro dummy folder decrypter plugin for hook"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ def _log(self, type, args):
+ msg = " | ".join(str(a).strip() for a in args if a)
+ logger = getattr(self.log, type)
+ logger("%s: %s: %s" % (self.__name__, self.HOSTER_NAME, msg or _("%s MARK" % type.upper())))
+
+
+ def init(self):
+ super(XFileSharingPro, self).init()
+
+ self.__pattern__ = self.core.pluginManager.crypterPlugins[self.__name__]['pattern']
+
+ self.HOSTER_DOMAIN = re.match(self.__pattern__, self.pyfile.url).group("DOMAIN").lower()
+ self.HOSTER_NAME = "".join(part.capitalize() for part in re.split(r'(\.|\d+)', self.HOSTER_DOMAIN) if part != '.')
+
+ if self.HOSTER_NAME[0].isdigit():
+ self.HOSTER_NAME = 'X' + self.HOSTER_NAME
+
+ account = self.core.accountManager.getAccountPlugin(self.HOSTER_NAME)
+
+ if account and account.canUse():
+ self.account = account
+
+ elif self.account:
+ self.account.HOSTER_DOMAIN = self.HOSTER_DOMAIN
+
+ else:
+ return
+
+ self.user, data = self.account.selectAccount()
+ self.req = self.account.getAccountRequest(self.user)
+ self.premium = self.account.isPremium(self.user)
diff --git a/module/plugins/crypter/XupPl.py b/pyload/plugin/crypter/XupPl.py
index 9d4d27b61..9d4d27b61 100644
--- a/module/plugins/crypter/XupPl.py
+++ b/pyload/plugin/crypter/XupPl.py
diff --git a/module/plugins/crypter/YoutubeBatch.py b/pyload/plugin/crypter/YoutubeBatch.py
index 5e4269fd2..5e4269fd2 100644
--- a/module/plugins/crypter/YoutubeBatch.py
+++ b/pyload/plugin/crypter/YoutubeBatch.py
diff --git a/module/plugins/crypter/__init__.py b/pyload/plugin/crypter/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/plugins/crypter/__init__.py
+++ b/pyload/plugin/crypter/__init__.py
diff --git a/pyload/plugin/extractor/SevenZip.py b/pyload/plugin/extractor/SevenZip.py
new file mode 100644
index 000000000..4b23c6ff2
--- /dev/null
+++ b/pyload/plugin/extractor/SevenZip.py
@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*-
+
+import os
+import re
+
+from subprocess import Popen, PIPE
+
+from pyload.plugin.internal.UnRar import ArchiveError, CRCError, PasswordError, UnRar, renice
+from pyload.utils import fs_encode, safe_join
+
+
+class SevenZip(UnRar):
+ __name__ = "SevenZip"
+ __version__ = "0.08"
+
+ __description__ = """7-Zip extractor plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Michael Nowak", ""),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ CMD = "7z"
+ VERSION = ""
+
+ EXTENSIONS = [".7z", ".xz", ".zip", ".gz", ".gzip", ".tgz", ".bz2", ".bzip2",
+ ".tbz2", ".tbz", ".tar", ".wim", ".swm", ".lzma", ".rar", ".cab",
+ ".arj", ".z", ".taz", ".cpio", ".rpm", ".deb", ".lzh", ".lha",
+ ".chm", ".chw", ".hxs", ".iso", ".msi", ".doc", ".xls", ".ppt",
+ ".dmg", ".xar", ".hfs", ".exe", ".ntfs", ".fat", ".vhd", ".mbr",
+ ".squashfs", ".cramfs", ".scap"]
+
+
+ #@NOTE: there are some more uncovered 7z formats
+ re_filelist = re.compile(r'([\d\:]+)\s+([\d\:]+)\s+([\w\.]+)\s+(\d+)\s+(\d+)\s+(.+)')
+ re_wrongpwd = re.compile(r'(Can not open encrypted archive|Wrong password)', re.I)
+ re_wrongcrc = re.compile(r'Encrypted\s+\=\s+\+', re.I)
+ re_version = re.compile(r'7-Zip\s(?:\[64\]\s)?(\d+\.\d+)', re.I)
+
+
+ @classmethod
+ def isUsable(cls):
+ if os.name == "nt":
+ cls.CMD = os.path.join(pypath, "7z.exe")
+ p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE)
+ out,err = p.communicate()
+ else:
+ p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE)
+ out, err = p.communicate()
+
+ cls.VERSION = cls.re_version.search(out).group(1)
+
+ return True
+
+
+ def check(self):
+ file = fs_encode(self.filename)
+
+ p = self.call_cmd("t", file)
+ out, err = p.communicate()
+
+ if p.returncode > 1:
+ raise CRCError(err)
+
+ p = self.call_cmd("l", "-slt", file)
+ out, err = p.communicate()
+
+ if p.returncode > 1:
+ raise ArchiveError(_("Process return code: %d") % p.returncode)
+
+ # check if output or error macthes the 'wrong password'-Regexp
+ if self.re_wrongpwd.search(out):
+ raise PasswordError
+
+ # check if output matches 'Encrypted = +'
+ if self.re_wrongcrc.search(out):
+ raise CRCError(_("Header protected"))
+
+
+ def isPassword(self, password):
+ p = self.call_cmd("l", fs_encode(self.filename), password=password)
+ p.communicate()
+ return p.returncode == 0
+
+
+ def repair(self):
+ return False
+
+
+ def extract(self, password=None):
+ command = "x" if self.fullpath else "e"
+
+ p = self.call_cmd(command, '-o' + self.out, fs_encode(self.filename), password=password)
+
+ renice(p.pid, self.renice)
+
+ # communicate and retrieve stderr
+ self._progress(p)
+ err = p.stderr.read().strip()
+
+ if err:
+ if self.re_wrongpwd.search(err):
+ raise PasswordError
+
+ elif self.re_wrongcrc.search(err):
+ raise CRCError(err)
+
+ else: #: raise error if anything is on stderr
+ raise ArchiveError(err)
+
+ if p.returncode > 1:
+ raise ArchiveError(_("Process return code: %d") % p.returncode)
+
+ self.files = self.list(password)
+
+
+ def list(self, password=None):
+ command = "l" if self.fullpath else "l"
+
+ p = self.call_cmd(command, fs_encode(self.filename), password=password)
+ out, err = p.communicate()
+
+ if "Can not open" in err:
+ raise ArchiveError(_("Cannot open file"))
+
+ if p.returncode > 1:
+ raise ArchiveError(_("Process return code: %d") % p.returncode)
+
+ result = set()
+ for groups in self.re_filelist.findall(out):
+ f = groups[-1].strip()
+ result.add(safe_join(self.out, f))
+
+ return list(result)
+
+
+ def call_cmd(self, command, *xargs, **kwargs):
+ args = []
+
+ #overwrite flag
+ if self.overwrite:
+ args.append("-y")
+
+ #set a password
+ if "password" in kwargs and kwargs["password"]:
+ args.append("-p'%s'" % kwargs["password"])
+ else:
+ args.append("-p-")
+
+ #@NOTE: return codes are not reliable, some kind of threading, cleanup whatever issue
+ call = [self.CMD, command] + args + list(xargs)
+
+ self.manager.logDebug(" ".join(call))
+
+ p = Popen(call, stdout=PIPE, stderr=PIPE)
+ return p
diff --git a/pyload/plugin/extractor/UnRar.py b/pyload/plugin/extractor/UnRar.py
new file mode 100644
index 000000000..8a3985678
--- /dev/null
+++ b/pyload/plugin/extractor/UnRar.py
@@ -0,0 +1,248 @@
+# -*- coding: utf-8 -*-
+
+import os
+import re
+
+from glob import glob
+from string import digits
+from subprocess import Popen, PIPE
+
+from pyload.plugin.internal.Extractor import Extractor, ArchiveError, CRCError, PasswordError
+from pyload.utils import decode, fs_encode, safe_join
+
+
+def renice(pid, value):
+ if value and os.name != "nt":
+ try:
+ Popen(["renice", str(value), str(pid)], stdout=PIPE, stderr=PIPE, bufsize=-1)
+
+ except Exception:
+ pass
+
+
+class UnRar(Extractor):
+ __name__ = "UnRar"
+ __version__ = "1.13"
+
+ __description__ = """Rar extractor plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("Walter Purcaro", "vuolter@gmail.com"),
+ ("Immenz", "immenz@gmx.net"),]
+
+
+ CMD = "unrar"
+ VERSION = ""
+
+ EXTENSIONS = [".rar"]
+
+
+ re_multipart = re.compile(r'\.(part|r)(\d+)(?:\.rar)?',re.I)
+
+ re_filefixed = re.compile(r'Building (.+)')
+ re_filelist = re.compile(r'^(.)(\s*[\w\.\-]+)\s+(\d+\s+)+(?:\d+\%\s+)?[\d\-]{8}\s+[\d\:]{5}', re.M|re.I)
+
+ re_wrongpwd = re.compile(r'password', re.I)
+ re_wrongcrc = re.compile(r'encrypted|damaged|CRC failed|checksum error', re.I)
+
+ re_version = re.compile(r'UNRAR\s(\d+\.\d+)', re.I)
+
+
+ @classmethod
+ def isUsable(cls):
+ if os.name == "nt":
+ cls.CMD = os.path.join(pypath, "UnRAR.exe")
+ p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE)
+ out, err = p.communicate()
+ else:
+ try:
+ p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE)
+ out, err = p.communicate()
+
+ except OSError: #: fallback to rar
+ cls.CMD = "rar"
+ p = Popen([cls.CMD], stdout=PIPE, stderr=PIPE)
+ out, err = p.communicate()
+
+ cls.VERSION = cls.re_version.search(out).group(1)
+
+ return True
+
+
+ @classmethod
+ def isMultipart(cls,filename):
+ multipart = cls.re_multipart.search(filename)
+ if multipart:
+ # First Multipart file (part1.rar for *.part1-9.rar format or *.rar for .r1-9 format) handled as normal Archive
+ return False if (multipart.group(1) == "part" and int(multipart.group(2)) == 1) else True
+
+ return False
+
+
+ def check(self):
+ p = self.call_cmd("l", "-v", fs_encode(self.filename))
+ out, err = p.communicate()
+
+ if self.re_wrongpwd.search(err):
+ raise PasswordError
+
+ if self.re_wrongcrc.search(err):
+ raise CRCError(err)
+
+ # output only used to check if passworded files are present
+ for attr in self.re_filelist.findall(out):
+ if attr[0].startswith("*"):
+ raise PasswordError
+
+
+ def isPassword(self, password):
+ # at this point we can only verify header protected files
+ p = self.call_cmd("l", "-v", fs_encode(self.filename), password=password)
+ out, err = p.communicate()
+ return False if self.re_wrongpwd.search(err) else True
+
+
+ def repair(self):
+ p = self.call_cmd("rc", fs_encode(self.filename))
+
+ # communicate and retrieve stderr
+ self._progress(p)
+ err = p.stderr.read().strip()
+
+ if err or p.returncode:
+ p = self.call_cmd("r", fs_encode(self.filename))
+
+ # communicate and retrieve stderr
+ self._progress(p)
+ err = p.stderr.read().strip()
+
+ if err or p.returncode:
+ return False
+ else:
+ dir = os.path.dirname(filename)
+ name = re_filefixed.search(out).group(1)
+
+ self.filename = os.path.join(dir, name)
+
+ return True
+
+
+ def _progress(self, process):
+ s = ""
+ while True:
+ c = process.stdout.read(1)
+ # quit loop on eof
+ if not c:
+ break
+ # reading a percentage sign -> set progress and restart
+ if c == '%':
+ self.notifyProgress(int(s))
+ s = ""
+ # not reading a digit -> therefore restart
+ elif c not in digits:
+ s = ""
+ # add digit to progressstring
+ else:
+ s += c
+
+
+ def extract(self, password=None):
+ command = "x" if self.fullpath else "e"
+
+ p = self.call_cmd(command, fs_encode(self.filename), self.out, password=password)
+
+ renice(p.pid, self.renice)
+
+ # communicate and retrieve stderr
+ self._progress(p)
+ err = p.stderr.read().strip()
+
+ if err:
+ if self.re_wrongpwd.search(err):
+ raise PasswordError
+
+ elif self.re_wrongcrc.search(err):
+ raise CRCError(err)
+
+ else: #: raise error if anything is on stderr
+ raise ArchiveError(err)
+
+ if p.returncode:
+ raise ArchiveError(_("Process return code: %d") % p.returncode)
+
+ self.files = self.list(password)
+
+
+ def getDeleteFiles(self):
+ dir, name = os.path.split(self.filename)
+
+ # actually extracted file
+ files = [self.filename]
+
+ # eventually Multipart Files
+ files.extend(safe_join(dir, os.path.basename(file)) for file in filter(self.isMultipart, os.listdir(dir))
+ if re.sub(self.re_multipart,".rar",name) == re.sub(self.re_multipart,".rar",file))
+
+ return files
+
+
+ def list(self, password=None):
+ command = "vb" if self.fullpath else "lb"
+
+ p = self.call_cmd(command, "-v", fs_encode(self.filename), password=password)
+ out, err = p.communicate()
+
+ if "Cannot open" in err:
+ raise ArchiveError(_("Cannot open file"))
+
+ if err.strip(): #: only log error at this point
+ self.manager.logError(err.strip())
+
+ result = set()
+ if not self.fullpath and self.VERSION.startswith('5'):
+ # NOTE: Unrar 5 always list full path
+ for f in decode(out).splitlines():
+ f = safe_join(self.out, os.path.basename(f.strip()))
+ if os.path.isfile(f):
+ result.add(safe_join(self.out, os.path.basename(f)))
+ else:
+ for f in decode(out).splitlines():
+ f = f.strip()
+ result.add(safe_join(self.out, f))
+
+ return list(result)
+
+
+ def call_cmd(self, command, *xargs, **kwargs):
+ args = []
+
+ # overwrite flag
+ if self.overwrite:
+ args.append("-o+")
+ else:
+ args.append("-o-")
+ if self.delete:
+ args.append("-or")
+
+ for word in self.excludefiles:
+ args.append("-x'%s'" % word.strip())
+
+ # assume yes on all queries
+ args.append("-y")
+
+ # set a password
+ if "password" in kwargs and kwargs['password']:
+ args.append("-p%s" % kwargs['password'])
+ else:
+ args.append("-p-")
+
+ if self.keepbroken:
+ args.append("-kb")
+
+ # NOTE: return codes are not reliable, some kind of threading, cleanup whatever issue
+ call = [self.CMD, command] + args + list(xargs)
+
+ self.manager.logDebug(" ".join(call))
+
+ p = Popen(call, stdout=PIPE, stderr=PIPE)
+ return p
diff --git a/pyload/plugin/extractor/UnZip.py b/pyload/plugin/extractor/UnZip.py
new file mode 100644
index 000000000..cb6621f99
--- /dev/null
+++ b/pyload/plugin/extractor/UnZip.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import os
+import sys
+import zipfile
+
+from pyload.plugin.internal.Extractor import Extractor, ArchiveError, CRCError, PasswordError
+from pyload.utils import fs_encode
+
+
+class UnZip(Extractor):
+ __name__ = "UnZip"
+ __version__ = "1.10"
+
+ __description__ = """Zip extractor plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ EXTENSIONS = [".zip", ".zip64"]
+ VERSION ="(python %s.%s.%s)" % (sys.version_info[0], sys.version_info[1], sys.version_info[2])
+
+
+ @classmethod
+ def isUsable(cls):
+ return sys.version_info[:2] >= (2, 6)
+
+
+ def list(self, password=None):
+ with zipfile.ZipFile(fs_encode(self.filename), 'r', allowZip64=True) as z:
+ z.setpassword(password)
+ return z.namelist()
+
+
+ def check(self):
+ with zipfile.ZipFile(fs_encode(self.filename), 'r', allowZip64=True) as z:
+ badfile = z.testzip()
+
+ if badfile:
+ raise CRCError(badfile)
+ else:
+ raise PasswordError
+
+
+ def extract(self, password=None):
+ try:
+ with zipfile.ZipFile(fs_encode(self.filename), 'r', allowZip64=True) as z:
+ z.setpassword(password)
+
+ badfile = z.testzip()
+
+ if badfile:
+ raise CRCError(badfile)
+ else:
+ z.extractall(self.out)
+
+ except (zipfile.BadZipfile, zipfile.LargeZipFile), e:
+ raise ArchiveError(e)
+
+ except RuntimeError, e:
+ if "encrypted" in e:
+ raise PasswordError
+ else:
+ raise ArchiveError(e)
+ else:
+ self.files = z.namelist()
diff --git a/module/plugins/hooks/__init__.py b/pyload/plugin/extractor/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/plugins/hooks/__init__.py
+++ b/pyload/plugin/extractor/__init__.py
diff --git a/pyload/plugin/hook/AlldebridCom.py b/pyload/plugin/hook/AlldebridCom.py
new file mode 100644
index 000000000..6d3e5db48
--- /dev/null
+++ b/pyload/plugin/hook/AlldebridCom.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class AlldebridCom(MultiHook):
+ __name__ = "AlldebridCom"
+ __type__ = "hook"
+ __version__ = "0.16"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 ),
+ ("ssl" , "bool" , "Use HTTPS" , True )]
+
+ __description__ = """Alldebrid.com hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Andy Voigt", "spamsales@online.de")]
+
+
+ def getHosters(self):
+ https = "https" if self.getConfig("ssl") else "http"
+ html = self.getURL(https + "://www.alldebrid.com/api.php", get={'action': "get_host"}).replace("\"", "").strip()
+
+ return [x.strip() for x in html.split(",") if x.strip()]
diff --git a/pyload/plugin/hook/BypassCaptcha.py b/pyload/plugin/hook/BypassCaptcha.py
new file mode 100644
index 000000000..7b7e156bb
--- /dev/null
+++ b/pyload/plugin/hook/BypassCaptcha.py
@@ -0,0 +1,135 @@
+# -*- coding: utf-8 -*-
+
+from pycurl import FORM_FILE, LOW_SPEED_TIME
+
+from pyload.network.HTTPRequest import BadHeader
+from pyload.network.RequestFactory import getURL, getRequest
+from pyload.plugin.Hook import Hook, threaded
+
+
+class BypassCaptchaException(Exception):
+
+ def __init__(self, err):
+ self.err = err
+
+
+ def getCode(self):
+ return self.err
+
+
+ def __str__(self):
+ return "<BypassCaptchaException %s>" % self.err
+
+
+ def __repr__(self):
+ return "<BypassCaptchaException %s>" % self.err
+
+
+class BypassCaptcha(Hook):
+ __name__ = "BypassCaptcha"
+ __type__ = "hook"
+ __version__ = "0.06"
+
+ __config__ = [("force", "bool", "Force BC even if client is connected", False),
+ ("passkey", "password", "Passkey", "")]
+
+ __description__ = """Send captchas to BypassCaptcha.com"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("Godofdream", "soilfcition@gmail.com"),
+ ("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ PYLOAD_KEY = "4f771155b640970d5607f919a615bdefc67e7d32"
+
+ SUBMIT_URL = "http://bypasscaptcha.com/upload.php"
+ RESPOND_URL = "http://bypasscaptcha.com/check_value.php"
+ GETCREDITS_URL = "http://bypasscaptcha.com/ex_left.php"
+
+
+ def getCredits(self):
+ res = getURL(self.GETCREDITS_URL, post={"key": self.getConfig("passkey")})
+
+ data = dict(x.split(' ', 1) for x in res.splitlines())
+ return int(data['Left'])
+
+
+ def submit(self, captcha, captchaType="file", match=None):
+ req = getRequest()
+
+ #raise timeout threshold
+ req.c.setopt(LOW_SPEED_TIME, 80)
+
+ try:
+ res = req.load(self.SUBMIT_URL,
+ post={'vendor_key': self.PYLOAD_KEY,
+ 'key': self.getConfig("passkey"),
+ 'gen_task_id': "1",
+ 'file': (FORM_FILE, captcha)},
+ multipart=True)
+ finally:
+ req.close()
+
+ data = dict(x.split(' ', 1) for x in res.splitlines())
+ if not data or "Value" not in data:
+ raise BypassCaptchaException(res)
+
+ result = data['Value']
+ ticket = data['TaskId']
+ self.logDebug("Result %s : %s" % (ticket, result))
+
+ return ticket, result
+
+
+ def respond(self, ticket, success):
+ try:
+ res = getURL(self.RESPOND_URL, post={"task_id": ticket, "key": self.getConfig("passkey"),
+ "cv": 1 if success else 0})
+ except BadHeader, e:
+ self.logError(_("Could not send response"), e)
+
+
+ def captchaTask(self, task):
+ if "service" in task.data:
+ return False
+
+ if not task.isTextual():
+ return False
+
+ if not self.getConfig("passkey"):
+ return False
+
+ if self.core.isClientConnected() and not self.getConfig("force"):
+ return False
+
+ if self.getCredits() > 0:
+ task.handler.append(self)
+ task.data['service'] = self.__name__
+ task.setWaiting(100)
+ self._processCaptcha(task)
+
+ else:
+ self.logInfo(_("Your %s account has not enough credits") % self.__name__)
+
+
+ def captchaCorrect(self, task):
+ if task.data['service'] == self.__name__ and "ticket" in task.data:
+ self.respond(task.data['ticket'], True)
+
+
+ def captchaInvalid(self, task):
+ if task.data['service'] == self.__name__ and "ticket" in task.data:
+ self.respond(task.data['ticket'], False)
+
+
+ @threaded
+ def _processCaptcha(self, task):
+ c = task.captchaFile
+ try:
+ ticket, result = self.submit(c)
+ except BypassCaptchaException, e:
+ task.error = e.getCode()
+ return
+
+ task.data['ticket'] = ticket
+ task.setResult(result)
diff --git a/pyload/plugin/hook/Captcha9Kw.py b/pyload/plugin/hook/Captcha9Kw.py
new file mode 100644
index 000000000..dd3fb1ba1
--- /dev/null
+++ b/pyload/plugin/hook/Captcha9Kw.py
@@ -0,0 +1,251 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import re
+
+from base64 import b64encode
+from time import sleep
+
+from pyload.network.HTTPRequest import BadHeader
+from pyload.network.RequestFactory import getURL
+
+from pyload.plugin.Hook import Hook, threaded
+
+
+class Captcha9kw(Hook):
+ __name__ = "Captcha9Kw"
+ __type__ = "hook"
+ __version__ = "0.28"
+
+ __config__ = [("ssl" , "bool" , "Use HTTPS" , True ),
+ ("force" , "bool" , "Force captcha resolving even if client is connected" , True ),
+ ("confirm" , "bool" , "Confirm Captcha (cost +6 credits)" , False ),
+ ("captchaperhour", "int" , "Captcha per hour" , "9999" ),
+ ("captchapermin" , "int" , "Captcha per minute" , "9999" ),
+ ("prio" , "int" , "Priority (max 10)(cost +0 -> +10 credits)" , "0" ),
+ ("queue" , "int" , "Max. Queue (max 999)" , "50" ),
+ ("hoster_options", "string" , "Hoster options (format: pluginname:prio=1:selfsolfe=1:confirm=1:timeout=900|...)", "ShareonlineBiz:prio=0:timeout=999 | UploadedTo:prio=0:timeout=999"),
+ ("selfsolve" , "bool" , "Selfsolve (manually solve your captcha in your 9kw client if active)" , "0" ),
+ ("passkey" , "password", "API key" , "" ),
+ ("timeout" , "int" , "Timeout in seconds (min 60, max 3999)" , "900" )]
+
+ __description__ = """Send captchas to 9kw.eu"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ API_URL = "http://www.9kw.eu/index.cgi"
+
+
+ def activate(self):
+ if self.getConfig("ssl"):
+ self.API_URL = self.API_URL.replace("http://", "https://")
+
+
+ def getCredits(self):
+ res = getURL(self.API_URL,
+ get={'apikey': self.getConfig("passkey"),
+ 'pyload': "1",
+ 'source': "pyload",
+ 'action': "usercaptchaguthaben"})
+
+ if res.isdigit():
+ self.logInfo(_("%s credits left") % res)
+ credits = self.info['credits'] = int(res)
+ return credits
+ else:
+ self.logError(res)
+ return 0
+
+
+ @threaded
+ def _processCaptcha(self, task):
+ try:
+ with open(task.captchaFile, 'rb') as f:
+ data = f.read()
+
+ except IOError, e:
+ self.logError(e)
+ return
+
+ pluginname = re.search(r'_([^_]*)_\d+.\w+', task.captchaFile).group(1)
+ option = {'min' : 2,
+ 'max' : 50,
+ 'phrase' : 0,
+ 'numeric' : 0,
+ 'case_sensitive': 0,
+ 'math' : 0,
+ 'prio' : min(max(self.getConfig("prio"), 0), 10),
+ 'confirm' : self.getConfig("confirm"),
+ 'timeout' : min(max(self.getConfig("timeout"), 300), 3999),
+ 'selfsolve' : self.getConfig("selfsolve"),
+ 'cph' : self.getConfig("captchaperhour"),
+ 'cpm' : self.getConfig("captchapermin")}
+
+ for opt in str(self.getConfig("hoster_options").split('|')):
+
+ details = map(str.strip, opt.split(':'))
+
+ if not details or details[0].lower() != pluginname.lower():
+ continue
+
+ for d in details:
+ hosteroption = d.split("=")
+
+ if len(hosteroption) < 2 or not hosteroption[1].isdigit():
+ continue
+
+ o = hosteroption[0].lower()
+ if o in option:
+ option[o] = hosteroption[1]
+
+ break
+
+ post_data = {'apikey' : self.getConfig("passkey"),
+ 'prio' : option['prio'],
+ 'confirm' : option['confirm'],
+ 'maxtimeout' : option['timeout'],
+ 'selfsolve' : option['selfsolve'],
+ 'captchaperhour': option['cph'],
+ 'captchapermin' : option['cpm'],
+ 'case-sensitive': option['case_sensitive'],
+ 'min_len' : option['min'],
+ 'max_len' : option['max'],
+ 'phrase' : option['phrase'],
+ 'numeric' : option['numeric'],
+ 'math' : option['math'],
+ 'oldsource' : pluginname,
+ 'pyload' : "1",
+ 'source' : "pyload",
+ 'base64' : "1",
+ 'mouse' : 1 if task.isPositional() else 0,
+ 'file-upload-01': b64encode(data),
+ 'action' : "usercaptchaupload"}
+
+ for _i in xrange(5):
+ try:
+ res = getURL(self.API_URL, post=post_data)
+ except BadHeader, e:
+ sleep(3)
+ else:
+ if res and res.isdigit():
+ break
+ else:
+ self.logError(_("Bad upload: %s") % res)
+ return
+
+ self.logDebug(_("NewCaptchaID ticket: %s") % res, task.captchaFile)
+
+ task.data["ticket"] = res
+
+ for _i in xrange(int(self.getConfig("timeout") / 5)):
+ result = getURL(self.API_URL,
+ get={'apikey': self.getConfig("passkey"),
+ 'id' : res,
+ 'pyload': "1",
+ 'info' : "1",
+ 'source': "pyload",
+ 'action': "usercaptchacorrectdata"})
+
+ if not result or result == "NO DATA":
+ sleep(5)
+ else:
+ break
+ else:
+ self.logDebug("Could not send request: %s" % res)
+ result = None
+
+ self.logInfo(_("Captcha result for ticket %s: %s") % (res, result))
+
+ task.setResult(result)
+
+
+ def captchaTask(self, task):
+ if not task.isTextual() and not task.isPositional():
+ return
+
+ if not self.getConfig("passkey"):
+ return
+
+ if self.core.isClientConnected() and not self.getConfig("force"):
+ return
+
+ credits = self.getCredits()
+
+ if not credits:
+ self.logError(_("Your captcha 9kw.eu account has not enough credits"))
+ return
+
+ queue = min(self.getConfig("queue"), 999)
+ timeout = min(max(self.getConfig("timeout"), 300), 3999)
+ pluginname = re.search(r'_([^_]*)_\d+.\w+', task.captchaFile).group(1)
+
+ for _i in xrange(5):
+ servercheck = getURL("http://www.9kw.eu/grafik/servercheck.txt")
+ if queue < re.search(r'queue=(\d+)', servercheck).group(1):
+ break
+
+ sleep(10)
+ else:
+ self.fail(_("Too many captchas in queue"))
+
+ for opt in str(self.getConfig("hoster_options").split('|')):
+ details = map(str.strip, opt.split(':'))
+
+ if not details or details[0].lower() != pluginname.lower():
+ continue
+
+ for d in details:
+ hosteroption = d.split("=")
+
+ if len(hosteroption) > 1 \
+ and hosteroption[0].lower() == 'timeout' \
+ and hosteroption[1].isdigit():
+ timeout = int(hosteroption[1])
+
+ break
+
+ task.handler.append(self)
+
+ task.setWaiting(timeout)
+
+ self._processCaptcha(task)
+
+
+ def _captchaResponse(self, task, correct):
+ type = "correct" if correct else "refund"
+
+ if 'ticket' not in task.data:
+ self.logDebug("No CaptchaID for %s request (task: %s)" % (type, task))
+ return
+
+ passkey = self.getConfig("passkey")
+
+ for _i in xrange(3):
+ res = getURL(self.API_URL,
+ get={'action' : "usercaptchacorrectback",
+ 'apikey' : passkey,
+ 'api_key': passkey,
+ 'correct': "1" if correct else "2",
+ 'pyload' : "1",
+ 'source' : "pyload",
+ 'id' : task.data["ticket"]})
+
+ self.logDebug("Request %s: %s" % (type, res))
+
+ if res == "OK":
+ break
+
+ sleep(5)
+ else:
+ self.logDebug("Could not send %s request: %s" % (type, res))
+
+
+ def captchaCorrect(self, task):
+ self._captchaResponse(task, True)
+
+
+ def captchaInvalid(self, task):
+ self._captchaResponse(task, False)
diff --git a/pyload/plugin/hook/CaptchaBrotherhood.py b/pyload/plugin/hook/CaptchaBrotherhood.py
new file mode 100644
index 000000000..554d102ec
--- /dev/null
+++ b/pyload/plugin/hook/CaptchaBrotherhood.py
@@ -0,0 +1,167 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import StringIO
+import pycurl
+
+try:
+ from PIL import Image
+except ImportError:
+ import Image
+
+from time import sleep
+from urllib import urlencode
+
+from pyload.network.RequestFactory import getURL, getRequest
+from pyload.plugin.Hook import Hook, threaded
+
+
+class CaptchaBrotherhoodException(Exception):
+
+ def __init__(self, err):
+ self.err = err
+
+
+ def getCode(self):
+ return self.err
+
+
+ def __str__(self):
+ return "<CaptchaBrotherhoodException %s>" % self.err
+
+
+ def __repr__(self):
+ return "<CaptchaBrotherhoodException %s>" % self.err
+
+
+class CaptchaBrotherhood(Hook):
+ __name__ = "CaptchaBrotherhood"
+ __type__ = "hook"
+ __version__ = "0.08"
+
+ __config__ = [("username", "str", "Username", ""),
+ ("force", "bool", "Force CT even if client is connected", False),
+ ("passkey", "password", "Password", "")]
+
+ __description__ = """Send captchas to CaptchaBrotherhood.com"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ API_URL = "http://www.captchabrotherhood.com/"
+
+
+ def getCredits(self):
+ res = getURL(self.API_URL + "askCredits.aspx",
+ get={"username": self.getConfig("username"), "password": self.getConfig("passkey")})
+ if not res.startswith("OK"):
+ raise CaptchaBrotherhoodException(res)
+ else:
+ credits = int(res[3:])
+ self.logInfo(_("%d credits left") % credits)
+ self.info['credits'] = credits
+ return credits
+
+
+ def submit(self, captcha, captchaType="file", match=None):
+ try:
+ img = Image.open(captcha)
+ output = StringIO.StringIO()
+ self.logDebug("CAPTCHA IMAGE", img, img.format, img.mode)
+ if img.format in ("GIF", "JPEG"):
+ img.save(output, img.format)
+ else:
+ if img.mode != "RGB":
+ img = img.convert("RGB")
+ img.save(output, "JPEG")
+ data = output.getvalue()
+ output.close()
+ except Exception, e:
+ raise CaptchaBrotherhoodException("Reading or converting captcha image failed: %s" % e)
+
+ req = getRequest()
+
+ url = "%ssendNewCaptcha.aspx?%s" % (self.API_URL,
+ urlencode({'username' : self.getConfig("username"),
+ 'password' : self.getConfig("passkey"),
+ 'captchaSource': "pyLoad",
+ 'timeout' : "80"}))
+
+ req.c.setopt(pycurl.URL, url)
+ req.c.setopt(pycurl.POST, 1)
+ req.c.setopt(pycurl.POSTFIELDS, data)
+ req.c.setopt(pycurl.HTTPHEADER, ["Content-Type: text/html"])
+
+ try:
+ req.c.perform()
+ res = req.getResponse()
+ except Exception, e:
+ raise CaptchaBrotherhoodException("Submit captcha image failed")
+
+ req.close()
+
+ if not res.startswith("OK"):
+ raise CaptchaBrotherhoodException(res[1])
+
+ ticket = res[3:]
+
+ for _i in xrange(15):
+ sleep(5)
+ res = self.api_response("askCaptchaResult", ticket)
+ if res.startswith("OK-answered"):
+ return ticket, res[12:]
+
+ raise CaptchaBrotherhoodException("No solution received in time")
+
+
+ def api_response(self, api, ticket):
+ res = getURL("%s%s.aspx" % (self.API_URL, api),
+ get={"username": self.getConfig("username"),
+ "password": self.getConfig("passkey"),
+ "captchaID": ticket})
+ if not res.startswith("OK"):
+ raise CaptchaBrotherhoodException("Unknown response: %s" % res)
+
+ return res
+
+
+ def captchaTask(self, task):
+ if "service" in task.data:
+ return False
+
+ if not task.isTextual():
+ return False
+
+ if not self.getConfig("username") or not self.getConfig("passkey"):
+ return False
+
+ if self.core.isClientConnected() and not self.getConfig("force"):
+ return False
+
+ if self.getCredits() > 10:
+ task.handler.append(self)
+ task.data['service'] = self.__name__
+ task.setWaiting(100)
+ self._processCaptcha(task)
+ else:
+ self.logInfo(_("Your CaptchaBrotherhood Account has not enough credits"))
+
+
+ def captchaInvalid(self, task):
+ if task.data['service'] == self.__name__ and "ticket" in task.data:
+ res = self.api_response("complainCaptcha", task.data['ticket'])
+
+
+ @threaded
+ def _processCaptcha(self, task):
+ c = task.captchaFile
+ try:
+ ticket, result = self.submit(c)
+ except CaptchaBrotherhoodException, e:
+ task.error = e.getCode()
+ return
+
+ task.data['ticket'] = ticket
+ task.setResult(result)
diff --git a/pyload/plugin/hook/DeathByCaptcha.py b/pyload/plugin/hook/DeathByCaptcha.py
new file mode 100644
index 000000000..e0108963b
--- /dev/null
+++ b/pyload/plugin/hook/DeathByCaptcha.py
@@ -0,0 +1,214 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import re
+
+from base64 import b64encode
+from pycurl import FORM_FILE, HTTPHEADER
+from time import sleep
+
+from pyload.utils import json_loads
+from pyload.network.HTTPRequest import BadHeader
+from pyload.network.RequestFactory import getRequest
+from pyload.plugin.Hook import Hook, threaded
+
+
+class DeathByCaptchaException(Exception):
+ DBC_ERRORS = {'not-logged-in': 'Access denied, check your credentials',
+ 'invalid-credentials': 'Access denied, check your credentials',
+ 'banned': 'Access denied, account is suspended',
+ 'insufficient-funds': 'Insufficient account balance to decrypt CAPTCHA',
+ 'invalid-captcha': 'CAPTCHA is not a valid image',
+ 'service-overload': 'CAPTCHA was rejected due to service overload, try again later',
+ 'invalid-request': 'Invalid request',
+ 'timed-out': 'No CAPTCHA solution received in time'}
+
+
+ def __init__(self, err):
+ self.err = err
+
+
+ def getCode(self):
+ return self.err
+
+
+ def getDesc(self):
+ if self.err in self.DBC_ERRORS.keys():
+ return self.DBC_ERRORS[self.err]
+ else:
+ return self.err
+
+
+ def __str__(self):
+ return "<DeathByCaptchaException %s>" % self.err
+
+
+ def __repr__(self):
+ return "<DeathByCaptchaException %s>" % self.err
+
+
+class DeathByCaptcha(Hook):
+ __name__ = "DeathByCaptcha"
+ __type__ = "hook"
+ __version__ = "0.06"
+
+ __config__ = [("username", "str", "Username", ""),
+ ("passkey", "password", "Password", ""),
+ ("force", "bool", "Force DBC even if client is connected", False)]
+
+ __description__ = """Send captchas to DeathByCaptcha.com"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ API_URL = "http://api.dbcapi.me/api/"
+
+
+ def api_response(self, api="captcha", post=False, multipart=False):
+ req = getRequest()
+ req.c.setopt(HTTPHEADER, ["Accept: application/json", "User-Agent: pyLoad %s" % self.core.version])
+
+ if post:
+ if not isinstance(post, dict):
+ post = {}
+ post.update({"username": self.getConfig("username"),
+ "password": self.getConfig("passkey")})
+
+ res = None
+ try:
+ json = req.load("%s%s" % (self.API_URL, api),
+ post=post,
+ multipart=multipart)
+ self.logDebug(json)
+ res = json_loads(json)
+
+ if "error" in res:
+ raise DeathByCaptchaException(res['error'])
+ elif "status" not in res:
+ raise DeathByCaptchaException(str(res))
+
+ except BadHeader, e:
+ if 403 == e.code:
+ raise DeathByCaptchaException('not-logged-in')
+ elif 413 == e.code:
+ raise DeathByCaptchaException('invalid-captcha')
+ elif 503 == e.code:
+ raise DeathByCaptchaException('service-overload')
+ elif e.code in (400, 405):
+ raise DeathByCaptchaException('invalid-request')
+ else:
+ raise
+
+ finally:
+ req.close()
+
+ return res
+
+
+ def getCredits(self):
+ res = self.api_response("user", True)
+
+ if 'is_banned' in res and res['is_banned']:
+ raise DeathByCaptchaException('banned')
+ elif 'balance' in res and 'rate' in res:
+ self.info.update(res)
+ else:
+ raise DeathByCaptchaException(res)
+
+
+ def getStatus(self):
+ res = self.api_response("status", False)
+
+ if 'is_service_overloaded' in res and res['is_service_overloaded']:
+ raise DeathByCaptchaException('service-overload')
+
+
+ def submit(self, captcha, captchaType="file", match=None):
+ #@NOTE: Workaround multipart-post bug in HTTPRequest.py
+ if re.match("^\w*$", self.getConfig("passkey")):
+ multipart = True
+ data = (FORM_FILE, captcha)
+ else:
+ multipart = False
+ with open(captcha, 'rb') as f:
+ data = f.read()
+ data = "base64:" + b64encode(data)
+
+ res = self.api_response("captcha", {"captchafile": data}, multipart)
+
+ if "captcha" not in res:
+ raise DeathByCaptchaException(res)
+ ticket = res['captcha']
+
+ for _i in xrange(24):
+ sleep(5)
+ res = self.api_response("captcha/%d" % ticket, False)
+ if res['text'] and res['is_correct']:
+ break
+ else:
+ raise DeathByCaptchaException('timed-out')
+
+ result = res['text']
+ self.logDebug("Result %s : %s" % (ticket, result))
+
+ return ticket, result
+
+
+ def captchaTask(self, task):
+ if "service" in task.data:
+ return False
+
+ if not task.isTextual():
+ return False
+
+ if not self.getConfig("username") or not self.getConfig("passkey"):
+ return False
+
+ if self.core.isClientConnected() and not self.getConfig("force"):
+ return False
+
+ try:
+ self.getStatus()
+ self.getCredits()
+ except DeathByCaptchaException, e:
+ self.logError(e.getDesc())
+ return False
+
+ balance, rate = self.info['balance'], self.info['rate']
+ self.logInfo(_("Account balance"),
+ _("US$%.3f (%d captchas left at %.2f cents each)") % (balance / 100,
+ balance // rate, rate))
+
+ if balance > rate:
+ task.handler.append(self)
+ task.data['service'] = self.__name__
+ task.setWaiting(180)
+ self._processCaptcha(task)
+
+
+ def captchaInvalid(self, task):
+ if task.data['service'] == self.__name__ and "ticket" in task.data:
+ try:
+ res = self.api_response("captcha/%d/report" % task.data['ticket'], True)
+
+ except DeathByCaptchaException, e:
+ self.logError(e.getDesc())
+
+ except Exception, e:
+ self.logError(e)
+
+
+ @threaded
+ def _processCaptcha(self, task):
+ c = task.captchaFile
+ try:
+ ticket, result = self.submit(c)
+ except DeathByCaptchaException, e:
+ task.error = e.getCode()
+ self.logError(e.getDesc())
+ return
+
+ task.data['ticket'] = ticket
+ task.setResult(result)
diff --git a/pyload/plugin/hook/DebridItaliaCom.py b/pyload/plugin/hook/DebridItaliaCom.py
new file mode 100644
index 000000000..e2f766d86
--- /dev/null
+++ b/pyload/plugin/hook/DebridItaliaCom.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class DebridItaliaCom(MultiHook):
+ __name__ = "DebridItaliaCom"
+ __type__ = "hook"
+ __version__ = "0.12"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Debriditalia.com hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ def getHosters(self):
+ return self.getURL("http://debriditalia.com/api.php", get={'hosts': ""}).replace('"', '').split(',')
diff --git a/pyload/plugin/hook/EasybytezCom.py b/pyload/plugin/hook/EasybytezCom.py
new file mode 100644
index 000000000..1163bbf46
--- /dev/null
+++ b/pyload/plugin/hook/EasybytezCom.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class EasybytezCom(MultiHook):
+ __name__ = "EasybytezCom"
+ __type__ = "hook"
+ __version__ = "0.07"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """EasyBytez.com hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ def getHosters(self):
+ user, data = self.account.selectAccount()
+
+ req = self.account.getAccountRequest(user)
+ html = req.load("http://www.easybytez.com")
+
+ return re.search(r'</textarea>\s*Supported sites:(.*)', html).group(1).split(',')
diff --git a/pyload/plugin/hook/ExpertDecoders.py b/pyload/plugin/hook/ExpertDecoders.py
new file mode 100644
index 000000000..8fbc88c80
--- /dev/null
+++ b/pyload/plugin/hook/ExpertDecoders.py
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+from base64 import b64encode
+from pycurl import LOW_SPEED_TIME
+from uuid import uuid4
+
+from pyload.network.HTTPRequest import BadHeader
+from pyload.network.RequestFactory import getURL, getRequest
+from pyload.plugin.Hook import Hook, threaded
+
+
+class ExpertDecoders(Hook):
+ __name__ = "ExpertDecoders"
+ __type__ = "hook"
+ __version__ = "0.04"
+
+ __config__ = [("force", "bool", "Force CT even if client is connected", False),
+ ("passkey", "password", "Access key", "")]
+
+ __description__ = """Send captchas to expertdecoders.com"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ API_URL = "http://www.fasttypers.org/imagepost.ashx"
+
+
+ def getCredits(self):
+ res = getURL(self.API_URL, post={"key": self.getConfig("passkey"), "action": "balance"})
+
+ if res.isdigit():
+ self.logInfo(_("%s credits left") % res)
+ self.info['credits'] = credits = int(res)
+ return credits
+ else:
+ self.logError(res)
+ return 0
+
+
+ @threaded
+ def _processCaptcha(self, task):
+ task.data['ticket'] = ticket = uuid4()
+ result = None
+
+ with open(task.captchaFile, 'rb') as f:
+ data = f.read()
+
+ req = getRequest()
+ #raise timeout threshold
+ req.c.setopt(LOW_SPEED_TIME, 80)
+
+ try:
+ result = req.load(self.API_URL,
+ post={'action' : "upload",
+ 'key' : self.getConfig("passkey"),
+ 'file' : b64encode(data),
+ 'gen_task_id': ticket})
+ finally:
+ req.close()
+
+ self.logDebug("Result %s : %s" % (ticket, result))
+ task.setResult(result)
+
+
+ def captchaTask(self, task):
+ if not task.isTextual():
+ return False
+
+ if not self.getConfig("passkey"):
+ return False
+
+ if self.core.isClientConnected() and not self.getConfig("force"):
+ return False
+
+ if self.getCredits() > 0:
+ task.handler.append(self)
+ task.setWaiting(100)
+ self._processCaptcha(task)
+
+ else:
+ self.logInfo(_("Your ExpertDecoders Account has not enough credits"))
+
+
+ def captchaInvalid(self, task):
+ if "ticket" in task.data:
+
+ try:
+ res = getURL(self.API_URL,
+ post={'action': "refund", 'key': self.getConfig("passkey"), 'gen_task_id': task.data['ticket']})
+ self.logInfo(_("Request refund"), res)
+
+ except BadHeader, e:
+ self.logError(_("Could not send refund request"), e)
diff --git a/pyload/plugin/hook/FastixRu.py b/pyload/plugin/hook/FastixRu.py
new file mode 100644
index 000000000..8bc3b3f16
--- /dev/null
+++ b/pyload/plugin/hook/FastixRu.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class FastixRu(MultiHook):
+ __name__ = "FastixRu"
+ __type__ = "hook"
+ __version__ = "0.05"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Fastix.ru hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Massimo Rosamilia", "max@spiritix.eu")]
+
+
+ def getHosters(self):
+ html = self.getURL("http://fastix.ru/api_v2",
+ get={'apikey': "5182964c3f8f9a7f0b00000a_kelmFB4n1IrnCDYuIFn2y",
+ 'sub' : "allowed_sources"})
+ host_list = json_loads(html)
+ host_list = host_list['allow']
+ return host_list
diff --git a/pyload/plugin/hook/FreeWayMe.py b/pyload/plugin/hook/FreeWayMe.py
new file mode 100644
index 000000000..711be37a8
--- /dev/null
+++ b/pyload/plugin/hook/FreeWayMe.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class FreeWayMe(MultiHook):
+ __name__ = "FreeWayMe"
+ __type__ = "hook"
+ __version__ = "0.14"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """FreeWay.me hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Nicolas Giese", "james@free-way.me")]
+
+
+ def getHosters(self):
+ hostis = self.getURL("https://www.free-way.me/ajax/jd.php", get={'id': 3}).replace("\"", "").strip()
+ self.logDebug("Hosters", hostis)
+ return [x.strip() for x in hostis.split(",") if x.strip()]
diff --git a/pyload/plugin/hook/ImageTyperz.py b/pyload/plugin/hook/ImageTyperz.py
new file mode 100644
index 000000000..a9d7326de
--- /dev/null
+++ b/pyload/plugin/hook/ImageTyperz.py
@@ -0,0 +1,153 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import re
+
+from base64 import b64encode
+from pycurl import FORM_FILE, LOW_SPEED_TIME
+
+from pyload.network.RequestFactory import getURL, getRequest
+from pyload.plugin.Hook import Hook, threaded
+
+
+class ImageTyperzException(Exception):
+
+ def __init__(self, err):
+ self.err = err
+
+
+ def getCode(self):
+ return self.err
+
+
+ def __str__(self):
+ return "<ImageTyperzException %s>" % self.err
+
+
+ def __repr__(self):
+ return "<ImageTyperzException %s>" % self.err
+
+
+class ImageTyperz(Hook):
+ __name__ = "ImageTyperz"
+ __type__ = "hook"
+ __version__ = "0.06"
+
+ __config__ = [("username", "str", "Username", ""),
+ ("passkey", "password", "Password", ""),
+ ("force", "bool", "Force IT even if client is connected", False)]
+
+ __description__ = """Send captchas to ImageTyperz.com"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ SUBMIT_URL = "http://captchatypers.com/Forms/UploadFileAndGetTextNEW.ashx"
+ RESPOND_URL = "http://captchatypers.com/Forms/SetBadImage.ashx"
+ GETCREDITS_URL = "http://captchatypers.com/Forms/RequestBalance.ashx"
+
+
+ def getCredits(self):
+ res = getURL(self.GETCREDITS_URL,
+ post={'action': "REQUESTBALANCE",
+ 'username': self.getConfig("username"),
+ 'password': self.getConfig("passkey")})
+
+ if res.startswith('ERROR'):
+ raise ImageTyperzException(res)
+
+ try:
+ balance = float(res)
+ except Exception:
+ raise ImageTyperzException("Invalid response")
+
+ self.logInfo(_("Account balance: $%s left") % res)
+ return balance
+
+
+ def submit(self, captcha, captchaType="file", match=None):
+ req = getRequest()
+ #raise timeout threshold
+ req.c.setopt(LOW_SPEED_TIME, 80)
+
+ try:
+ #@NOTE: Workaround multipart-post bug in HTTPRequest.py
+ if re.match("^\w*$", self.getConfig("passkey")):
+ multipart = True
+ data = (FORM_FILE, captcha)
+ else:
+ multipart = False
+ with open(captcha, 'rb') as f:
+ data = f.read()
+ data = b64encode(data)
+
+ res = req.load(self.SUBMIT_URL,
+ post={'action': "UPLOADCAPTCHA",
+ 'username': self.getConfig("username"),
+ 'password': self.getConfig("passkey"), "file": data},
+ multipart=multipart)
+ finally:
+ req.close()
+
+ if res.startswith("ERROR"):
+ raise ImageTyperzException(res)
+ else:
+ data = res.split('|')
+ if len(data) == 2:
+ ticket, result = data
+ else:
+ raise ImageTyperzException("Unknown response: %s" % res)
+
+ return ticket, result
+
+
+ def captchaTask(self, task):
+ if "service" in task.data:
+ return False
+
+ if not task.isTextual():
+ return False
+
+ if not self.getConfig("username") or not self.getConfig("passkey"):
+ return False
+
+ if self.core.isClientConnected() and not self.getConfig("force"):
+ return False
+
+ if self.getCredits() > 0:
+ task.handler.append(self)
+ task.data['service'] = self.__name__
+ task.setWaiting(100)
+ self._processCaptcha(task)
+
+ else:
+ self.logInfo(_("Your %s account has not enough credits") % self.__name__)
+
+
+ def captchaInvalid(self, task):
+ if task.data['service'] == self.__name__ and "ticket" in task.data:
+ res = getURL(self.RESPOND_URL,
+ post={'action': "SETBADIMAGE",
+ 'username': self.getConfig("username"),
+ 'password': self.getConfig("passkey"),
+ 'imageid': task.data['ticket']})
+
+ if res == "SUCCESS":
+ self.logInfo(_("Bad captcha solution received, requested refund"))
+ else:
+ self.logError(_("Bad captcha solution received, refund request failed"), res)
+
+
+ @threaded
+ def _processCaptcha(self, task):
+ c = task.captchaFile
+ try:
+ ticket, result = self.submit(c)
+ except ImageTyperzException, e:
+ task.error = e.getCode()
+ return
+
+ task.data['ticket'] = ticket
+ task.setResult(result)
diff --git a/pyload/plugin/hook/LinkdecrypterCom.py b/pyload/plugin/hook/LinkdecrypterCom.py
new file mode 100644
index 000000000..efdf77065
--- /dev/null
+++ b/pyload/plugin/hook/LinkdecrypterCom.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class LinkdecrypterCom(MultiHook):
+ __name__ = "LinkdecrypterCom"
+ __type__ = "hook"
+ __version__ = "1.02"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Linkdecrypter.com hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ def getCrypters(self):
+ return re.search(r'>Supported\(\d+\)</b>: <i>(.[\w.\-, ]+)',
+ self.getURL("http://linkdecrypter.com/").replace("(g)", "")).group(1).split(', ')
diff --git a/pyload/plugin/hook/LinksnappyCom.py b/pyload/plugin/hook/LinksnappyCom.py
new file mode 100644
index 000000000..dc0c47496
--- /dev/null
+++ b/pyload/plugin/hook/LinksnappyCom.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class LinksnappyCom(MultiHook):
+ __name__ = "LinksnappyCom"
+ __type__ = "hook"
+ __version__ = "0.04"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Linksnappy.com hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ def getHosters(self):
+ json_data = self.getURL("http://gen.linksnappy.com/lseAPI.php", get={'act': "FILEHOSTS"})
+ json_data = json_loads(json_data)
+
+ return json_data['return'].keys()
diff --git a/pyload/plugin/hook/MegaDebridEu.py b/pyload/plugin/hook/MegaDebridEu.py
new file mode 100644
index 000000000..7e86d4d49
--- /dev/null
+++ b/pyload/plugin/hook/MegaDebridEu.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class MegaDebridEu(MultiHook):
+ __name__ = "MegaDebridEu"
+ __type__ = "hook"
+ __version__ = "0.05"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Mega-debrid.eu hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("D.Ducatel", "dducatel@je-geek.fr")]
+
+
+ def getHosters(self):
+ reponse = self.getURL("http://www.mega-debrid.eu/api.php", get={'action': "getHosters"})
+ json_data = json_loads(reponse)
+
+ if json_data['response_code'] == "ok":
+ host_list = [element[0] for element in json_data['hosters']]
+ else:
+ self.logError(_("Unable to retrieve hoster list"))
+ host_list = list()
+
+ return host_list
diff --git a/pyload/plugin/hook/MultihostersCom.py b/pyload/plugin/hook/MultihostersCom.py
new file mode 100644
index 000000000..7b92089a1
--- /dev/null
+++ b/pyload/plugin/hook/MultihostersCom.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.hook.ZeveraCom import ZeveraCom
+
+
+class MultihostersCom(ZeveraCom):
+ __name__ = "MultihostersCom"
+ __type__ = "hook"
+ __version__ = "0.02"
+
+ __config__ = [("mode" , "all;listed;unlisted", "Use for plugins (if supported)" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed", "bool" , "Revert to standard download if download fails", False),
+ ("interval" , "int" , "Reload interval in hours (0 to disable)" , 12 )]
+
+ __description__ = """Multihosters.com hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("tjeh", "tjeh@gmx.net")]
diff --git a/pyload/plugin/hook/MultishareCz.py b/pyload/plugin/hook/MultishareCz.py
new file mode 100644
index 000000000..56f30fb39
--- /dev/null
+++ b/pyload/plugin/hook/MultishareCz.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class MultishareCz(MultiHook):
+ __name__ = "MultishareCz"
+ __type__ = "hook"
+ __version__ = "0.07"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """MultiShare.cz hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ HOSTER_PATTERN = r'<img class="logo-shareserveru"[^>]*?alt="([^"]+)"></td>\s*<td class="stav">[^>]*?alt="OK"'
+
+
+ def getHosters(self):
+ html = self.getURL("http://www.multishare.cz/monitoring/")
+ return re.findall(self.HOSTER_PATTERN, html)
diff --git a/pyload/plugin/hook/MyfastfileCom.py b/pyload/plugin/hook/MyfastfileCom.py
new file mode 100644
index 000000000..097a54b60
--- /dev/null
+++ b/pyload/plugin/hook/MyfastfileCom.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.MultiHook import MultiHook
+from pyload.utils import json_loads
+
+
+class MyfastfileCom(MultiHook):
+ __name__ = "MyfastfileCom"
+ __type__ = "hook"
+ __version__ = "0.05"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Myfastfile.com hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ def getHosters(self):
+ json_data = self.getURL("http://myfastfile.com/api.php", get={'hosts': ""}, decode=True)
+ self.logDebug("JSON data", json_data)
+ json_data = json_loads(json_data)
+
+ return json_data['hosts']
diff --git a/pyload/plugin/hook/NoPremiumPl.py b/pyload/plugin/hook/NoPremiumPl.py
new file mode 100644
index 000000000..da7967154
--- /dev/null
+++ b/pyload/plugin/hook/NoPremiumPl.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class NoPremiumPl(MultiHook):
+ __name__ = "NoPremiumPl"
+ __type__ = "hook"
+ __version__ = "0.03"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """NoPremium.pl hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("goddie", "dev@nopremium.pl")]
+
+
+ def getHosters(self):
+ hostings = json_loads(self.getURL("https://www.nopremium.pl/clipboard.php?json=3").strip())
+ hostings_domains = [domain for row in hostings for domain in row["domains"] if row["sdownload"] == "0"]
+
+ self.logDebug(hostings_domains)
+
+ return hostings_domains
diff --git a/pyload/plugin/hook/OverLoadMe.py b/pyload/plugin/hook/OverLoadMe.py
new file mode 100644
index 000000000..e4602019f
--- /dev/null
+++ b/pyload/plugin/hook/OverLoadMe.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class OverLoadMe(MultiHook):
+ __name__ = "OverLoadMe"
+ __type__ = "hook"
+ __version__ = "0.04"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 ),
+ ("ssl" , "bool" , "Use HTTPS" , True )]
+
+ __description__ = """Over-Load.me hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("marley", "marley@over-load.me")]
+
+
+ def getHosters(self):
+ https = "https" if self.getConfig("ssl") else "http"
+ html = self.getURL(https + "://api.over-load.me/hoster.php",
+ get={'auth': "0001-cb1f24dadb3aa487bda5afd3b76298935329be7700cd7-5329be77-00cf-1ca0135f"}).replace("\"", "").strip()
+ self.logDebug("Hosterlist", html)
+
+ return [x.strip() for x in html.split(",") if x.strip()]
diff --git a/pyload/plugin/hook/PremiumTo.py b/pyload/plugin/hook/PremiumTo.py
new file mode 100644
index 000000000..58d753cec
--- /dev/null
+++ b/pyload/plugin/hook/PremiumTo.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class PremiumTo(MultiHook):
+ __name__ = "PremiumTo"
+ __type__ = "hook"
+ __version__ = "0.08"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Premium.to hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("zoidberg", "zoidberg@mujmail.cz"),
+ ("stickell", "l.stickell@yahoo.it")]
+
+
+ def getHosters(self):
+ html = self.getURL("http://premium.to/api/hosters.php",
+ get={'username': self.account.username, 'password': self.account.password})
+ return [x.strip() for x in html.replace("\"", "").split(";")]
diff --git a/pyload/plugin/hook/PremiumizeMe.py b/pyload/plugin/hook/PremiumizeMe.py
new file mode 100644
index 000000000..c5f1588ec
--- /dev/null
+++ b/pyload/plugin/hook/PremiumizeMe.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class PremiumizeMe(MultiHook):
+ __name__ = "PremiumizeMe"
+ __type__ = "hook"
+ __version__ = "0.17"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Premiumize.me hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Florian Franzen", "FlorianFranzen@gmail.com")]
+
+
+ def getHosters(self):
+ # Get account data
+ user, data = self.account.selectAccount()
+
+ # Get supported hosters list from premiumize.me using the
+ # json API v1 (see https://secure.premiumize.me/?show=api)
+ answer = self.getURL("https://api.premiumize.me/pm-api/v1.php",
+ get={'method': "hosterlist", 'params[login]': user, 'params[pass]': data['password']})
+ data = json_loads(answer)
+
+ # If account is not valid thera are no hosters available
+ if data['status'] != 200:
+ return []
+
+ # Extract hosters from json file
+ return data['result']['hosterlist']
diff --git a/pyload/plugin/hook/PutdriveCom.py b/pyload/plugin/hook/PutdriveCom.py
new file mode 100644
index 000000000..85e2f541d
--- /dev/null
+++ b/pyload/plugin/hook/PutdriveCom.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.hook.ZeveraCom import ZeveraCom
+
+
+class PutdriveCom(ZeveraCom):
+ __name__ = "PutdriveCom"
+ __type__ = "hook"
+ __version__ = "0.01"
+
+ __config__ = [("mode" , "all;listed;unlisted", "Use for plugins (if supported)" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed", "bool" , "Revert to standard download if download fails", False),
+ ("interval" , "int" , "Reload interval in hours (0 to disable)" , 12 )]
+
+ __description__ = """Putdrive.com hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
diff --git a/pyload/plugin/hook/RPNetBiz.py b/pyload/plugin/hook/RPNetBiz.py
new file mode 100644
index 000000000..75fe0e39b
--- /dev/null
+++ b/pyload/plugin/hook/RPNetBiz.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class RPNetBiz(MultiHook):
+ __name__ = "RPNetBiz"
+ __type__ = "hook"
+ __version__ = "0.14"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """RPNet.biz hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Dman", "dmanugm@gmail.com")]
+
+
+ def getHosters(self):
+ # Get account data
+ user, data = self.account.selectAccount()
+
+ res = self.getURL("https://premium.rpnet.biz/client_api.php",
+ get={'username': user, 'password': data['password'], 'action': "showHosterList"})
+ hoster_list = json_loads(res)
+
+ # If account is not valid thera are no hosters available
+ if 'error' in hoster_list:
+ return []
+
+ # Extract hosters from json file
+ return hoster_list['hosters']
diff --git a/pyload/plugin/hook/RapideoPl.py b/pyload/plugin/hook/RapideoPl.py
new file mode 100644
index 000000000..12d53830b
--- /dev/null
+++ b/pyload/plugin/hook/RapideoPl.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class RapideoPl(MultiHook):
+ __name__ = "RapideoPl"
+ __type__ = "hook"
+ __version__ = "0.03"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Rapideo.pl hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("goddie", "dev@rapideo.pl")]
+
+
+ def getHosters(self):
+ hostings = json_loads(self.getURL("https://www.rapideo.pl/clipboard.php?json=3").strip())
+ hostings_domains = [domain for row in hostings for domain in row["domains"] if row["sdownload"] == "0"]
+
+ self.logDebug(hostings_domains)
+
+ return hostings_domains
diff --git a/pyload/plugin/hook/RealdebridCom.py b/pyload/plugin/hook/RealdebridCom.py
new file mode 100644
index 000000000..a8eb03f83
--- /dev/null
+++ b/pyload/plugin/hook/RealdebridCom.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class RealdebridCom(MultiHook):
+ __name__ = "RealdebridCom"
+ __type__ = "hook"
+ __version__ = "0.46"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 ),
+ ("ssl" , "bool" , "Use HTTPS" , True )]
+
+ __description__ = """Real-Debrid.com hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Devirex Hazzard", "naibaf_11@yahoo.de")]
+
+
+ def getHosters(self):
+ https = "https" if self.getConfig("ssl") else "http"
+ html = self.getURL(https + "://real-debrid.com/api/hosters.php").replace("\"", "").strip()
+
+ return [x.strip() for x in html.split(",") if x.strip()]
diff --git a/pyload/plugin/hook/RehostTo.py b/pyload/plugin/hook/RehostTo.py
new file mode 100644
index 000000000..cda80417c
--- /dev/null
+++ b/pyload/plugin/hook/RehostTo.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class RehostTo(MultiHook):
+ __name__ = "RehostTo"
+ __type__ = "hook"
+ __version__ = "0.50"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Rehost.to hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org")]
+
+
+ def getHosters(self):
+ user, data = self.account.selectAccount()
+ html = self.getURL("http://rehost.to/api.php",
+ get={'cmd' : "get_supported_och_dl",
+ 'long_ses': self.account.getAccountInfo(user)['session']})
+ return [x.strip() for x in html.replace("\"", "").split(",")]
diff --git a/pyload/plugin/hook/SimplyPremiumCom.py b/pyload/plugin/hook/SimplyPremiumCom.py
new file mode 100644
index 000000000..28d9af41f
--- /dev/null
+++ b/pyload/plugin/hook/SimplyPremiumCom.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class SimplyPremiumCom(MultiHook):
+ __name__ = "SimplyPremiumCom"
+ __type__ = "hook"
+ __version__ = "0.05"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Simply-Premium.com hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("EvolutionClip", "evolutionclip@live.de")]
+
+
+ def getHosters(self):
+ json_data = self.getURL("http://www.simply-premium.com/api/hosts.php", get={'format': "json", 'online': 1})
+ json_data = json_loads(json_data)
+
+ host_list = [element['regex'] for element in json_data['result']]
+
+ return host_list
diff --git a/pyload/plugin/hook/SimplydebridCom.py b/pyload/plugin/hook/SimplydebridCom.py
new file mode 100644
index 000000000..011b346b8
--- /dev/null
+++ b/pyload/plugin/hook/SimplydebridCom.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class SimplydebridCom(MultiHook):
+ __name__ = "SimplydebridCom"
+ __type__ = "hook"
+ __version__ = "0.04"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Simply-Debrid.com hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Kagenoshin", "kagenoshin@gmx.ch")]
+
+
+ def getHosters(self):
+ html = self.getURL("http://simply-debrid.com/api.php", get={'list': 1})
+ return [x.strip() for x in html.rstrip(';').replace("\"", "").split(";")]
diff --git a/pyload/plugin/hook/SmoozedCom.py b/pyload/plugin/hook/SmoozedCom.py
new file mode 100644
index 000000000..3f5aab63d
--- /dev/null
+++ b/pyload/plugin/hook/SmoozedCom.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class SmoozedCom(MultiHook):
+ __name__ = "SmoozedCom"
+ __type__ = "hook"
+ __version__ = "0.03"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Smoozed.com hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("", "")]
+
+
+ def getHosters(self):
+ user, data = self.account.selectAccount()
+ return self.account.getAccountInfo(user)["hosters"]
diff --git a/pyload/plugin/hook/UnrestrictLi.py b/pyload/plugin/hook/UnrestrictLi.py
new file mode 100644
index 000000000..0c4984042
--- /dev/null
+++ b/pyload/plugin/hook/UnrestrictLi.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class UnrestrictLi(MultiHook):
+ __name__ = "UnrestrictLi"
+ __type__ = "hook"
+ __version__ = "0.05"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 ),
+ ("history" , "bool" , "Delete History" , False)]
+
+ __description__ = """Unrestrict.li hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ def getHosters(self):
+ json_data = self.getURL("http://unrestrict.li/api/jdownloader/hosts.php", get={'format': "json"})
+ json_data = json_loads(json_data)
+
+ return [element['host'] for element in json_data['result']]
diff --git a/pyload/plugin/hook/XFileSharingPro.py b/pyload/plugin/hook/XFileSharingPro.py
new file mode 100644
index 000000000..e3f816502
--- /dev/null
+++ b/pyload/plugin/hook/XFileSharingPro.py
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.Hook import Hook
+
+
+class XFileSharingPro(Hook):
+ __name__ = "XFileSharingPro"
+ __type__ = "hook"
+ __version__ = "0.31"
+
+ __config__ = [("activated" , "bool", "Activated" , True ),
+ ("use_hoster_list" , "bool", "Load listed hosters only" , False),
+ ("use_crypter_list", "bool", "Load listed crypters only" , False),
+ ("use_builtin_list", "bool", "Load built-in plugin list" , True ),
+ ("hoster_list" , "str" , "Hoster list (comma separated)" , "" ),
+ ("crypter_list" , "str" , "Crypter list (comma separated)", "" )]
+
+ __description__ = """Load XFileSharingPro based hosters and crypter which don't need a own plugin to run"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ # event_list = ["pluginConfigChanged"]
+ regexp = {'hoster' : (r'https?://(?:www\.)?(?P<DOMAIN>[\w.^_]+(?:\.[a-zA-Z]{2,})(?:\:\d+)?)/(?:embed-)?\w{12}(?:\W|$)',
+ r'https?://(?:[^/]+\.)?(?P<DOMAIN>%s)/(?:embed-)?\w+'),
+ 'crypter': (r'https?://(?:www\.)?(?P<DOMAIN>[\w.^_]+(?:\.[a-zA-Z]{2,})(?:\:\d+)?)/(?:user|folder)s?/\w+',
+ r'https?://(?:[^/]+\.)?(?P<DOMAIN>%s)/(?:user|folder)s?/\w+')}
+
+ HOSTER_BUILTIN = [#WORKING HOSTERS:
+ "180upload.com", "backin.net", "eyesfile.ca", "file4safe.com", "fileband.com", "filedwon.com",
+ "fileparadox.in", "filevice.com", "hostingbulk.com", "junkyvideo.com", "linestorage.com", "ravishare.com",
+ "ryushare.com", "salefiles.com", "sendmyway.com", "sharesix.com", "thefile.me", "verzend.be", "xvidstage.com",
+ #NOT TESTED:
+ "101shared.com", "4upfiles.com", "filemaze.ws", "filenuke.com", "linkzhost.com", "mightyupload.com",
+ "rockdizfile.com", "sharebeast.com", "sharerepo.com", "shareswift.com", "uploadbaz.com", "uploadc.com",
+ "vidbull.com", "zalaa.com", "zomgupload.com",
+ #NOT WORKING:
+ "amonshare.com", "banicrazy.info", "boosterking.com", "host4desi.com", "laoupload.com", "rd-fs.com"]
+ CRYPTER_BUILTIN = ["junocloud.me", "rapidfileshare.net"]
+
+
+ # def pluginConfigChanged(self.__name__, plugin, name, value):
+ # self.loadPattern()
+
+
+ def activate(self):
+ self.loadPattern()
+
+
+ def loadPattern(self):
+ use_builtin_list = self.getConfig('use_builtin_list')
+
+ for type in ("hoster", "crypter"):
+ every_plugin = not self.getConfig("use_%s_list" % type)
+
+ if every_plugin:
+ self.logInfo(_("Handling any %s I can!") % type)
+ pattern = self.regexp[type][0]
+ else:
+ plugins = self.getConfig('%s_list' % type)
+ plugin_set = set(plugins.replace(' ', '').replace('\\', '').replace('|', ',').replace(';', ',').lower().split(','))
+
+ if use_builtin_list:
+ plugin_set |= set(x.lower() for x in getattr(self, "%s_BUILTIN" % type.upper()))
+
+ plugin_set -= set(('', u''))
+
+ if not plugin_set:
+ self.logInfo(_("No %s to handle") % type)
+ self._unload(type)
+ return
+
+ match_list = '|'.join(sorted(plugin_set))
+
+ len_match_list = len(plugin_set)
+ self.logInfo(_("Handling %d %s%s: %s") % (len_match_list,
+ type,
+ "" if len_match_list == 1 else "s",
+ match_list.replace('|', ', ')))
+
+ pattern = self.regexp[type][1] % match_list.replace('.', '\.')
+
+ dict = self.core.pluginManager.plugins[type]["XFileSharingPro"]
+ dict['pattern'] = pattern
+ dict['re'] = re.compile(pattern)
+
+ self.logDebug("Loaded %s pattern: %s" % (type, pattern))
+
+
+ def _unload(self, type):
+ dict = self.core.pluginManager.plugins[type]["XFileSharingPro"]
+ dict['pattern'] = r'^unmatchable$'
+ dict['re'] = re.compile(dict['pattern'])
+
+
+ def deactivate(self):
+ # self.unloadHoster("BasePlugin")
+ for type in ("hoster", "crypter"):
+ self._unload(type, "XFileSharingPro")
+
+
+ # def downloadFailed(self, pyfile):
+ # if pyfile.pluginname == "BasePlugin" \
+ # and pyfile.hasStatus("failed") \
+ # and not self.getConfig("use_hoster_list") \
+ # and self.unloadHoster("BasePlugin"):
+ # self.logDebug("Unloaded XFileSharingPro from BasePlugin")
+ # pyfile.setStatus("queued")
diff --git a/pyload/plugin/hook/ZeveraCom.py b/pyload/plugin/hook/ZeveraCom.py
new file mode 100644
index 000000000..a60c33bd4
--- /dev/null
+++ b/pyload/plugin/hook/ZeveraCom.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.MultiHook import MultiHook
+
+
+class ZeveraCom(MultiHook):
+ __name__ = "ZeveraCom"
+ __type__ = "hook"
+ __version__ = "0.05"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Zevera.com hook plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ def getHosters(self):
+ html = self.account.api_response(pyreq.getHTTPRequest(timeout=120), cmd="gethosters")
+ return [x.strip() for x in html.split(",")]
diff --git a/module/plugins/hoster/__init__.py b/pyload/plugin/hook/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/plugins/hoster/__init__.py
+++ b/pyload/plugin/hook/__init__.py
diff --git a/pyload/plugin/hoster/AlldebridCom.py b/pyload/plugin/hoster/AlldebridCom.py
new file mode 100644
index 000000000..8ab98bc6f
--- /dev/null
+++ b/pyload/plugin/hoster/AlldebridCom.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from random import randrange
+from urllib import unquote
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHoster import MultiHoster
+from pyload.utils import parseFileSize
+
+
+class AlldebridCom(MultiHoster):
+ __name__ = "AlldebridCom"
+ __type__ = "hoster"
+ __version__ = "0.44"
+
+ __pattern__ = r'https?://(?:www\.|s\d+\.)?alldebrid\.com/dl/[\w^_]+'
+
+ __description__ = """Alldebrid.com multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Andy Voigt", "spamsales@online.de")]
+
+
+ def getFilename(self, url):
+ try:
+ name = unquote(url.rsplit("/", 1)[1])
+ except IndexError:
+ name = "Unknown_Filename..."
+
+ if name.endswith("..."): # incomplete filename, append random stuff
+ name += "%s.tmp" % randrange(100, 999)
+
+ return name
+
+
+ def setup(self):
+ self.chunkLimit = 16
+
+
+ def handlePremium(self, pyfile):
+ password = self.getPassword()
+
+ data = json_loads(self.load("http://www.alldebrid.com/service.php",
+ get={'link': pyfile.url, 'json': "true", 'pw': password}))
+
+ self.logDebug("Json data", data)
+
+ if data['error']:
+ if data['error'] == "This link isn't available on the hoster website.":
+ self.offline()
+ else:
+ self.logWarning(data['error'])
+ self.tempOffline()
+ else:
+ if pyfile.name and not pyfile.name.endswith('.tmp'):
+ pyfile.name = data['filename']
+ pyfile.size = parseFileSize(data['filesize'])
+ self.link = data['link']
+
+ if self.getConfig("ssl"):
+ self.link = self.link.replace("http://", "https://")
+ else:
+ self.link = self.link.replace("https://", "http://")
+
+ if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown"):
+ #only use when name wasnt already set
+ pyfile.name = self.getFilename(self.link)
+
+
+ def checkFile(self):
+ if self.checkDownload({'error': "<title>An error occured while processing your request</title>"}) == "error":
+ self.retry(wait_time=60, reason=_("An error occured while generating link"))
+
+ return super(AlldebridCom, self).checkFile()
diff --git a/pyload/plugin/hoster/AndroidfilehostCom.py b/pyload/plugin/hoster/AndroidfilehostCom.py
new file mode 100644
index 000000000..386df4f2c
--- /dev/null
+++ b/pyload/plugin/hoster/AndroidfilehostCom.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*
+#
+# Test links:
+# https://www.androidfilehost.com/?fid=95916177934518197
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class AndroidfilehostCom(SimpleHoster):
+ __name__ = "AndroidfilehostCom"
+ __type__ = "hoster"
+ __version__ = "0.01"
+
+ __pattern__ = r'https?://(?:www\.)?androidfilehost\.com/\?fid=\d+'
+
+ __description__ = """Androidfilehost.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
+
+
+ NAME_PATTERN = r'<br />(?P<N>.*?)</h1>'
+ SIZE_PATTERN = r'<h4>size</h4>\s*<p>(?P<S>[\d.,]+)(?P<U>[\w^_]+)</p>'
+ HASHSUM_PATTERN = r'<h4>(?P<T>.*?)</h4>\s*<p><code>(?P<H>.*?)</code></p>'
+
+ OFFLINE_PATTERN = r'404 not found'
+
+ WAIT_PATTERN = r'users must wait <strong>(\d+) secs'
+
+
+ def setup(self):
+ self.multiDL = True
+ self.resumeDownload = True
+ self.chunkLimit = 1
+
+
+ def handleFree(self, pyfile):
+ wait = re.search(self.WAIT_PATTERN, self.html)
+ self.logDebug("Waiting time: %s seconds" % wait.group(1))
+
+ fid = re.search(r'id="fid" value="(\d+)" />', self.html).group(1)
+ self.logDebug("fid: %s" % fid)
+
+ html = self.load("https://www.androidfilehost.com/libs/otf/mirrors.otf.php",
+ post={'submit': 'submit',
+ 'action': 'getdownloadmirrors',
+ 'fid' : fid},
+ decode=True)
+
+ self.link = re.findall('"url":"(.*?)"', html)[0].replace("\\", "")
+ mirror_host = self.link.split("/")[2]
+
+ self.logDebug("Mirror Host: %s" % mirror_host)
+
+ html = self.load("https://www.androidfilehost.com/libs/otf/stats.otf.php",
+ get={'fid' : fid,
+ 'w' : 'download',
+ 'mirror': mirror_host},
+ decode=True)
diff --git a/pyload/plugin/hoster/BasketbuildCom.py b/pyload/plugin/hoster/BasketbuildCom.py
new file mode 100644
index 000000000..fb34bbc40
--- /dev/null
+++ b/pyload/plugin/hoster/BasketbuildCom.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*
+#
+# Test links:
+# https://s.basketbuild.com/filedl/devs?dev=pacman&dl=pacman/falcon/RC-3/pac_falcon-RC-3-20141103.zip
+# https://s.basketbuild.com/filedl/gapps?dl=gapps-gb-20110828-signed.zip
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class BasketbuildCom(SimpleHoster):
+ __name__ = "BasketbuildCom"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'https?://(?:www\.)?(?:\w\.)?basketbuild\.com/filedl/.+'
+
+ __description__ = """basketbuild.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
+
+
+ NAME_PATTERN = r'File Name:</strong> (?P<N>.+?)<br/>'
+ SIZE_PATTERN = r'File Size:</strong> (?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+ OFFLINE_PATTERN = r'404 - Page Not Found'
+
+
+ def setup(self):
+ self.multiDL = True
+ self.resumeDownload = True
+ self.chunkLimit = 1
+
+
+ def handleFree(self, pyfile):
+ try:
+ link1 = re.search(r'href="(.+dlgate/.+)"', self.html).group(1)
+ self.html = self.load(link1)
+
+ except AttributeError:
+ self.error(_("Hop #1 not found"))
+
+ else:
+ self.logDebug("Next hop: %s" % link1)
+
+ try:
+ wait = re.search(r'var sec = (\d+)', self.html).group(1)
+ self.logDebug("Wait %s seconds" % wait)
+ self.wait(wait)
+
+ except AttributeError:
+ self.logDebug("No wait time found")
+
+ try:
+ self.link = re.search(r'id="dlLink">\s*<a href="(.+?)"', self.html).group(1)
+
+ except AttributeError:
+ self.error(_("DL-Link not found"))
diff --git a/pyload/plugin/hoster/BayfilesCom.py b/pyload/plugin/hoster/BayfilesCom.py
new file mode 100644
index 000000000..457440bd3
--- /dev/null
+++ b/pyload/plugin/hoster/BayfilesCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class BayfilesCom(DeadHoster):
+ __name__ = "BayfilesCom"
+ __type__ = "hoster"
+ __version__ = "0.09"
+
+ __pattern__ = r'https?://(?:www\.)?bayfiles\.(com|net)/file/(?P<ID>\w+/\w+/[^/]+)'
+
+ __description__ = """Bayfiles.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
diff --git a/pyload/plugin/hoster/BezvadataCz.py b/pyload/plugin/hoster/BezvadataCz.py
new file mode 100644
index 000000000..cea32dd5c
--- /dev/null
+++ b/pyload/plugin/hoster/BezvadataCz.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class BezvadataCz(SimpleHoster):
+ __name__ = "BezvadataCz"
+ __type__ = "hoster"
+ __version__ = "0.26"
+
+ __pattern__ = r'http://(?:www\.)?bezvadata\.cz/stahnout/.+'
+
+ __description__ = """BezvaData.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<p><b>Soubor: (?P<N>[^<]+)</b></p>'
+ SIZE_PATTERN = r'<li><strong>Velikost:</strong> (?P<S>[^<]+)</li>'
+ OFFLINE_PATTERN = r'<title>BezvaData \| Soubor nenalezen</title>'
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = True
+
+
+ def handleFree(self, pyfile):
+ #download button
+ m = re.search(r'<a class="stahnoutSoubor".*?href="(.*?)"', self.html)
+ if m is None:
+ self.error(_("Page 1 URL not found"))
+ url = "http://bezvadata.cz%s" % m.group(1)
+
+ #captcha form
+ self.html = self.load(url)
+ self.checkErrors()
+ for _i in xrange(5):
+ action, inputs = self.parseHtmlForm('frm-stahnoutFreeForm')
+ if not inputs:
+ self.error(_("FreeForm"))
+
+ m = re.search(r'<img src="data:image/png;base64,(.*?)"', self.html)
+ if m is None:
+ self.error(_("Wrong captcha image"))
+
+ #captcha image is contained in html page as base64encoded data but decryptCaptcha() expects image url
+ self.load, proper_load = self.loadcaptcha, self.load
+ try:
+ inputs['captcha'] = self.decryptCaptcha(m.group(1), imgtype='png')
+ finally:
+ self.load = proper_load
+
+ if '<img src="data:image/png;base64' in self.html:
+ self.invalidCaptcha()
+ else:
+ self.correctCaptcha()
+ break
+ else:
+ self.fail(_("No valid captcha code entered"))
+
+ #download url
+ self.html = self.load("http://bezvadata.cz%s" % action, post=inputs)
+ self.checkErrors()
+ m = re.search(r'<a class="stahnoutSoubor2" href="(.*?)">', self.html)
+ if m is None:
+ self.error(_("Page 2 URL not found"))
+ url = "http://bezvadata.cz%s" % m.group(1)
+ self.logDebug("DL URL %s" % url)
+
+ #countdown
+ m = re.search(r'id="countdown">(\d\d):(\d\d)<', self.html)
+ wait_time = (int(m.group(1)) * 60 + int(m.group(2))) if m else 120
+ self.wait(wait_time, False)
+
+ self.download(url)
+
+
+ def checkErrors(self):
+ if 'images/button-download-disable.png' in self.html:
+ self.longWait(5 * 60, 24) #: parallel dl limit
+ elif '<div class="infobox' in self.html:
+ self.tempOffline()
+
+ self.info.pop('error', None)
+
+
+ def loadcaptcha(self, data, *args, **kwargs):
+ return data.decode('base64')
diff --git a/pyload/plugin/hoster/BillionuploadsCom.py b/pyload/plugin/hoster/BillionuploadsCom.py
new file mode 100644
index 000000000..2dec3e8b8
--- /dev/null
+++ b/pyload/plugin/hoster/BillionuploadsCom.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class BillionuploadsCom(XFSHoster):
+ __name__ = "BillionuploadsCom"
+ __type__ = "hoster"
+ __version__ = "0.04"
+
+ __pattern__ = r'http://(?:www\.)?billionuploads\.com/\w{12}'
+
+ __description__ = """Billionuploads.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<td class="dofir" title="(?P<N>.+?)"'
+ SIZE_PATTERN = r'<td class="dofir">(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
diff --git a/pyload/plugin/hoster/BitshareCom.py b/pyload/plugin/hoster/BitshareCom.py
new file mode 100644
index 000000000..81bc8dae9
--- /dev/null
+++ b/pyload/plugin/hoster/BitshareCom.py
@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import re
+
+from pyload.plugin.internal.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class BitshareCom(SimpleHoster):
+ __name__ = "BitshareCom"
+ __type__ = "hoster"
+ __version__ = "0.53"
+
+ __pattern__ = r'http://(?:www\.)?bitshare\.com/(files/)?(?(1)|\?f=)(?P<ID>\w+)(?(1)/(?P<NAME>.+?)\.html)'
+
+ __description__ = """Bitshare.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Paul King", ""),
+ ("fragonib", "fragonib[AT]yahoo[DOT]es")]
+
+
+ COOKIES = [("bitshare.com", "language_selection", "EN")]
+
+ INFO_PATTERN = r'Downloading (?P<N>.+) - (?P<S>[\d.,]+) (?P<U>[\w^_]+)</h1>'
+ OFFLINE_PATTERN = r'[Ff]ile (not available|was deleted|was not found)'
+
+ AJAXID_PATTERN = r'var ajaxdl = "(.*?)";'
+ TRAFFIC_USED_UP = r'Your Traffic is used up for today'
+
+
+ def setup(self):
+ self.multiDL = self.premium
+ self.chunkLimit = 1
+
+
+ def process(self, pyfile):
+ if self.premium:
+ self.account.relogin(self.user)
+
+ # File id
+ m = re.match(self.__pattern__, pyfile.url)
+ self.file_id = max(m.group('ID1'), m.group('ID2'))
+ self.logDebug("File id is [%s]" % self.file_id)
+
+ # Load main page
+ self.html = self.load(pyfile.url, ref=False, decode=True)
+
+ # Check offline
+ if re.search(self.OFFLINE_PATTERN, self.html):
+ self.offline()
+
+ # Check Traffic used up
+ if re.search(self.TRAFFIC_USED_UP, self.html):
+ self.logInfo(_("Your Traffic is used up for today"))
+ self.wait(30 * 60, True)
+ self.retry()
+
+ # File name
+ m = re.match(self.__pattern__, pyfile.url)
+ name1 = m.group('NAME') if m else None
+
+ m = re.search(self.INFO_PATTERN, self.html)
+ name2 = m.group('N') if m else None
+
+ pyfile.name = max(name1, name2)
+
+ # Ajax file id
+ self.ajaxid = re.search(self.AJAXID_PATTERN, self.html).group(1)
+ self.logDebug("File ajax id is [%s]" % self.ajaxid)
+
+ # This may either download our file or forward us to an error page
+ self.download(self.getDownloadUrl())
+
+ if self.checkDownload({"error": ">Error occured<"}):
+ self.retry(5, 5 * 60, "Bitshare host : Error occured")
+
+
+ def getDownloadUrl(self):
+ # Return location if direct download is active
+ if self.premium:
+ header = self.load(self.pyfile.url, cookies=True, just_header=True)
+ if 'location' in header:
+ return header['location']
+
+ # Get download info
+ self.logDebug("Getting download info")
+ res = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html",
+ post={"request": "generateID", "ajaxid": self.ajaxid})
+
+ self.handleErrors(res, ':')
+
+ parts = res.split(":")
+ filetype = parts[0]
+ wait = int(parts[1])
+ captcha = int(parts[2])
+
+ self.logDebug("Download info [type: '%s', waiting: %d, captcha: %d]" % (filetype, wait, captcha))
+
+ # Waiting
+ if wait > 0:
+ self.logDebug("Waiting %d seconds." % wait)
+ if wait < 120:
+ self.wait(wait, False)
+ else:
+ self.wait(wait - 55, True)
+ self.retry()
+
+ # Resolve captcha
+ if captcha == 1:
+ self.logDebug("File is captcha protected")
+ recaptcha = ReCaptcha(self)
+
+ # Try up to 3 times
+ for i in xrange(3):
+ response, challenge = recaptcha.challenge()
+ res = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html",
+ post={"request" : "validateCaptcha",
+ "ajaxid" : self.ajaxid,
+ "recaptcha_challenge_field": challenge,
+ "recaptcha_response_field" : response})
+ if self.handleCaptchaErrors(res):
+ break
+
+ # Get download URL
+ self.logDebug("Getting download url")
+ res = self.load("http://bitshare.com/files-ajax/" + self.file_id + "/request.html",
+ post={"request": "getDownloadURL", "ajaxid": self.ajaxid})
+
+ self.handleErrors(res, '#')
+
+ url = res.split("#")[-1]
+
+ return url
+
+
+ def handleErrors(self, res, separator):
+ self.logDebug("Checking response [%s]" % res)
+ if "ERROR:Session timed out" in res:
+ self.retry()
+ elif "ERROR" in res:
+ msg = res.split(separator)[-1]
+ self.fail(msg)
+
+
+ def handleCaptchaErrors(self, res):
+ self.logDebug("Result of captcha resolving [%s]" % res)
+ if "SUCCESS" in res:
+ self.correctCaptcha()
+ return True
+ elif "ERROR:SESSION ERROR" in res:
+ self.retry()
+
+ self.invalidCaptcha()
diff --git a/pyload/plugin/hoster/BoltsharingCom.py b/pyload/plugin/hoster/BoltsharingCom.py
new file mode 100644
index 000000000..39e84cd7c
--- /dev/null
+++ b/pyload/plugin/hoster/BoltsharingCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class BoltsharingCom(DeadHoster):
+ __name__ = "BoltsharingCom"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?boltsharing\.com/\w{12}'
+
+ __description__ = """Boltsharing.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/CatShareNet.py b/pyload/plugin/hoster/CatShareNet.py
new file mode 100644
index 000000000..94a963c45
--- /dev/null
+++ b/pyload/plugin/hoster/CatShareNet.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class CatShareNet(SimpleHoster):
+ __name__ = "CatShareNet"
+ __type__ = "hoster"
+ __version__ = "0.11"
+
+ __pattern__ = r'http://(?:www\.)?catshare\.net/\w{16}'
+
+ __description__ = """CatShare.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("z00nx", "z00nx0@gmail.com"),
+ ("prOq", ""),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ TEXT_ENCODING = True
+
+ INFO_PATTERN = r'<title>(?P<N>.+) \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)<'
+ OFFLINE_PATTERN = ur'Podany plik został usunięty\s*</div>'
+
+ IP_BLOCKED_PATTERN = ur'>Nasz serwis wykrył ÅŒe Twój adres IP nie pochodzi z Polski.<'
+ WAIT_PATTERN = r'var\scount\s=\s(\d+);'
+
+ LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'<form action="(.+?)" method="GET">'
+
+
+ def setup(self):
+ self.multiDL = self.premium
+ self.resumeDownload = True
+
+
+ def getFileInfo(self):
+ m = re.search(self.IP_BLOCKED_PATTERN, self.html)
+ if m:
+ self.fail(_("Only connections from Polish IP address are allowed"))
+ return super(CatShareNet, self).getFileInfo()
+
+
+ def handleFree(self, pyfile):
+ recaptcha = ReCaptcha(self)
+
+ response, challenge = recaptcha.challenge()
+ self.html = self.load(pyfile.url,
+ post={'recaptcha_challenge_field': challenge,
+ 'recaptcha_response_field' : response})
+
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.invalidCaptcha()
+ self.retry(reason=_("Wrong captcha entered"))
+
+ self.link = m.group(1)
diff --git a/pyload/plugin/hoster/CloudzerNet.py b/pyload/plugin/hoster/CloudzerNet.py
new file mode 100644
index 000000000..c3154e9f1
--- /dev/null
+++ b/pyload/plugin/hoster/CloudzerNet.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class CloudzerNet(DeadHoster):
+ __name__ = "CloudzerNet"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'https?://(?:www\.)?(cloudzer\.net/file/|clz\.to/(file/)?)\w+'
+
+ __description__ = """Cloudzer.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("gs", "I-_-I-_-I@web.de"),
+ ("z00nx", "z00nx0@gmail.com"),
+ ("stickell", "l.stickell@yahoo.it")]
diff --git a/pyload/plugin/hoster/CloudzillaTo.py b/pyload/plugin/hoster/CloudzillaTo.py
new file mode 100644
index 000000000..e33e2ebe4
--- /dev/null
+++ b/pyload/plugin/hoster/CloudzillaTo.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class CloudzillaTo(SimpleHoster):
+ __name__ = "CloudzillaTo"
+ __type__ = "hoster"
+ __version__ = "0.06"
+
+ __pattern__ = r'http://(?:www\.)?cloudzilla\.to/share/file/(?P<ID>[\w^_]+)'
+
+ __description__ = """Cloudzilla.to hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ INFO_PATTERN = r'title="(?P<N>.+?)">\1</span> <span class="size">\((?P<S>[\d.]+) (?P<U>[\w^_]+)'
+ OFFLINE_PATTERN = r'>File not found...<'
+
+ PASSWORD_PATTERN = r'<div id="pwd_protected">'
+
+
+ def checkErrors(self):
+ m = re.search(self.PASSWORD_PATTERN, self.html)
+ if m:
+ self.html = self.load(self.pyfile.url, get={'key': self.getPassword()})
+
+ if re.search(self.PASSWORD_PATTERN, self.html):
+ self.retry(reason="Wrong password")
+
+
+ def handleFree(self, pyfile):
+ self.html = self.load("http://www.cloudzilla.to/generateticket/",
+ post={'file_id': self.info['pattern']['ID'], 'key': self.getPassword()})
+
+ ticket = dict(re.findall(r'<(.+?)>([^<>]+?)</', self.html))
+
+ self.logDebug(ticket)
+
+ if 'error' in ticket:
+ if "File is password protected" in ticket['error']:
+ self.retry(reason="Wrong password")
+ else:
+ self.fail(ticket['error'])
+
+ if 'wait' in ticket:
+ self.wait(ticket['wait'], int(ticket['wait']) > 5)
+
+ self.link = "http://%(server)s/download/%(file_id)s/%(ticket_id)s" % {'server' : ticket['server'],
+ 'file_id' : self.info['pattern']['ID'],
+ 'ticket_id': ticket['ticket_id']}
+
+
+ def handlePremium(self, pyfile):
+ return self.handleFree(pyfile)
diff --git a/pyload/plugin/hoster/CramitIn.py b/pyload/plugin/hoster/CramitIn.py
new file mode 100644
index 000000000..3ccb3cfc6
--- /dev/null
+++ b/pyload/plugin/hoster/CramitIn.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class CramitIn(XFSHoster):
+ __name__ = "CramitIn"
+ __type__ = "hoster"
+ __version__ = "0.07"
+
+ __pattern__ = r'http://(?:www\.)?cramit\.in/\w{12}'
+
+ __description__ = """Cramit.in hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ INFO_PATTERN = r'<span class=t2>\s*(?P<N>.*?)</span>.*?<small>\s*\((?P<S>.*?)\)'
+
+ LINK_PATTERN = r'href="(http://cramit\.in/file_download/.*?)"'
diff --git a/pyload/plugin/hoster/CrockoCom.py b/pyload/plugin/hoster/CrockoCom.py
new file mode 100644
index 000000000..bcbbc84a1
--- /dev/null
+++ b/pyload/plugin/hoster/CrockoCom.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class CrockoCom(SimpleHoster):
+ __name__ = "CrockoCom"
+ __type__ = "hoster"
+ __version__ = "0.19"
+
+ __pattern__ = r'http://(?:www\.)?(crocko|easy-share)\.com/\w+'
+
+ __description__ = """Crocko hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<span class="fz24">Download:\s*<strong>(?P<N>.*)'
+ SIZE_PATTERN = r'<span class="tip1"><span class="inner">(?P<S>[^<]+)</span></span>'
+ OFFLINE_PATTERN = r'<h1>Sorry,<br />the page you\'re looking for <br />isn\'t here.</h1>|File not found'
+
+ CAPTCHA_PATTERN = re.compile(r"u='(/file_contents/captcha/\w+)';\s*w='(\d+)';")
+
+ FORM_PATTERN = r'<form method="post" action="([^"]+)">(.*?)</form>'
+ FORM_INPUT_PATTERN = r'<input[^>]* name="?([^" ]+)"? value="?([^" ]+)"?[^>]*>'
+
+ NAME_REPLACEMENTS = [(r'<[^>]*>', '')]
+
+
+ def handleFree(self, pyfile):
+ if "You need Premium membership to download this file." in self.html:
+ self.fail(_("You need Premium membership to download this file"))
+
+ for _i in xrange(5):
+ m = re.search(self.CAPTCHA_PATTERN, self.html)
+ if m:
+ url, wait_time = 'http://crocko.com' + m.group(1), int(m.group(2))
+ self.wait(wait_time)
+ self.html = self.load(url)
+ else:
+ break
+
+ m = re.search(self.FORM_PATTERN, self.html, re.S)
+ if m is None:
+ self.error(_("FORM_PATTERN not found"))
+
+ action, form = m.groups()
+ inputs = dict(re.findall(self.FORM_INPUT_PATTERN, form))
+ recaptcha = ReCaptcha(self)
+
+ for _i in xrange(5):
+ inputs['recaptcha_response_field'], inputs['recaptcha_challenge_field'] = recaptcha.challenge()
+ self.download(action, post=inputs)
+
+ if self.checkDownload({"captcha": recaptcha.KEY_AJAX_PATTERN}):
+ self.invalidCaptcha()
+ else:
+ break
+ else:
+ self.fail(_("No valid captcha solution received"))
diff --git a/pyload/plugin/hoster/CyberlockerCh.py b/pyload/plugin/hoster/CyberlockerCh.py
new file mode 100644
index 000000000..c4e1d41b1
--- /dev/null
+++ b/pyload/plugin/hoster/CyberlockerCh.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class CyberlockerCh(DeadHoster):
+ __name__ = "CyberlockerCh"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?cyberlocker\.ch/\w+'
+
+ __description__ = """Cyberlocker.ch hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
diff --git a/pyload/plugin/hoster/CzshareCom.py b/pyload/plugin/hoster/CzshareCom.py
new file mode 100644
index 000000000..3bf371508
--- /dev/null
+++ b/pyload/plugin/hoster/CzshareCom.py
@@ -0,0 +1,158 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# http://czshare.com/5278880/random.bin
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+from pyload.utils import parseFileSize
+
+
+class CzshareCom(SimpleHoster):
+ __name__ = "CzshareCom"
+ __type__ = "hoster"
+ __version__ = "0.98"
+
+ __pattern__ = r'http://(?:www\.)?(czshare|sdilej)\.(com|cz)/(\d+/|download\.php\?).+'
+
+ __description__ = """CZshare.com hoster plugin, now Sdilej.cz"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<div class="tab" id="parameters">\s*<p>\s*Cel. n.zev: <a href=[^>]*>(?P<N>[^<]+)</a>'
+ SIZE_PATTERN = r'<div class="tab" id="category">(?:\s*<p>[^\n]*</p>)*\s*Velikost:\s*(?P<S>[\d .,]+)(?P<U>[\w^_]+)\s*</div>'
+ OFFLINE_PATTERN = r'<div class="header clearfix">\s*<h2 class="red">'
+
+ SIZE_REPLACEMENTS = [(' ', '')]
+ URL_REPLACEMENTS = [(r'http://[^/]*/download.php\?.*?id=(\w+).*', r'http://sdilej.cz/\1/x/')]
+
+ CHECK_TRAFFIC = True
+
+ FREE_URL_PATTERN = r'<a href="([^"]+)" class="page-download">[^>]*alt="([^"]+)" /></a>'
+ FREE_FORM_PATTERN = r'<form action="download\.php" method="post">\s*<img src="captcha\.php" id="captcha" />(.*?)</form>'
+ PREMIUM_FORM_PATTERN = r'<form action="/profi_down\.php" method="post">(.*?)</form>'
+ FORM_INPUT_PATTERN = r'<input[^>]* name="([^"]+)" value="([^"]+)"[^>]*/>'
+ MULTIDL_PATTERN = r'<p><font color=\'red\'>Z[^<]*PROFI.</font></p>'
+ USER_CREDIT_PATTERN = r'<div class="credit">\s*kredit: <strong>([\d .,]+)(\w+)</strong>\s*</div><!-- .credit -->'
+
+
+ def checkTrafficLeft(self):
+ # check if user logged in
+ m = re.search(self.USER_CREDIT_PATTERN, self.html)
+ if m is None:
+ self.account.relogin(self.user)
+ self.html = self.load(self.pyfile.url, cookies=True, decode=True)
+ m = re.search(self.USER_CREDIT_PATTERN, self.html)
+ if m is None:
+ return False
+
+ # check user credit
+ try:
+ credit = parseFileSize(m.group(1).replace(' ', ''), m.group(2))
+ self.logInfo(_("Premium download for %i KiB of Credit") % (self.pyfile.size / 1024))
+ self.logInfo(_("User %s has %i KiB left") % (self.user, credit / 1024))
+ if credit < self.pyfile.size:
+ self.logInfo(_("Not enough credit to download file: %s") % self.pyfile.name)
+ return False
+ except Exception, e:
+ # let's continue and see what happens...
+ self.logError(e)
+
+ return True
+
+
+ def handlePremium(self, pyfile):
+ # parse download link
+ try:
+ form = re.search(self.PREMIUM_FORM_PATTERN, self.html, re.S).group(1)
+ inputs = dict(re.findall(self.FORM_INPUT_PATTERN, form))
+ except Exception, e:
+ self.logError(e)
+ self.resetAccount()
+
+ # download the file, destination is determined by pyLoad
+ self.download("http://sdilej.cz/profi_down.php", post=inputs, disposition=True)
+
+
+ def handleFree(self, pyfile):
+ # get free url
+ m = re.search(self.FREE_URL_PATTERN, self.html)
+ if m is None:
+ self.error(_("FREE_URL_PATTERN not found"))
+
+ parsed_url = "http://sdilej.cz" + m.group(1)
+
+ self.logDebug("PARSED_URL:" + parsed_url)
+
+ # get download ticket and parse html
+ self.html = self.load(parsed_url, cookies=True, decode=True)
+ if re.search(self.MULTIDL_PATTERN, self.html):
+ self.longWait(5 * 60, 12)
+
+ try:
+ form = re.search(self.FREE_FORM_PATTERN, self.html, re.S).group(1)
+ inputs = dict(re.findall(self.FORM_INPUT_PATTERN, form))
+ pyfile.size = int(inputs['size'])
+
+ except Exception, e:
+ self.logError(e)
+ self.error(_("Form"))
+
+ # get and decrypt captcha
+ captcha_url = 'http://sdilej.cz/captcha.php'
+ for _i in xrange(5):
+ inputs['captchastring2'] = self.decryptCaptcha(captcha_url)
+ self.html = self.load(parsed_url, cookies=True, post=inputs, decode=True)
+
+ if u"<li>ZadanÃœ ověřovací kód nesouhlasí!</li>" in self.html:
+ self.invalidCaptcha()
+
+ elif re.search(self.MULTIDL_PATTERN, self.html):
+ self.longWait(5 * 60, 12)
+
+ else:
+ self.correctCaptcha()
+ break
+ else:
+ self.fail(_("No valid captcha code entered"))
+
+ m = re.search("countdown_number = (\d+);", self.html)
+ self.setWait(int(m.group(1)) if m else 50)
+
+ # download the file, destination is determined by pyLoad
+ self.logDebug("WAIT URL", self.req.lastEffectiveURL)
+
+ m = re.search("free_wait.php\?server=(.*?)&(.*)", self.req.lastEffectiveURL)
+ if m is None:
+ self.error(_("Download URL not found"))
+
+ self.link = "http://%s/download.php?%s" % (m.group(1), m.group(2))
+
+ self.wait()
+
+
+ def checkFile(self):
+ # check download
+ check = self.checkDownload({
+ "temp offline" : re.compile(r"^Soubor je do.*asn.* nedostupn.*$"),
+ "credit" : re.compile(r"^Nem.*te dostate.*n.* kredit.$"),
+ "multi-dl" : re.compile(self.MULTIDL_PATTERN),
+ "captcha" : "<li>ZadanÃœ ověřovací kód nesouhlasí!</li>"
+ })
+
+ if check == "temp offline":
+ self.fail(_("File not available - try later"))
+
+ elif check == "credit":
+ self.resetAccount()
+
+ elif check == "multi-dl":
+ self.longWait(5 * 60, 12)
+
+ elif check == "captcha":
+ self.invalidCaptcha()
+ self.retry()
+
+ return super(CzshareCom, self).checkFile()
diff --git a/module/plugins/hoster/DailymotionCom.py b/pyload/plugin/hoster/DailymotionCom.py
index c212fa872..c212fa872 100644
--- a/module/plugins/hoster/DailymotionCom.py
+++ b/pyload/plugin/hoster/DailymotionCom.py
diff --git a/pyload/plugin/hoster/DataHu.py b/pyload/plugin/hoster/DataHu.py
new file mode 100644
index 000000000..219e73441
--- /dev/null
+++ b/pyload/plugin/hoster/DataHu.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# http://data.hu/get/6381232/random.bin
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class DataHu(SimpleHoster):
+ __name__ = "DataHu"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?data\.hu/get/\w+'
+
+ __description__ = """Data.hu hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("crash", ""),
+ ("stickell", "l.stickell@yahoo.it")]
+
+
+ INFO_PATTERN = ur'<title>(?P<N>.*) \((?P<S>[^)]+)\) let\xf6lt\xe9se</title>'
+ OFFLINE_PATTERN = ur'Az adott f\xe1jl nem l\xe9tezik'
+ LINK_FREE_PATTERN = r'<div class="download_box_button"><a href="([^"]+)">'
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = self.premium
diff --git a/pyload/plugin/hoster/DataportCz.py b/pyload/plugin/hoster/DataportCz.py
new file mode 100644
index 000000000..8a32400ec
--- /dev/null
+++ b/pyload/plugin/hoster/DataportCz.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class DataportCz(SimpleHoster):
+ __name__ = "DataportCz"
+ __type__ = "hoster"
+ __version__ = "0.41"
+
+ __pattern__ = r'http://(?:www\.)?dataport\.cz/file/(.+)'
+
+ __description__ = """Dataport.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<span itemprop="name">(?P<N>[^<]+)</span>'
+ SIZE_PATTERN = r'<td class="fil">Velikost</td>\s*<td>(?P<S>[^<]+)</td>'
+ OFFLINE_PATTERN = r'<h2>Soubor nebyl nalezen</h2>'
+
+ CAPTCHA_PATTERN = r'<section id="captcha_bg">\s*<img src="(.*?)"'
+ FREE_SLOTS_PATTERN = ur'Počet volnÜch slotů: <span class="darkblue">(\d+)</span><br />'
+
+
+ def handleFree(self, pyfile):
+ captchas = {"1": "jkeG", "2": "hMJQ", "3": "vmEK", "4": "ePQM", "5": "blBd"}
+
+ for _i in xrange(60):
+ action, inputs = self.parseHtmlForm('free_download_form')
+ self.logDebug(action, inputs)
+ if not action or not inputs:
+ self.error(_("free_download_form"))
+
+ if "captchaId" in inputs and inputs['captchaId'] in captchas:
+ inputs['captchaCode'] = captchas[inputs['captchaId']]
+ else:
+ self.error(_("captcha"))
+
+ self.html = self.download("http://www.dataport.cz%s" % action, post=inputs)
+
+ check = self.checkDownload({"captcha": 'alert("\u0160patn\u011b opsan\u00fd k\u00f3d z obr\u00e1zu");',
+ "slot" : 'alert("Je n\u00e1m l\u00edto, ale moment\u00e1ln\u011b nejsou'})
+ if check == "captcha":
+ self.error(_("invalid captcha"))
+
+ elif check == "slot":
+ self.logDebug("No free slots - wait 60s and retry")
+ self.wait(60, False)
+ self.html = self.load(pyfile.url, decode=True)
+ continue
+
+ else:
+ break
diff --git a/pyload/plugin/hoster/DateiTo.py b/pyload/plugin/hoster/DateiTo.py
new file mode 100644
index 000000000..216a758c8
--- /dev/null
+++ b/pyload/plugin/hoster/DateiTo.py
@@ -0,0 +1,79 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class DateiTo(SimpleHoster):
+ __name__ = "DateiTo"
+ __type__ = "hoster"
+ __version__ = "0.07"
+
+ __pattern__ = r'http://(?:www\.)?datei\.to/datei/(?P<ID>\w+)\.html'
+
+ __description__ = """Datei.to hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'Dateiname:</td>\s*<td colspan="2"><strong>(?P<N>.*?)</'
+ SIZE_PATTERN = r'Dateigr&ouml;&szlig;e:</td>\s*<td colspan="2">(?P<S>.*?)</'
+ OFFLINE_PATTERN = r'>Datei wurde nicht gefunden<|>Bitte wÀhle deine Datei aus... <'
+
+ WAIT_PATTERN = r'countdown\({seconds: (\d+)'
+ MULTIDL_PATTERN = r'>Du lÀdst bereits eine Datei herunter<'
+
+ DATA_PATTERN = r'url: "(.*?)", data: "(.*?)",'
+
+
+ def handleFree(self, pyfile):
+ url = 'http://datei.to/ajax/download.php'
+ data = {'P': 'I', 'ID': self.info['pattern']['ID']}
+ recaptcha = ReCaptcha(self)
+
+ for _i in xrange(10):
+ self.logDebug("URL", url, "POST", data)
+ self.html = self.load(url, post=data)
+ self.checkErrors()
+
+ if url.endswith('download.php') and 'P' in data:
+ if data['P'] == 'I':
+ self.doWait()
+
+ elif data['P'] == 'IV':
+ break
+
+ m = re.search(self.DATA_PATTERN, self.html)
+ if m is None:
+ self.error(_("data"))
+ url = 'http://datei.to/' + m.group(1)
+ data = dict(x.split('=') for x in m.group(2).split('&'))
+
+ if url.endswith('recaptcha.php'):
+ data['recaptcha_response_field'], data['recaptcha_challenge_field'] = recaptcha.challenge()
+ else:
+ self.fail(_("Too bad..."))
+
+ self.download(self.html)
+
+
+ def checkErrors(self):
+ m = re.search(self.MULTIDL_PATTERN, self.html)
+ if m:
+ m = re.search(self.WAIT_PATTERN, self.html)
+ wait_time = int(m.group(1)) if m else 30
+
+ errmsg = self.info['error'] = _("Parallel downloads")
+ self.retry(wait_time=wait_time, reason=errmsg)
+
+ self.info.pop('error', None)
+
+
+ def doWait(self):
+ m = re.search(self.WAIT_PATTERN, self.html)
+ wait_time = int(m.group(1)) if m else 30
+
+ self.load('http://datei.to/ajax/download.php', post={'P': 'Ads'})
+ self.wait(wait_time, False)
diff --git a/pyload/plugin/hoster/DdlstorageCom.py b/pyload/plugin/hoster/DdlstorageCom.py
new file mode 100644
index 000000000..cfde84ad0
--- /dev/null
+++ b/pyload/plugin/hoster/DdlstorageCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class DdlstorageCom(DeadHoster):
+ __name__ = "DdlstorageCom"
+ __type__ = "hoster"
+ __version__ = "1.02"
+
+ __pattern__ = r'https?://(?:www\.)?ddlstorage\.com/\w+'
+
+ __description__ = """DDLStorage.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
+ ("stickell", "l.stickell@yahoo.it")]
diff --git a/pyload/plugin/hoster/DebridItaliaCom.py b/pyload/plugin/hoster/DebridItaliaCom.py
new file mode 100644
index 000000000..1e7e1a338
--- /dev/null
+++ b/pyload/plugin/hoster/DebridItaliaCom.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.MultiHoster import MultiHoster
+
+
+class DebridItaliaCom(MultiHoster):
+ __name__ = "DebridItaliaCom"
+ __type__ = "hoster"
+ __version__ = "0.17"
+
+ __pattern__ = r'https?://(?:www\.|s\d+\.)?debriditalia\.com/dl/\d+'
+
+ __description__ = """Debriditalia.com multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ URL_REPLACEMENTS = [("https://", "http://")]
+
+
+ def handlePremium(self, pyfile):
+ self.html = self.load("http://www.debriditalia.com/api.php",
+ get={'generate': "on", 'link': pyfile.url, 'p': self.getPassword()})
+
+ if "ERROR:" not in self.html:
+ self.link = self.html.strip()
+ else:
+ self.info['error'] = re.search(r'ERROR:(.*)', self.html).group(1).strip()
+
+ self.html = self.load("http://debriditalia.com/linkgen2.php",
+ post={'xjxfun' : "convertiLink",
+ 'xjxargs[]': "S<![CDATA[%s]]>" % pyfile.url,
+ 'xjxargs[]': "S%s" % self.getPassword()})
+ try:
+ self.link = re.search(r'<a href="(.+?)"', self.html).group(1)
+ except AttributeError:
+ pass
diff --git a/pyload/plugin/hoster/DepositfilesCom.py b/pyload/plugin/hoster/DepositfilesCom.py
new file mode 100644
index 000000000..67cfe4bdc
--- /dev/null
+++ b/pyload/plugin/hoster/DepositfilesCom.py
@@ -0,0 +1,112 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urllib import unquote
+
+from pyload.plugin.internal.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class DepositfilesCom(SimpleHoster):
+ __name__ = "DepositfilesCom"
+ __type__ = "hoster"
+ __version__ = "0.53"
+
+ __pattern__ = r'https?://(?:www\.)?(depositfiles\.com|dfiles\.(eu|ru))(/\w{1,3})?/files/(?P<ID>\w+)'
+
+ __description__ = """Depositfiles.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("spoob", "spoob@pyload.org"),
+ ("zoidberg", "zoidberg@mujmail.cz"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ NAME_PATTERN = r'<script type="text/javascript">eval\( unescape\(\'(?P<N>.*?)\''
+ SIZE_PATTERN = r': <b>(?P<S>[\d.,]+)&nbsp;(?P<U>[\w^_]+)</b>'
+ OFFLINE_PATTERN = r'<span class="html_download_api-not_exists"></span>'
+
+ NAME_REPLACEMENTS = [(r'\%u([0-9A-Fa-f]{4})', lambda m: unichr(int(m.group(1), 16))),
+ (r'.*<b title="(?P<N>[^"]+).*', "\g<N>")]
+ URL_REPLACEMENTS = [(__pattern__ + ".*", "https://dfiles.eu/files/\g<ID>")]
+
+ COOKIES = [("dfiles.eu", "lang_current", "en")]
+
+ LINK_FREE_PATTERN = r'<form id="downloader_file_form" action="(http://.+?\.(dfiles\.eu|depositfiles\.com)/.+?)" method="post"'
+ LINK_PREMIUM_PATTERN = r'class="repeat"><a href="(.+?)"'
+ LINK_MIRROR_PATTERN = r'class="repeat_mirror"><a href="(.+?)"'
+
+
+ def handleFree(self, pyfile):
+ if re.search(r'File is checked, please try again in a minute.', self.html) is not None:
+ self.logInfo(_("The file is being checked. Waiting 1 minute"))
+ self.retry(wait_time=60)
+
+ wait = re.search(r'html_download_api-limit_interval\">(\d+)</span>', self.html)
+ if wait:
+ wait_time = int(wait.group(1))
+ self.logInfo(_("Traffic used up. Waiting %d seconds") % wait_time)
+ self.wait(wait_time, True)
+ self.retry()
+
+ wait = re.search(r'>Try in (\d+) minutes or use GOLD account', self.html)
+ if wait:
+ wait_time = int(wait.group(1))
+ self.logInfo(_("All free slots occupied. Waiting %d minutes") % wait_time)
+ self.setWait(wait_time * 60, False)
+
+ wait = re.search(r'Please wait (\d+) sec', self.html)
+ if wait:
+ self.setWait(int(wait.group(1)))
+
+ m = re.search(r"var fid = '(\w+)';", self.html)
+ if m is None:
+ self.retry(wait_time=5)
+ params = {'fid': m.group(1)}
+ self.logDebug("FID: %s" % params['fid'])
+
+ self.wait()
+ recaptcha = ReCaptcha(self)
+ captcha_key = recaptcha.detect_key()
+ if captcha_key is None:
+ self.error(_("ReCaptcha key not found"))
+
+ for _i in xrange(5):
+ self.html = self.load("https://dfiles.eu/get_file.php", get=params)
+
+ if '<input type=button value="Continue" onclick="check_recaptcha' in self.html:
+ if 'response' in params:
+ self.invalidCaptcha()
+ params['response'], params['challenge'] = recaptcha.challenge(captcha_key)
+ self.logDebug(params)
+ continue
+
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m:
+ if 'response' in params:
+ self.correctCaptcha()
+
+ self.link = unquote(m.group(1))
+ break
+ else:
+ self.error(_("Download link"))
+ else:
+ self.fail(_("No valid captcha response received"))
+
+
+ def handlePremium(self, pyfile):
+ if '<span class="html_download_api-gold_traffic_limit">' in self.html:
+ self.logWarning(_("Download limit reached"))
+ self.retry(25, 60 * 60, "Download limit reached")
+ elif 'onClick="show_gold_offer' in self.html:
+ self.account.relogin(self.user)
+ self.retry()
+ else:
+ link = re.search(self.LINK_PREMIUM_PATTERN, self.html)
+ mirror = re.search(self.LINK_MIRROR_PATTERN, self.html)
+
+ if link:
+ self.link = link.group(1)
+
+ elif mirror:
+ self.link = mirror.group(1)
diff --git a/pyload/plugin/hoster/DevhostSt.py b/pyload/plugin/hoster/DevhostSt.py
new file mode 100644
index 000000000..e4c6f819b
--- /dev/null
+++ b/pyload/plugin/hoster/DevhostSt.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# http://d-h.st/mM8
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class DevhostSt(SimpleHoster):
+ __name__ = "DevhostSt"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'http://(?:www\.)?d-h\.st/(?!users/)\w{3}'
+
+ __description__ = """d-h.st hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
+
+
+ NAME_PATTERN = r'<span title="(?P<N>.*?)"'
+ SIZE_PATTERN = r'</span> \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)<br'
+ HASHSUM_PATTERN = r'>(?P<T>.*?) Sum</span>: &nbsp;(?P<H>.*?)<br'
+
+ OFFLINE_PATTERN = r'>File Not Found'
+ LINK_FREE_PATTERN = r'var product_download_url= \'(.+?)\''
+
+
+ def setup(self):
+ self.multiDL = True
+ self.chunkLimit = 1
diff --git a/pyload/plugin/hoster/DlFreeFr.py b/pyload/plugin/hoster/DlFreeFr.py
new file mode 100644
index 000000000..b0f9e7b7f
--- /dev/null
+++ b/pyload/plugin/hoster/DlFreeFr.py
@@ -0,0 +1,137 @@
+# -*- coding: utf-8 -*-
+
+import pycurl
+import re
+
+from pyload.network.Browser import Browser
+from pyload.network.CookieJar import CookieJar
+from pyload.plugin.internal.captcha import AdYouLike
+from pyload.plugin.internal.SimpleHoster import SimpleHoster, replace_patterns
+from pyload.utils import json_loads
+
+
+class CustomBrowser(Browser):
+
+ def __init__(self, bucket=None, options={}):
+ Browser.__init__(self, bucket, options)
+
+
+ def load(self, *args, **kwargs):
+ post = kwargs.get("post")
+
+ if post is None and len(args) > 2:
+ post = args[2]
+
+ if post:
+ self.http.c.setopt(pycurl.FOLLOWLOCATION, 0)
+ self.http.c.setopt(pycurl.POST, 1)
+ self.http.c.setopt(pycurl.CUSTOMREQUEST, "POST")
+ else:
+ self.http.c.setopt(pycurl.FOLLOWLOCATION, 1)
+ self.http.c.setopt(pycurl.POST, 0)
+ self.http.c.setopt(pycurl.CUSTOMREQUEST, "GET")
+
+ return Browser.load(self, *args, **kwargs)
+
+
+class DlFreeFr(SimpleHoster):
+ __name__ = "DlFreeFr"
+ __type__ = "hoster"
+ __version__ = "0.28"
+
+ __pattern__ = r'http://(?:www\.)?dl\.free\.fr/(\w+|getfile\.pl\?file=/\w+)'
+
+ __description__ = """Dl.free.fr hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("the-razer", "daniel_ AT gmx DOT net"),
+ ("zoidberg", "zoidberg@mujmail.cz"),
+ ("Toilal", "toilal.dev@gmail.com")]
+
+
+ NAME_PATTERN = r'Fichier:</td>\s*<td[^>]*>(?P<N>[^>]*)</td>'
+ SIZE_PATTERN = r'Taille:</td>\s*<td[^>]*>(?P<S>[\d.,]+\w)o'
+ OFFLINE_PATTERN = r'Erreur 404 - Document non trouv|Fichier inexistant|Le fichier demand&eacute; n\'a pas &eacute;t&eacute; trouv&eacute;'
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = True
+ self.limitDL = 5
+ self.chunkLimit = 1
+
+
+ def init(self):
+ factory = self.core.requestFactory
+ self.req = CustomBrowser(factory.bucket, factory.getOptions())
+
+
+ def process(self, pyfile):
+ pyfile.url = replace_patterns(pyfile.url, self.URL_REPLACEMENTS)
+ valid_url = pyfile.url
+ headers = self.load(valid_url, just_header=True)
+
+ if headers.get('code') == 302:
+ valid_url = headers.get('location')
+ headers = self.load(valid_url, just_header=True)
+
+ if headers.get('code') == 200:
+ content_type = headers.get('content-type')
+ if content_type and content_type.startswith("text/html"):
+ # Undirect acces to requested file, with a web page providing it (captcha)
+ self.html = self.load(valid_url)
+ self.handleFree(pyfile)
+ else:
+ # Direct access to requested file for users using free.fr as Internet Service Provider.
+ self.link = valid_url
+
+ elif headers.get('code') == 404:
+ self.offline()
+
+ else:
+ self.fail(_("Invalid return code: ") + str(headers.get('code')))
+
+
+ def handleFree(self, pyfile):
+ action, inputs = self.parseHtmlForm('action="getfile.pl"')
+
+ adyoulike = AdYouLike(self)
+ response, challenge = adyoulike.challenge()
+ inputs.update(response)
+
+ self.load("http://dl.free.fr/getfile.pl", post=inputs)
+ headers = self.getLastHeaders()
+ if headers.get("code") == 302 and "set-cookie" in headers and "location" in headers:
+ m = re.search("(.*?)=(.*?); path=(.*?); domain=(.*?)", headers.get("set-cookie"))
+ cj = CookieJar(__name__)
+ if m:
+ cj.setCookie(m.group(4), m.group(1), m.group(2), m.group(3))
+ else:
+ self.fail(_("Cookie error"))
+
+ self.link = headers.get("location")
+
+ self.req.setCookieJar(cj)
+ else:
+ self.fail(_("Invalid response"))
+
+
+ def getLastHeaders(self):
+ #parse header
+ header = {"code": self.req.code}
+ for line in self.req.http.header.splitlines():
+ line = line.strip()
+ if not line or ":" not in line:
+ continue
+
+ key, none, value = line.partition(":")
+ key = key.lower().strip()
+ value = value.strip()
+
+ if key in header:
+ if type(header[key]) == list:
+ header[key].append(value)
+ else:
+ header[key] = [header[key], value]
+ else:
+ header[key] = value
+ return header
diff --git a/pyload/plugin/hoster/DodanePl.py b/pyload/plugin/hoster/DodanePl.py
new file mode 100644
index 000000000..35fa1ecab
--- /dev/null
+++ b/pyload/plugin/hoster/DodanePl.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class DodanePl(DeadHoster):
+ __name__ = "DodanePl"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?dodane\.pl/file/\d+'
+
+ __description__ = """Dodane.pl hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("z00nx", "z00nx0@gmail.com")]
diff --git a/pyload/plugin/hoster/DuploadOrg.py b/pyload/plugin/hoster/DuploadOrg.py
new file mode 100644
index 000000000..db00c46e9
--- /dev/null
+++ b/pyload/plugin/hoster/DuploadOrg.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class DuploadOrg(DeadHoster):
+ __name__ = "DuploadOrg"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?dupload\.org/\w{12}'
+
+ __description__ = """Dupload.grg hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
diff --git a/pyload/plugin/hoster/EasybytezCom.py b/pyload/plugin/hoster/EasybytezCom.py
new file mode 100644
index 000000000..07e75714d
--- /dev/null
+++ b/pyload/plugin/hoster/EasybytezCom.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class EasybytezCom(XFSHoster):
+ __name__ = "EasybytezCom"
+ __type__ = "hoster"
+ __version__ = "0.23"
+
+ __pattern__ = r'http://(?:www\.)?easybytez\.com/\w{12}'
+
+ __description__ = """Easybytez.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
+ ("stickell", "l.stickell@yahoo.it")]
+
+
+ OFFLINE_PATTERN = r'>File not available'
+
+ LINK_PATTERN = r'(http://(\w+\.(easybytez|easyload|ezbytez|zingload)\.(com|to)|\d+\.\d+\.\d+\.\d+)/files/\d+/\w+/.+?)["\'<]'
diff --git a/pyload/plugin/hoster/EdiskCz.py b/pyload/plugin/hoster/EdiskCz.py
new file mode 100644
index 000000000..7aaef10ae
--- /dev/null
+++ b/pyload/plugin/hoster/EdiskCz.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class EdiskCz(SimpleHoster):
+ __name__ = "EdiskCz"
+ __type__ = "hoster"
+ __version__ = "0.23"
+
+ __pattern__ = r'http://(?:www\.)?edisk\.(cz|sk|eu)/(stahni|sk/stahni|en/download)/.+'
+
+ __description__ = """Edisk.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ INFO_PATTERN = r'<span class="fl" title="(?P<N>[^"]+)">\s*.*?\((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)</h1></span>'
+ OFFLINE_PATTERN = r'<h3>This file does not exist due to one of the following:</h3><ul><li>'
+
+ ACTION_PATTERN = r'/en/download/(\d+/.*\.html)'
+ LINK_FREE_PATTERN = r'http://.*edisk\.cz.*\.html'
+
+
+ def setup(self):
+ self.multiDL = False
+
+
+ def process(self, pyfile):
+ url = re.sub("/(stahni|sk/stahni)/", "/en/download/", pyfile.url)
+
+ self.logDebug("URL:" + url)
+
+ m = re.search(self.ACTION_PATTERN, url)
+ if m is None:
+ self.error(_("ACTION_PATTERN not found"))
+ action = m.group(1)
+
+ self.html = self.load(url, decode=True)
+ self.getFileInfo()
+
+ self.html = self.load(re.sub("/en/download/", "/en/download-slow/", url))
+
+ url = self.load(re.sub("/en/download/", "/x-download/", url), post={
+ "action": action
+ })
+
+ if not re.match(self.LINK_FREE_PATTERN, url):
+ self.fail(_("Unexpected server response"))
+
+ self.download(url)
diff --git a/pyload/plugin/hoster/EgoFilesCom.py b/pyload/plugin/hoster/EgoFilesCom.py
new file mode 100644
index 000000000..a843f5051
--- /dev/null
+++ b/pyload/plugin/hoster/EgoFilesCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class EgoFilesCom(DeadHoster):
+ __name__ = "EgoFilesCom"
+ __type__ = "hoster"
+ __version__ = "0.16"
+
+ __pattern__ = r'https?://(?:www\.)?egofiles\.com/\w+'
+
+ __description__ = """Egofiles.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
diff --git a/pyload/plugin/hoster/EnteruploadCom.py b/pyload/plugin/hoster/EnteruploadCom.py
new file mode 100644
index 000000000..efec5b37c
--- /dev/null
+++ b/pyload/plugin/hoster/EnteruploadCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class EnteruploadCom(DeadHoster):
+ __name__ = "EnteruploadCom"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?enterupload\.com/\w+'
+
+ __description__ = """EnterUpload.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/EpicShareNet.py b/pyload/plugin/hoster/EpicShareNet.py
new file mode 100644
index 000000000..16685088a
--- /dev/null
+++ b/pyload/plugin/hoster/EpicShareNet.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class EpicShareNet(DeadHoster):
+ __name__ = "EpicShareNet"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'https?://(?:www\.)?epicshare\.net/\w{12}'
+
+ __description__ = """EpicShare.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("t4skforce", "t4skforce1337[AT]gmail[DOT]com")]
diff --git a/pyload/plugin/hoster/EuroshareEu.py b/pyload/plugin/hoster/EuroshareEu.py
new file mode 100644
index 000000000..84fbcda08
--- /dev/null
+++ b/pyload/plugin/hoster/EuroshareEu.py
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class EuroshareEu(SimpleHoster):
+ __name__ = "EuroshareEu"
+ __type__ = "hoster"
+ __version__ = "0.27"
+
+ __pattern__ = r'http://(?:www\.)?euroshare\.(eu|sk|cz|hu|pl)/file/.+'
+
+ __description__ = """Euroshare.eu hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ INFO_PATTERN = r'<span style="float: left;"><strong>(?P<N>.+?)</strong> \((?P<S>.+?)\)</span>'
+ OFFLINE_PATTERN = ur'<h2>S.bor sa nena.iel</h2>|Poşadovaná stránka neexistuje!'
+
+ LINK_FREE_PATTERN = r'<a href="(/file/\d+/[^/]*/download/)"><div class="downloadButton"'
+
+ ERR_PARDL_PATTERN = r'<h2>Prebieha s.ahovanie</h2>|<p>Naraz je z jednej IP adresy mo.n. s.ahova. iba jeden s.bor'
+ ERR_NOT_LOGGED_IN_PATTERN = r'href="/customer-zone/login/"'
+
+ URL_REPLACEMENTS = [(r"(http://[^/]*\.)(sk|cz|hu|pl)/", r"\1eu/")]
+
+
+ def handlePremium(self, pyfile):
+ if self.ERR_NOT_LOGGED_IN_PATTERN in self.html:
+ self.account.relogin(self.user)
+ self.retry(reason=_("User not logged in"))
+
+ self.download(pyfile.url.rstrip('/') + "/download/")
+
+ check = self.checkDownload({"login": re.compile(self.ERR_NOT_LOGGED_IN_PATTERN),
+ "json" : re.compile(r'\{"status":"error".*?"message":"(.*?)"')})
+
+ if check == "login" or (check == "json" and self.lastCheck.group(1) == "Access token expired"):
+ self.account.relogin(self.user)
+ self.retry(reason=_("Access token expired"))
+
+ elif check == "json":
+ self.fail(self.lastCheck.group(1))
+
+
+ def handleFree(self, pyfile):
+ if re.search(self.ERR_PARDL_PATTERN, self.html) is not None:
+ self.longWait(5 * 60, 12)
+
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("LINK_FREE_PATTERN not found"))
+
+ self.link = "http://euroshare.eu%s" % m.group(1)
+
+
+ def checkFile(self):
+ if self.checkDownload({"multi-dl": re.compile(self.ERR_PARDL_PATTERN)})
+ self.longWait(5 * 60, 12)
+
+ return super(EuroshareEu, self).checkFile()
diff --git a/pyload/plugin/hoster/ExashareCom.py b/pyload/plugin/hoster/ExashareCom.py
new file mode 100644
index 000000000..504eef334
--- /dev/null
+++ b/pyload/plugin/hoster/ExashareCom.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class ExashareCom(XFSHoster):
+ __name__ = "ExashareCom"
+ __type__ = "hoster"
+ __version__ = "0.01"
+
+ __pattern__ = r'http://(?:www\.)?exashare\.com/\w{12}'
+
+ __description__ = """Exashare.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ INFO_PATTERN = r'>(?P<NAME>.+?)<small>\( (?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+ LINK_FREE_PATTERN = r'file: "(.+?)"'
+
+
+ def setup(self):
+ self.multiDL = True
+ self.chunkLimit = 1
+ self.resumeDownload = self.premium
+
+
+ def handleFree(self, pyfile):
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("Free download link not found"))
+ else:
+ self.link = m.group(1)
diff --git a/pyload/plugin/hoster/ExtabitCom.py b/pyload/plugin/hoster/ExtabitCom.py
new file mode 100644
index 000000000..d5c1f0ba4
--- /dev/null
+++ b/pyload/plugin/hoster/ExtabitCom.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.utils import json_loads
+
+from pyload.plugin.internal.CaptchaService import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster, secondsToMidnight
+
+
+class ExtabitCom(SimpleHoster):
+ __name__ = "ExtabitCom"
+ __type__ = "hoster"
+ __version__ = "0.65"
+
+ __pattern__ = r'http://(?:www\.)?extabit\.com/(file|go|fid)/(?P<ID>\w+)'
+
+ __description__ = """Extabit.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<th>File:</th>\s*<td class="col-fileinfo">\s*<div title="(?P<N>[^"]+)">'
+ SIZE_PATTERN = r'<th>Size:</th>\s*<td class="col-fileinfo">(?P<S>[^<]+)</td>'
+ OFFLINE_PATTERN = r'>File not found<'
+ TEMP_OFFLINE_PATTERN = r'>(File is temporary unavailable|No download mirror)<'
+
+ LINK_FREE_PATTERN = r'[\'"](http://guest\d+\.extabit\.com/\w+/.*?)[\'"]'
+
+
+ def handleFree(self, pyfile):
+ if r">Only premium users can download this file" in self.html:
+ self.fail(_("Only premium users can download this file"))
+
+ m = re.search(r"Next free download from your ip will be available in <b>(\d+)\s*minutes", self.html)
+ if m:
+ self.wait(int(m.group(1)) * 60, True)
+ elif "The daily downloads limit from your IP is exceeded" in self.html:
+ self.logWarning(_("You have reached your daily downloads limit for today"))
+ self.wait(secondsToMidnight(gmt=2), True)
+
+ self.logDebug("URL: " + self.req.http.lastEffectiveURL)
+ m = re.match(self.__pattern__, self.req.http.lastEffectiveURL)
+ fileID = m.group('ID') if m else self.info['pattern']['ID']
+
+ m = re.search(r'recaptcha/api/challenge\?k=(\w+)', self.html)
+ if m:
+ recaptcha = ReCaptcha(self)
+ captcha_key = m.group(1)
+
+ for _i in xrange(5):
+ get_data = {"type": "recaptcha"}
+ get_data['capture'], get_data['challenge'] = recaptcha.challenge(captcha_key)
+ res = json_loads(self.load("http://extabit.com/file/%s/" % fileID, get=get_data))
+ if "ok" in res:
+ self.correctCaptcha()
+ break
+ else:
+ self.invalidCaptcha()
+ else:
+ self.fail(_("Invalid captcha"))
+ else:
+ self.error(_("Captcha"))
+
+ if not "href" in res:
+ self.error(_("Bad JSON response"))
+
+ self.html = self.load("http://extabit.com/file/%s%s" % (fileID, res['href']))
+
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("LINK_FREE_PATTERN not found"))
+
+ url = m.group(1)
+ self.download(url)
diff --git a/pyload/plugin/hoster/FastixRu.py b/pyload/plugin/hoster/FastixRu.py
new file mode 100644
index 000000000..129259304
--- /dev/null
+++ b/pyload/plugin/hoster/FastixRu.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from random import randrange
+from urllib import unquote
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHoster import MultiHoster
+
+
+class FastixRu(MultiHoster):
+ __name__ = "FastixRu"
+ __type__ = "hoster"
+ __version__ = "0.09"
+
+ __pattern__ = r'http://(?:www\.)?fastix\.(ru|it)/file/\w{24}'
+
+ __description__ = """Fastix multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Massimo Rosamilia", "max@spiritix.eu")]
+
+
+ def getFilename(self, url):
+ try:
+ name = unquote(url.rsplit("/", 1)[1])
+ except IndexError:
+ name = "Unknown_Filename..."
+ if name.endswith("..."): # incomplete filename, append random stuff
+ name += "%s.tmp" % randrange(100, 999)
+ return name
+
+
+ def setup(self):
+ self.chunkLimit = 3
+
+
+ def handlePremium(self, pyfile):
+ api_key = self.account.getAccountData(self.user)
+ api_key = api_key['api']
+
+ self.html = self.load("http://fastix.ru/api_v2/",
+ get={'apikey': api_key, 'sub': "getdirectlink", 'link': pyfile.url})
+
+ data = json_loads(self.html)
+
+ self.logDebug("Json data", data)
+
+ if "error\":true" in self.html:
+ self.offline()
+ else:
+ self.link = data['downloadlink']
+
+ if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown"):
+ #only use when name wasnt already set
+ pyfile.name = self.getFilename(self.link)
+
+
+ def checkFile(self):
+ if self.checkDownload({"error": "<title>An error occurred while processing your request</title>"}):
+ self.retry(wait_time=60, reason=_("An error occurred while generating link"))
+
+ return super(FastixRu, self).checkFile()
diff --git a/pyload/plugin/hoster/FastshareCz.py b/pyload/plugin/hoster/FastshareCz.py
new file mode 100644
index 000000000..4baa362c3
--- /dev/null
+++ b/pyload/plugin/hoster/FastshareCz.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urlparse import urljoin
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class FastshareCz(SimpleHoster):
+ __name__ = "FastshareCz"
+ __type__ = "hoster"
+ __version__ = "0.27"
+
+ __pattern__ = r'http://(?:www\.)?fastshare\.cz/\d+/.+'
+
+ __description__ = """FastShare.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+ URL_REPLACEMENTS = [("#.*", "")]
+
+ COOKIES = [("fastshare.cz", "lang", "en")]
+
+ INFO_PATTERN = r'<h1 class="dwp">(?P<N>[^<]+)</h1>\s*<div class="fileinfo">\s*Size\s*: (?P<S>\d+) (?P<U>[\w^_]+),'
+ OFFLINE_PATTERN = r'>(The file has been deleted|Requested page not found)'
+
+ LINK_FREE_PATTERN = r'action=(/free/.*?)>\s*<img src="([^"]*)"><br'
+ LINK_PREMIUM_PATTERN = r'(http://data\d+\.fastshare\.cz/download\.php\?id=\d+&)'
+
+ SLOT_ERROR = "> 100% of FREE slots are full"
+ CREDIT_ERROR = " credit for "
+
+
+ def checkErrors(self):
+ if self.SLOT_ERROR in self.html:
+ errmsg = self.info['error'] = _("No free slots")
+ self.retry(12, 60, errmsg)
+
+ if self.CREDIT_ERROR in self.html:
+ errmsg = self.info['error'] = _("Not enough traffic left")
+ self.logWarning(errmsg)
+ self.resetAccount()
+
+ self.info.pop('error', None)
+
+
+ def handleFree(self, pyfile):
+ m = re.search(self.FREE_URL_PATTERN, self.html)
+ if m:
+ action, captcha_src = m.groups()
+ else:
+ self.error(_("FREE_URL_PATTERN not found"))
+
+ baseurl = "http://www.fastshare.cz"
+ captcha = self.decryptCaptcha(urljoin(baseurl, captcha_src))
+ self.download(urljoin(baseurl, action), post={'code': captcha, 'btn.x': 77, 'btn.y': 18})
+
+
+ def checkFile(self):
+ check = self.checkDownload({
+ 'paralell-dl' : re.compile(r"<title>FastShare.cz</title>|<script>alert\('Pres FREE muzete stahovat jen jeden soubor najednou.'\)"),
+ 'wrong captcha': re.compile(r'Download for FREE'),
+ 'credit' : re.compile(self.CREDIT_ERROR)
+ })
+
+ if check == "paralell-dl":
+ self.retry(6, 10 * 60, _("Paralell download"))
+
+ elif check == "wrong captcha":
+ self.retry(max_tries=5, reason=_("Wrong captcha"))
+
+ elif check == "credit":
+ self.resetAccount()
+
+ return super(FastshareCz, self).checkFile()
diff --git a/pyload/plugin/hoster/FileApeCom.py b/pyload/plugin/hoster/FileApeCom.py
new file mode 100644
index 000000000..2c39e314c
--- /dev/null
+++ b/pyload/plugin/hoster/FileApeCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class FileApeCom(DeadHoster):
+ __name__ = "FileApeCom"
+ __type__ = "hoster"
+ __version__ = "0.12"
+
+ __pattern__ = r'http://(?:www\.)?fileape\.com/(index\.php\?act=download\&id=|dl/)\w+'
+
+ __description__ = """FileApe.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("espes", "")]
diff --git a/pyload/plugin/hoster/FileSharkPl.py b/pyload/plugin/hoster/FileSharkPl.py
new file mode 100644
index 000000000..24b1db6de
--- /dev/null
+++ b/pyload/plugin/hoster/FileSharkPl.py
@@ -0,0 +1,130 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urlparse import urljoin
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class FileSharkPl(SimpleHoster):
+ __name__ = "FileSharkPl"
+ __type__ = "hoster"
+ __version__ = "0.07"
+
+ __pattern__ = r'http://(?:www\.)?fileshark\.pl/pobierz/\d+/\w+'
+
+ __description__ = """FileShark.pl hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("prOq", ""),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ NAME_PATTERN = r'<h2 class="name-file">(?P<N>.+)</h2>'
+ SIZE_PATTERN = r'<p class="size-file">(.*?)<strong>(?P<S>\d+\.?\d*)\s(?P<U>\w+)</strong></p>'
+
+ OFFLINE_PATTERN = '(P|p)lik zosta. (usuni.ty|przeniesiony)'
+
+ LINK_FREE_PATTERN = r'<a href="(.*?)" class="btn-upload-free">'
+ LINK_PREMIUM_PATTERN = r'<a href="(.*?)" class="btn-upload-premium">'
+
+ WAIT_PATTERN = r'var timeToDownload = (\d+);'
+ ERROR_PATTERN = r'<p class="lead text-center alert alert-warning">(.*?)</p>'
+ IP_ERROR_PATTERN = r'Strona jest dost.pna wy..cznie dla u.ytkownik.w znajduj.cych si. na terenie Polski'
+ SLOT_ERROR_PATTERN = r'Osi.gni.to maksymaln. liczb. .ci.ganych jednocze.nie plik.w\.'
+
+ CAPTCHA_PATTERN = '<img src="data:image/jpeg;base64,(.*?)" title="captcha"'
+ TOKEN_PATTERN = r'name="form\[_token\]" value="(.*?)" />'
+
+
+ def setup(self):
+ self.resumeDownload = True
+
+ if self.premium:
+ self.multiDL = True
+ self.limitDL = 20
+ else:
+ self.multiDL = False
+
+
+ def checkErrors(self):
+ # check if file is now available for download (-> file name can be found in html body)
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m:
+ errmsg = self.info['error'] = _("Another download already run")
+ self.retry(15, int(m.group(1)), errmsg)
+
+ m = re.search(self.ERROR_PATTERN, self.html)
+ if m:
+ alert = m.group(1)
+
+ if re.match(self.IP_ERROR_PATTERN, alert):
+ self.fail(_("Only connections from Polish IP are allowed"))
+
+ elif re.match(self.SLOT_ERROR_PATTERN, alert):
+ errmsg = self.info['error'] = _("No free download slots available")
+ self.logWarning(errmsg)
+ self.retry(10, 30 * 60, _("Still no free download slots available"))
+
+ else:
+ self.info['error'] = alert
+ self.retry(10, 10 * 60, _("Try again later"))
+
+ self.info.pop('error', None)
+
+
+ def handleFree(self, pyfile):
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("Download url not found"))
+
+ link = urljoin("http://fileshark.pl", m.group(1))
+
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m:
+ seconds = int(m.group(1))
+ self.logDebug("Wait %s seconds" % seconds)
+ self.wait(seconds)
+
+ action, inputs = self.parseHtmlForm('action=""')
+
+ m = re.search(self.TOKEN_PATTERN, self.html)
+ if m is None:
+ self.retry(reason=_("Captcha form not found"))
+
+ inputs['form[_token]'] = m.group(1)
+
+ m = re.search(self.CAPTCHA_PATTERN, self.html)
+ if m is None:
+ self.retry(reason=_("Captcha image not found"))
+
+ tmp_load = self.load
+ self.load = self._decode64 #: work-around: injects decode64 inside decryptCaptcha
+
+ inputs['form[captcha]'] = self.decryptCaptcha(m.group(1), imgtype='jpeg')
+ inputs['form[start]'] = ""
+
+ self.load = tmp_load
+
+ self.download(link, post=inputs, cookies=True, disposition=True)
+
+
+ def checkFile(self):
+ check = self.checkDownload({'wrong_captcha': re.compile(r'<label for="form_captcha" generated="true" class="error">(.*?)</label>'),
+ 'wait_pattern' : re.compile(self.SECONDS_PATTERN),
+ 'DL-found' : re.compile('<a href="(.*)">')})
+ if check == "DL-found":
+ self.correctCaptcha()
+
+ elif check == "wrong_captcha":
+ self.invalidCaptcha()
+ self.retry(10, 1, _("Wrong captcha solution"))
+
+ elif check == "wait_pattern":
+ self.retry()
+
+ return super(FileSharkPl, self).checkFile()
+
+
+ def _decode64(self, data, *args, **kwargs):
+ return data.decode('base64')
diff --git a/pyload/plugin/hoster/FileStoreTo.py b/pyload/plugin/hoster/FileStoreTo.py
new file mode 100644
index 000000000..8998c0b1c
--- /dev/null
+++ b/pyload/plugin/hoster/FileStoreTo.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class FileStoreTo(SimpleHoster):
+ __name__ = "FileStoreTo"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'http://(?:www\.)?filestore\.to/\?d=(?P<ID>\w+)'
+
+ __description__ = """FileStore.to hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com"),
+ ("stickell", "l.stickell@yahoo.it")]
+
+
+ INFO_PATTERN = r'File: <span.*?>(?P<N>.+?)<.*>Size: (?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+ OFFLINE_PATTERN = r'>Download-Datei wurde nicht gefunden<'
+ TEMP_OFFLINE_PATTERN = r'>Der Download ist nicht bereit !<'
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = True
+
+
+ def handleFree(self, pyfile):
+ self.wait(10)
+ self.link = self.load("http://filestore.to/ajax/download.php",
+ get={'D': re.search(r'"D=(\w+)', self.html).group(1)})
diff --git a/pyload/plugin/hoster/FilebeerInfo.py b/pyload/plugin/hoster/FilebeerInfo.py
new file mode 100644
index 000000000..83fc6dbfc
--- /dev/null
+++ b/pyload/plugin/hoster/FilebeerInfo.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class FilebeerInfo(DeadHoster):
+ __name__ = "FilebeerInfo"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?filebeer\.info/(?!\d*~f)(?P<ID>\w+)'
+
+ __description__ = """Filebeer.info plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/FilecloudIo.py b/pyload/plugin/hoster/FilecloudIo.py
new file mode 100644
index 000000000..ae50f95bb
--- /dev/null
+++ b/pyload/plugin/hoster/FilecloudIo.py
@@ -0,0 +1,123 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class FilecloudIo(SimpleHoster):
+ __name__ = "FilecloudIo"
+ __type__ = "hoster"
+ __version__ = "0.08"
+
+ __pattern__ = r'http://(?:www\.)?(?:filecloud\.io|ifile\.it|mihd\.net)/(?P<ID>\w+)'
+
+ __description__ = """Filecloud.io hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
+ ("stickell", "l.stickell@yahoo.it")]
+
+
+ LOGIN_ACCOUNT = True
+
+ NAME_PATTERN = r'id="aliasSpan">(?P<N>.*?)&nbsp;&nbsp;<'
+ SIZE_PATTERN = r'{var __ab1 = (?P<S>\d+);}'
+ OFFLINE_PATTERN = r'l10n\.(FILES__DOESNT_EXIST|REMOVED)'
+ TEMP_OFFLINE_PATTERN = r'l10n\.FILES__WARNING'
+
+ UKEY_PATTERN = r'\'ukey\'\s*:\'(\w+)'
+ AB1_PATTERN = r'if\( __ab1 == \'(\w+)\' \)'
+
+ ERROR_MSG_PATTERN = r'var __error_msg\s*=\s*l10n\.(.*?);'
+
+ RECAPTCHA_PATTERN = r'var __recaptcha_public\s*=\s*\'(.+?)\';'
+
+ LINK_FREE_PATTERN = r'"(http://s\d+\.filecloud\.io/%s/\d+/.*?)"'
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = True
+ self.chunkLimit = 1
+
+
+ def handleFree(self, pyfile):
+ data = {"ukey": self.info['pattern']['ID']}
+
+ m = re.search(self.AB1_PATTERN, self.html)
+ if m is None:
+ self.error(_("__AB1"))
+ data['__ab1'] = m.group(1)
+
+ recaptcha = ReCaptcha(self)
+
+ m = re.search(self.RECAPTCHA_PATTERN, self.html)
+ captcha_key = m.group(1) if m else recaptcha.detect_key()
+
+ if captcha_key is None:
+ self.error(_("ReCaptcha key not found"))
+
+ response, challenge = recaptcha.challenge(captcha_key)
+ self.account.form_data = {"recaptcha_challenge_field": challenge,
+ "recaptcha_response_field" : response}
+ self.account.relogin(self.user)
+ self.retry(2)
+
+ json_url = "http://filecloud.io/download-request.json"
+ res = self.load(json_url, post=data)
+ self.logDebug(res)
+ res = json_loads(res)
+
+ if "error" in res and res['error']:
+ self.fail(res)
+
+ self.logDebug(res)
+ if res['captcha']:
+ data['ctype'] = "recaptcha"
+
+ for _i in xrange(5):
+ data['recaptcha_response'], data['recaptcha_challenge'] = recaptcha.challenge(captcha_key)
+
+ json_url = "http://filecloud.io/download-request.json"
+ res = self.load(json_url, post=data)
+ self.logDebug(res)
+ res = json_loads(res)
+
+ if "retry" in res and res['retry']:
+ self.invalidCaptcha()
+ else:
+ self.correctCaptcha()
+ break
+ else:
+ self.fail(_("Incorrect captcha"))
+
+ if res['dl']:
+ self.html = self.load('http://filecloud.io/download.html')
+
+ m = re.search(self.LINK_FREE_PATTERN % self.info['pattern']['ID'], self.html)
+ if m is None:
+ self.error(_("LINK_FREE_PATTERN not found"))
+
+ if "size" in self.info and self.info['size']:
+ self.check_data = {"size": int(self.info['size'])}
+
+ download_url = m.group(1)
+ self.download(download_url)
+ else:
+ self.fail(_("Unexpected server response"))
+
+
+ def handlePremium(self, pyfile):
+ akey = self.account.getAccountData(self.user)['akey']
+ ukey = self.info['pattern']['ID']
+ self.logDebug("Akey: %s | Ukey: %s" % (akey, ukey))
+ rep = self.load("http://api.filecloud.io/api-fetch_download_url.api",
+ post={"akey": akey, "ukey": ukey})
+ self.logDebug("FetchDownloadUrl: " + rep)
+ rep = json_loads(rep)
+ if rep['status'] == 'ok':
+ self.link = rep['download_url']
+ else:
+ self.fail(rep['message'])
diff --git a/module/plugins/hoster/FilefactoryCom.py b/pyload/plugin/hoster/FilefactoryCom.py
index 95d61cd6a..95d61cd6a 100644
--- a/module/plugins/hoster/FilefactoryCom.py
+++ b/pyload/plugin/hoster/FilefactoryCom.py
diff --git a/module/plugins/hoster/FilejungleCom.py b/pyload/plugin/hoster/FilejungleCom.py
index cd890778b..cd890778b 100644
--- a/module/plugins/hoster/FilejungleCom.py
+++ b/pyload/plugin/hoster/FilejungleCom.py
diff --git a/pyload/plugin/hoster/FileomCom.py b/pyload/plugin/hoster/FileomCom.py
new file mode 100644
index 000000000..cdfc15dd9
--- /dev/null
+++ b/pyload/plugin/hoster/FileomCom.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# http://fileom.com/gycaytyzdw3g/random.bin.html
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class FileomCom(XFSHoster):
+ __name__ = "FileomCom"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'https?://(?:www\.)?fileom\.com/\w{12}'
+
+ __description__ = """Fileom.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ NAME_PATTERN = r'Filename: <span>(?P<N>.+?)<'
+ SIZE_PATTERN = r'File Size: <span class="size">(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+
+ LINK_PATTERN = r'var url2 = \'(.+?)\';'
+
+
+ def setup(self):
+ self.multiDL = True
+ self.chunkLimit = 1
+ self.resumeDownload = self.premium
diff --git a/pyload/plugin/hoster/FilepostCom.py b/pyload/plugin/hoster/FilepostCom.py
new file mode 100644
index 000000000..8c462b5d6
--- /dev/null
+++ b/pyload/plugin/hoster/FilepostCom.py
@@ -0,0 +1,130 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from time import time
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class FilepostCom(SimpleHoster):
+ __name__ = "FilepostCom"
+ __type__ = "hoster"
+ __version__ = "0.33"
+
+ __pattern__ = r'https?://(?:www\.)?(?:filepost\.com/files|fp\.io)/(?P<ID>[^/]+)'
+
+ __description__ = """Filepost.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ INFO_PATTERN = r'<input type="text" id="url" value=\'<a href[^>]*>(?P<N>[^>]+?) - (?P<S>[\d.,]+) (?P<U>[\w^_]+)</a>\' class="inp_text"/>'
+ OFFLINE_PATTERN = r'class="error_msg_title"> Invalid or Deleted File. </div>|<div class="file_info file_info_deleted">'
+
+ PREMIUM_ONLY_PATTERN = r'members only. Please upgrade to premium|a premium membership is required to download this file'
+ RECAPTCHA_PATTERN = r'Captcha.init\({\s*key:\s*\'(.+?)\''
+ FLP_TOKEN_PATTERN = r'set_store_options\({token: \'(.+?)\''
+
+
+ def handleFree(self, pyfile):
+ m = re.search(self.FLP_TOKEN_PATTERN, self.html)
+ if m is None:
+ self.error(_("Token"))
+ flp_token = m.group(1)
+
+ m = re.search(self.RECAPTCHA_PATTERN, self.html)
+ if m is None:
+ self.error(_("Captcha key"))
+ captcha_key = m.group(1)
+
+ # Get wait time
+ get_dict = {'SID': self.req.cj.getCookie('SID'), 'JsHttpRequest': str(int(time() * 10000)) + '-xml'}
+ post_dict = {'action': 'set_download', 'token': flp_token, 'code': self.info['pattern']['ID']}
+ wait_time = int(self.getJsonResponse(get_dict, post_dict, 'wait_time'))
+
+ if wait_time > 0:
+ self.wait(wait_time)
+
+ post_dict = {"token": flp_token, "code": self.info['pattern']['ID'], "file_pass": ''}
+
+ if 'var is_pass_exists = true;' in self.html:
+ # Solve password
+ password = self.getPassword()
+
+ if password:
+ self.logInfo(_("Password protected link, trying ") + file_pass)
+
+ get_dict['JsHttpRequest'] = str(int(time() * 10000)) + '-xml'
+ post_dict['file_pass'] = file_pass
+
+ self.link = self.getJsonResponse(get_dict, post_dict, 'link')
+
+ if not self.link:
+ self.fail(_("Incorrect password"))
+ else:
+ self.fail(_("No password found"))
+
+ else:
+ # Solve recaptcha
+ recaptcha = ReCaptcha(self)
+
+ for i in xrange(5):
+ get_dict['JsHttpRequest'] = str(int(time() * 10000)) + '-xml'
+ if i:
+ post_dict['recaptcha_response_field'], post_dict['recaptcha_challenge_field'] = recaptcha.challenge(
+ captcha_key)
+ self.logDebug(u"RECAPTCHA: %s : %s : %s" % (
+ captcha_key, post_dict['recaptcha_challenge_field'], post_dict['recaptcha_response_field']))
+
+ download_url = self.getJsonResponse(get_dict, post_dict, 'link')
+ if download_url:
+ if i:
+ self.correctCaptcha()
+ break
+ elif i:
+ self.invalidCaptcha()
+
+ else:
+ self.fail(_("Invalid captcha"))
+
+ # Download
+ self.download(download_url)
+
+
+ def getJsonResponse(self, get_dict, post_dict, field):
+ res = json_loads(self.load('https://filepost.com/files/get/', get=get_dict, post=post_dict))
+
+ self.logDebug(res)
+
+ if not 'js' in res:
+ self.error(_("JSON %s 1") % field)
+
+ # i changed js_answer to res['js'] since js_answer is nowhere set.
+ # i don't know the JSON-HTTP specs in detail, but the previous author
+ # accessed res['js']['error'] as well as js_answer['error'].
+ # see the two lines commented out with "# ~?".
+ if 'error' in res['js']:
+
+ if res['js']['error'] == 'download_delay':
+ self.retry(wait_time=res['js']['params']['next_download'])
+ # ~? self.retry(wait_time=js_answer['params']['next_download'])
+
+ elif 'Wrong file password' in res['js']['error'] \
+ or 'You entered a wrong CAPTCHA code' in res['js']['error'] \
+ or 'CAPTCHA Code nicht korrekt' in res['js']['error']:
+ return None
+
+ elif 'CAPTCHA' in res['js']['error']:
+ self.logDebug("Error response is unknown, but mentions CAPTCHA")
+ return None
+
+ else:
+ self.fail(res['js']['error'])
+
+ if not 'answer' in res['js'] or not field in res['js']['answer']:
+ self.error(_("JSON %s 2") % field)
+
+ return res['js']['answer'][field]
diff --git a/pyload/plugin/hoster/FilepupNet.py b/pyload/plugin/hoster/FilepupNet.py
new file mode 100644
index 000000000..b19f40106
--- /dev/null
+++ b/pyload/plugin/hoster/FilepupNet.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# http://www.filepup.net/files/k5w4ZVoF1410184283.html
+# http://www.filepup.net/files/R4GBq9XH1410186553.html
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class FilepupNet(SimpleHoster):
+ __name__ = "FilepupNet"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?filepup\.net/files/\w+'
+
+ __description__ = """Filepup.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ NAME_PATTERN = r'>(?P<N>.+?)</h1>'
+ SIZE_PATTERN = r'class="fa fa-archive"></i> \((?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+
+ OFFLINE_PATTERN = r'>This file has been deleted'
+
+ LINK_FREE_PATTERN = r'(http://www\.filepup\.net/get/.+?)\''
+
+
+ def setup(self):
+ self.multiDL = False
+ self.chunkLimit = 1
+
+
+ def handleFree(self, pyfile):
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("Download link not found"))
+
+ dl_link = m.group(1)
+ self.download(dl_link, post={'task': "download"})
diff --git a/pyload/plugin/hoster/FilerNet.py b/pyload/plugin/hoster/FilerNet.py
new file mode 100644
index 000000000..3cf4bec36
--- /dev/null
+++ b/pyload/plugin/hoster/FilerNet.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# http://filer.net/get/ivgf5ztw53et3ogd
+# http://filer.net/get/hgo14gzcng3scbvv
+
+import pycurl
+import re
+
+from urlparse import urljoin
+
+from pyload.plugin.internal.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class FilerNet(SimpleHoster):
+ __name__ = "FilerNet"
+ __type__ = "hoster"
+ __version__ = "0.16"
+
+ __pattern__ = r'https?://(?:www\.)?filer\.net/get/\w+'
+
+ __description__ = """Filer.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ INFO_PATTERN = r'<h1 class="page-header">Free Download (?P<N>\S+) <small>(?P<S>[\w.]+) (?P<U>[\w^_]+)</small></h1>'
+ OFFLINE_PATTERN = r'Nicht gefunden'
+
+ LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'href="([^"]+)">Get download</a>'
+
+
+ def checkErrors(self):
+ # Wait between downloads
+ m = re.search(r'musst du <span id="time">(\d+)</span> Sekunden warten', self.html)
+ if m:
+ errmsg = self.info['error'] = _("Wait between free downloads")
+ self.retry(wait_time=int(m.group(1)), reason=errmsg)
+
+ self.info.pop('error', None)
+
+
+ def handleFree(self, pyfile):
+ inputs = self.parseHtmlForm(input_names={'token': re.compile(r'.+')})[1]
+ if 'token' not in inputs:
+ self.error(_("Unable to detect token"))
+
+ self.html = self.load(pyfile.url, post={'token': inputs['token']}, decode=True)
+
+ inputs = self.parseHtmlForm(input_names={'hash': re.compile(r'.+')})[1]
+ if 'hash' not in inputs:
+ self.error(_("Unable to detect hash"))
+
+ recaptcha = ReCaptcha(self)
+ response, challenge = recaptcha.challenge()
+
+ #@NOTE: Work-around for v0.4.9 just_header issue
+ #@TODO: Check for v0.4.10
+ self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 0)
+ self.load(pyfile.url, post={'recaptcha_challenge_field': challenge,
+ 'recaptcha_response_field' : response,
+ 'hash' : inputs['hash']})
+ self.req.http.c.setopt(pycurl.FOLLOWLOCATION, 1)
+
+ if 'location' in self.req.http.header.lower():
+ self.link = re.search(r'location: (\S+)', self.req.http.header, re.I).group(1)
+ self.correctCaptcha()
+ else:
+ self.invalidCaptcha()
diff --git a/pyload/plugin/hoster/FilerioCom.py b/pyload/plugin/hoster/FilerioCom.py
new file mode 100644
index 000000000..9290bee84
--- /dev/null
+++ b/pyload/plugin/hoster/FilerioCom.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class FilerioCom(XFSHoster):
+ __name__ = "FilerioCom"
+ __type__ = "hoster"
+ __version__ = "0.07"
+
+ __pattern__ = r'http://(?:www\.)?(filerio\.(in|com)|filekeen\.com)/\w{12}'
+
+ __description__ = """FileRio.in hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ URL_REPLACEMENTS = [(r'filekeen\.com', "filerio.in")]
+
+ OFFLINE_PATTERN = r'>&quot;File Not Found|File has been removed'
diff --git a/module/plugins/hoster/FilesMailRu.py b/pyload/plugin/hoster/FilesMailRu.py
index 09da46b01..09da46b01 100644
--- a/module/plugins/hoster/FilesMailRu.py
+++ b/pyload/plugin/hoster/FilesMailRu.py
diff --git a/pyload/plugin/hoster/FileserveCom.py b/pyload/plugin/hoster/FileserveCom.py
new file mode 100644
index 000000000..18322fa00
--- /dev/null
+++ b/pyload/plugin/hoster/FileserveCom.py
@@ -0,0 +1,216 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.utils import json_loads
+from pyload.network.RequestFactory import getURL
+from pyload.plugin.Hoster import Hoster
+from pyload.plugin.Plugin import chunks
+from pyload.plugin.internal.CaptchaService import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import secondsToMidnight
+from pyload.utils import parseFileSize
+
+
+def checkFile(plugin, urls):
+ html = getURL(plugin.URLS[1], post={"urls": "\n".join(urls)}, decode=True)
+
+ file_info = []
+ for li in re.finditer(plugin.LINKCHECK_TR, html, re.S):
+ try:
+ cols = re.findall(plugin.LINKCHECK_TD, li.group(1))
+ if cols:
+ file_info.append((
+ cols[1] if cols[1] != '--' else cols[0],
+ parseFileSize(cols[2]) if cols[2] != '--' else 0,
+ 2 if cols[3].startswith('Available') else 1,
+ cols[0]))
+ except Exception, e:
+ continue
+
+ return file_info
+
+
+class FileserveCom(Hoster):
+ __name__ = "FileserveCom"
+ __type__ = "hoster"
+ __version__ = "0.54"
+
+ __pattern__ = r'http://(?:www\.)?fileserve\.com/file/(?P<ID>[^/]+)'
+
+ __description__ = """Fileserve.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("jeix", "jeix@hasnomail.de"),
+ ("mkaay", "mkaay@mkaay.de"),
+ ("Paul King", ""),
+ ("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ URLS = ["http://www.fileserve.com/file/", "http://www.fileserve.com/link-checker.php",
+ "http://www.fileserve.com/checkReCaptcha.php"]
+ LINKCHECK_TR = r'<tr>\s*(<td>http://www\.fileserve\.com/file/.*?)</tr>'
+ LINKCHECK_TD = r'<td>(?:<[^>]*>|&nbsp;)*([^<]*)'
+
+ CAPTCHA_KEY_PATTERN = r'var reCAPTCHA_publickey=\'(.+?)\''
+ LONG_WAIT_PATTERN = r'<li class="title">You need to wait (\d+) (\w+) to start another download\.</li>'
+ LINK_EXPIRED_PATTERN = r'Your download link has expired'
+ DAILY_LIMIT_PATTERN = r'Your daily download limit has been reached'
+ NOT_LOGGED_IN_PATTERN = r'<form (name="loginDialogBoxForm"|id="login_form")|<li><a href="/login\.php">Login</a></li>'
+
+
+ def setup(self):
+ self.resumeDownload = self.multiDL = self.premium
+ self.file_id = re.match(self.__pattern__, self.pyfile.url).group('ID')
+ self.url = "%s%s" % (self.URLS[0], self.file_id)
+
+ self.logDebug("File ID: %s URL: %s" % (self.file_id, self.url))
+
+
+ def process(self, pyfile):
+ pyfile.name, pyfile.size, status, self.url = checkFile(self, [self.url])[0]
+ if status != 2:
+ self.offline()
+ self.logDebug("File Name: %s Size: %d" % (pyfile.name, pyfile.size))
+
+ if self.premium:
+ self.handlePremium(pyfile)
+ else:
+ self.handleFree(pyfile)
+
+
+ def handleFree(self, pyfile):
+ self.html = self.load(self.url)
+ action = self.load(self.url, post={"checkDownload": "check"}, decode=True)
+ action = json_loads(action)
+ self.logDebug(action)
+
+ if "fail" in action:
+ if action['fail'] == "timeLimit":
+ self.html = self.load(self.url, post={"checkDownload": "showError", "errorType": "timeLimit"},
+ decode=True)
+
+ self.doLongWait(re.search(self.LONG_WAIT_PATTERN, self.html))
+
+ elif action['fail'] == "parallelDownload":
+ self.logWarning(_("Parallel download error, now waiting 60s"))
+ self.retry(wait_time=60, reason=_("parallelDownload"))
+
+ else:
+ self.fail(_("Download check returned: %s") % action['fail'])
+
+ elif "success" in action:
+ if action['success'] == "showCaptcha":
+ self.doCaptcha()
+ self.doTimmer()
+ elif action['success'] == "showTimmer":
+ self.doTimmer()
+
+ else:
+ self.error(_("Unknown server response"))
+
+ # show download link
+ res = self.load(self.url, post={"downloadLink": "show"}, decode=True)
+ self.logDebug("Show downloadLink response: %s" % res)
+ if "fail" in res:
+ self.error(_("Couldn't retrieve download url"))
+
+ # this may either download our file or forward us to an error page
+ self.download(self.url, post={"download": "normal"})
+ self.logDebug(self.req.http.lastEffectiveURL)
+
+ check = self.checkDownload({"expired": self.LINK_EXPIRED_PATTERN,
+ "wait" : re.compile(self.LONG_WAIT_PATTERN),
+ "limit" : self.DAILY_LIMIT_PATTERN})
+
+ if check == "expired":
+ self.logDebug("Download link was expired")
+ self.retry()
+
+ elif check == "wait":
+ self.doLongWait(self.lastCheck)
+
+ elif check == "limit":
+ self.logWarning(_("Download limited reached for today"))
+ self.setWait(secondsToMidnight(gmt=2), True)
+ self.wait()
+ self.retry()
+
+ self.thread.m.reconnecting.wait(3) # Ease issue with later downloads appearing to be in parallel
+
+
+ def doTimmer(self):
+ res = self.load(self.url, post={"downloadLink": "wait"}, decode=True)
+ self.logDebug("Wait response: %s" % res[:80])
+
+ if "fail" in res:
+ self.fail(_("Failed getting wait time"))
+
+ if self.__name__ == "FilejungleCom":
+ m = re.search(r'"waitTime":(\d+)', res)
+ if m is None:
+ self.fail(_("Cannot get wait time"))
+ wait_time = int(m.group(1))
+ else:
+ wait_time = int(res) + 3
+
+ self.setWait(wait_time)
+ self.wait()
+
+
+ def doCaptcha(self):
+ captcha_key = re.search(self.CAPTCHA_KEY_PATTERN, self.html).group(1)
+ recaptcha = ReCaptcha(self)
+
+ for _i in xrange(5):
+ response, challenge = recaptcha.challenge(captcha_key)
+ res = json_loads(self.load(self.URLS[2],
+ post={'recaptcha_challenge_field' : challenge,
+ 'recaptcha_response_field' : response,
+ 'recaptcha_shortencode_field': self.file_id}))
+ if not res['success']:
+ self.invalidCaptcha()
+ else:
+ self.correctCaptcha()
+ break
+ else:
+ self.fail(_("Invalid captcha"))
+
+
+ def doLongWait(self, m):
+ wait_time = (int(m.group(1)) * {'seconds': 1, 'minutes': 60, 'hours': 3600}[m.group(2)]) if m else 12 * 60
+ self.setWait(wait_time, True)
+ self.wait()
+ self.retry()
+
+
+ def handlePremium(self, pyfile):
+ premium_url = None
+ if self.__name__ == "FileserveCom":
+ #try api download
+ res = self.load("http://app.fileserve.com/api/download/premium/",
+ post={"username": self.user,
+ "password": self.account.getAccountData(self.user)['password'],
+ "shorten": self.file_id},
+ decode=True)
+ if res:
+ res = json_loads(res)
+ if res['error_code'] == "302":
+ premium_url = res['next']
+ elif res['error_code'] in ["305", "500"]:
+ self.tempOffline()
+ elif res['error_code'] in ["403", "605"]:
+ self.resetAccount()
+ elif res['error_code'] in ["606", "607", "608"]:
+ self.offline()
+ else:
+ self.logError(res['error_code'], res['error_message'])
+
+ self.download(premium_url or pyfile.url)
+
+ if not premium_url and self.checkDownload({"login": re.compile(self.NOT_LOGGED_IN_PATTERN)}):
+ self.account.relogin(self.user)
+ self.retry(reason=_("Not logged in"))
+
+
+def getInfo(urls):
+ for chunk in chunks(urls, 100):
+ yield checkFile(FileserveCom, chunk)
diff --git a/pyload/plugin/hoster/FileshareInUa.py b/pyload/plugin/hoster/FileshareInUa.py
new file mode 100644
index 000000000..f7855378a
--- /dev/null
+++ b/pyload/plugin/hoster/FileshareInUa.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class FileshareInUa(DeadHoster):
+ __name__ = "FileshareInUa"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'https?://(?:www\.)?fileshare\.in\.ua/\w{7}'
+
+ __description__ = """Fileshare.in.ua hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("fwannmacher", "felipe@warhammerproject.com")]
diff --git a/pyload/plugin/hoster/FilesonicCom.py b/pyload/plugin/hoster/FilesonicCom.py
new file mode 100644
index 000000000..1dee6eefd
--- /dev/null
+++ b/pyload/plugin/hoster/FilesonicCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class FilesonicCom(DeadHoster):
+ __name__ = "FilesonicCom"
+ __type__ = "hoster"
+ __version__ = "0.35"
+
+ __pattern__ = r'http://(?:www\.)?filesonic\.com/file/\w+'
+
+ __description__ = """Filesonic.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("jeix", "jeix@hasnomail.de"),
+ ("paulking", "")]
diff --git a/pyload/plugin/hoster/FilezyNet.py b/pyload/plugin/hoster/FilezyNet.py
new file mode 100644
index 000000000..deab69101
--- /dev/null
+++ b/pyload/plugin/hoster/FilezyNet.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class FilezyNet(DeadHoster):
+ __name__ = "FilezyNet"
+ __type__ = "hoster"
+ __version__ = "0.20"
+
+ __pattern__ = r'http://(?:www\.)?filezy\.net/\w{12}'
+
+ __description__ = """Filezy.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = []
diff --git a/pyload/plugin/hoster/FiredriveCom.py b/pyload/plugin/hoster/FiredriveCom.py
new file mode 100644
index 000000000..4ce47e692
--- /dev/null
+++ b/pyload/plugin/hoster/FiredriveCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class FiredriveCom(DeadHoster):
+ __name__ = "FiredriveCom"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'https?://(?:www\.)?(firedrive|putlocker)\.com/(mobile/)?(file|embed)/(?P<ID>\w+)'
+
+ __description__ = """Firedrive.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
diff --git a/module/plugins/hoster/FlyFilesNet.py b/pyload/plugin/hoster/FlyFilesNet.py
index 5aff3e811..5aff3e811 100644
--- a/module/plugins/hoster/FlyFilesNet.py
+++ b/pyload/plugin/hoster/FlyFilesNet.py
diff --git a/pyload/plugin/hoster/FourSharedCom.py b/pyload/plugin/hoster/FourSharedCom.py
new file mode 100644
index 000000000..00209f4f1
--- /dev/null
+++ b/pyload/plugin/hoster/FourSharedCom.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class FourSharedCom(SimpleHoster):
+ __name__ = "FourSharedCom"
+ __type__ = "hoster"
+ __version__ = "0.31"
+
+ __pattern__ = r'https?://(?:www\.)?4shared(\-china)?\.com/(account/)?(download|get|file|document|photo|video|audio|mp3|office|rar|zip|archive|music)/.+'
+
+ __description__ = """4Shared.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("jeix", "jeix@hasnomail.de"),
+ ("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<meta name="title" content="(?P<N>.+?)"'
+ SIZE_PATTERN = r'<span title="Size: (?P<S>[\d.,]+) (?P<U>[\w^_]+)">'
+ OFFLINE_PATTERN = r'The file link that you requested is not valid\.|This file was deleted.'
+
+ NAME_REPLACEMENTS = [(r"&#(\d+).", lambda m: unichr(int(m.group(1))))]
+ SIZE_REPLACEMENTS = [(",", "")]
+
+ DIRECT_LINK = False
+ LOGIN_ACCOUNT = True
+
+ LINK_FREE_PATTERN = r'name="d3link" value="(.*?)"'
+ LINK_BTN_PATTERN = r'id="btnLink" href="(.*?)"'
+
+ ID_PATTERN = r'name="d3fid" value="(.*?)"'
+
+
+ def handleFree(self, pyfile):
+ m = re.search(self.LINK_BTN_PATTERN, self.html)
+ if m:
+ link = m.group(1)
+ else:
+ link = re.sub(r'/(download|get|file|document|photo|video|audio)/', r'/get/', pyfile.url)
+
+ self.html = self.load(link)
+
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("Download link"))
+
+ self.link = m.group(1)
+
+ try:
+ m = re.search(self.ID_PATTERN, self.html)
+ res = self.load('http://www.4shared.com/web/d2/getFreeDownloadLimitInfo?fileId=%s' % m.group(1))
+ self.logDebug(res)
+ except Exception:
+ pass
+
+ self.wait(20)
diff --git a/pyload/plugin/hoster/FreakshareCom.py b/pyload/plugin/hoster/FreakshareCom.py
new file mode 100644
index 000000000..331d7f2a3
--- /dev/null
+++ b/pyload/plugin/hoster/FreakshareCom.py
@@ -0,0 +1,180 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.Hoster import Hoster
+from pyload.plugin.internal.CaptchaService import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import secondsToMidnight
+
+
+class FreakshareCom(Hoster):
+ __name__ = "FreakshareCom"
+ __type__ = "hoster"
+ __version__ = "0.40"
+
+ __pattern__ = r'http://(?:www\.)?freakshare\.(net|com)/files/\S*?/'
+
+ __description__ = """Freakshare.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("sitacuisses", "sitacuisses@yahoo.de"),
+ ("spoob", "spoob@pyload.org"),
+ ("mkaay", "mkaay@mkaay.de"),
+ ("Toilal", "toilal.dev@gmail.com")]
+
+
+ def setup(self):
+ self.multiDL = False
+ self.req_opts = []
+
+
+ def process(self, pyfile):
+ self.pyfile = pyfile
+
+ pyfile.url = pyfile.url.replace("freakshare.net/", "freakshare.com/")
+
+ if self.account:
+ self.html = self.load(pyfile.url, cookies=False)
+ pyfile.name = self.get_file_name()
+ self.download(pyfile.url)
+
+ else:
+ self.prepare()
+ self.get_file_url()
+
+ self.download(pyfile.url, post=self.req_opts)
+
+ check = self.checkDownload({"bad" : "bad try",
+ "paralell" : "> Sorry, you cant download more then 1 files at time. <",
+ "empty" : "Warning: Unknown: Filename cannot be empty",
+ "wrong_captcha" : "Wrong Captcha!",
+ "downloadserver": "No Downloadserver. Please try again later!"})
+
+ if check == "bad":
+ self.fail(_("Bad Try"))
+
+ elif check == "paralell":
+ self.setWait(300, True)
+ self.wait()
+ self.retry()
+
+ elif check == "empty":
+ self.fail(_("File not downloadable"))
+
+ elif check == "wrong_captcha":
+ self.invalidCaptcha()
+ self.retry()
+
+ elif check == "downloadserver":
+ self.retry(5, 15 * 60, _("No Download server"))
+
+
+ def prepare(self):
+ pyfile = self.pyfile
+
+ self.download_html()
+
+ if not self.file_exists():
+ self.offline()
+
+ self.setWait(self.get_waiting_time())
+
+ pyfile.name = self.get_file_name()
+ pyfile.size = self.get_file_size()
+
+ self.wait()
+
+ return True
+
+
+ def download_html(self):
+ self.load("http://freakshare.com/index.php", {"language": "EN"}) # Set english language in server session
+ self.html = self.load(self.pyfile.url)
+
+
+ def get_file_url(self):
+ """ returns the absolute downloadable filepath
+ """
+ if not self.html:
+ self.download_html()
+ if not self.wantReconnect:
+ self.req_opts = self.get_download_options() # get the Post options for the Request
+ #file_url = self.pyfile.url
+ #return file_url
+ else:
+ self.offline()
+
+
+ def get_file_name(self):
+ if not self.html:
+ self.download_html()
+ if not self.wantReconnect:
+ file_name = re.search(r"<h1\sclass=\"box_heading\"\sstyle=\"text-align:center;\">([^ ]+)", self.html)
+ if file_name is not None:
+ file_name = file_name.group(1)
+ else:
+ file_name = self.pyfile.url
+ return file_name
+ else:
+ return self.pyfile.url
+
+
+ def get_file_size(self):
+ size = 0
+ if not self.html:
+ self.download_html()
+ if not self.wantReconnect:
+ file_size_check = re.search(
+ r"<h1\sclass=\"box_heading\"\sstyle=\"text-align:center;\">[^ ]+ - ([^ ]+) (\w\w)yte", self.html)
+ if file_size_check is not None:
+ units = float(file_size_check.group(1).replace(",", ""))
+ pow = {'KB': 1, 'MB': 2, 'GB': 3}[file_size_check.group(2)]
+ size = int(units * 1024 ** pow)
+
+ return size
+
+
+ def get_waiting_time(self):
+ if not self.html:
+ self.download_html()
+
+ if "Your Traffic is used up for today" in self.html:
+ self.wantReconnect = True
+ return secondsToMidnight(gmt=2)
+
+ timestring = re.search('\s*var\s(?:downloadWait|time)\s=\s(\d*)[\d.]*;', self.html)
+ if timestring:
+ return int(timestring.group(1))
+ else:
+ return 60
+
+
+ def file_exists(self):
+ """ returns True or False
+ """
+ if not self.html:
+ self.download_html()
+ if re.search(r"This file does not exist!", self.html) is not None:
+ return False
+ else:
+ return True
+
+
+ def get_download_options(self):
+ re_envelope = re.search(r".*?value=\"Free\sDownload\".*?\n*?(.*?<.*?>\n*)*?\n*\s*?</form>",
+ self.html).group(0) # get the whole request
+ to_sort = re.findall(r"<input\stype=\"hidden\"\svalue=\"(.*?)\"\sname=\"(.*?)\"\s\/>", re_envelope)
+ request_options = dict((n, v) for (v, n) in to_sort)
+
+ herewego = self.load(self.pyfile.url, None, request_options) # the actual download-Page
+
+ to_sort = re.findall(r"<input\stype=\".*?\"\svalue=\"(\S*?)\".*?name=\"(\S*?)\"\s.*?\/>", herewego)
+ request_options = dict((n, v) for (v, n) in to_sort)
+
+ challenge = re.search(r"http://api\.recaptcha\.net/challenge\?k=(\w+)", herewego)
+
+ if challenge:
+ re_captcha = ReCaptcha(self)
+ (request_options['recaptcha_challenge_field'],
+ request_options['recaptcha_response_field']) = re_captcha.challenge(challenge.group(1))
+
+ return request_options
diff --git a/pyload/plugin/hoster/FreeWayMe.py b/pyload/plugin/hoster/FreeWayMe.py
new file mode 100644
index 000000000..21f99c19e
--- /dev/null
+++ b/pyload/plugin/hoster/FreeWayMe.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.MultiHoster import MultiHoster
+
+
+class FreeWayMe(MultiHoster):
+ __name__ = "FreeWayMe"
+ __type__ = "hoster"
+ __version__ = "0.16"
+
+ __pattern__ = r'https://(?:www\.)?free-way\.me/.+'
+
+ __description__ = """FreeWayMe multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Nicolas Giese", "james@free-way.me")]
+
+
+ def setup(self):
+ self.resumeDownload = False
+ self.multiDL = self.premium
+ self.chunkLimit = 1
+
+
+ def handlePremium(self, pyfile):
+ user, data = self.account.selectAccount()
+
+ for _i in xrange(5):
+ # try it five times
+ header = self.load("https://www.free-way.me/load.php",
+ get={'multiget': 7,
+ 'url' : pyfile.url,
+ 'user' : user,
+ 'pw' : self.account.getAccountData(user)['password'],
+ 'json' : ""},
+ just_header=True)
+
+ if 'location' in header:
+ headers = self.load(header['location'], just_header=True)
+ if headers['code'] == 500:
+ # error on 2nd stage
+ self.logError(_("Error [stage2]"))
+ else:
+ # seems to work..
+ self.download(header['location'])
+ break
+ else:
+ # error page first stage
+ self.logError(_("Error [stage1]"))
+
+ #@TODO: handle errors
diff --git a/pyload/plugin/hoster/FreevideoCz.py b/pyload/plugin/hoster/FreevideoCz.py
new file mode 100644
index 000000000..3c9b94ea8
--- /dev/null
+++ b/pyload/plugin/hoster/FreevideoCz.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class FreevideoCz(DeadHoster):
+ __name__ = "FreevideoCz"
+ __type__ = "hoster"
+ __version__ = "0.30"
+
+ __pattern__ = r'http://(?:www\.)?freevideo\.cz/vase-videa/.+'
+
+ __description__ = """Freevideo.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/module/plugins/hoster/FshareVn.py b/pyload/plugin/hoster/FshareVn.py
index 186cb2f87..186cb2f87 100644
--- a/module/plugins/hoster/FshareVn.py
+++ b/pyload/plugin/hoster/FshareVn.py
diff --git a/module/plugins/hoster/Ftp.py b/pyload/plugin/hoster/Ftp.py
index 6924c5910..6924c5910 100644
--- a/module/plugins/hoster/Ftp.py
+++ b/pyload/plugin/hoster/Ftp.py
diff --git a/module/plugins/hoster/GamefrontCom.py b/pyload/plugin/hoster/GamefrontCom.py
index 89e188010..89e188010 100644
--- a/module/plugins/hoster/GamefrontCom.py
+++ b/pyload/plugin/hoster/GamefrontCom.py
diff --git a/pyload/plugin/hoster/GigapetaCom.py b/pyload/plugin/hoster/GigapetaCom.py
new file mode 100644
index 000000000..9aa842e21
--- /dev/null
+++ b/pyload/plugin/hoster/GigapetaCom.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from random import randint
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class GigapetaCom(SimpleHoster):
+ __name__ = "GigapetaCom"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?gigapeta\.com/dl/\w+'
+
+ __description__ = """GigaPeta.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<img src=".*" alt="file" />-->\s*(?P<N>.*?)\s*</td>'
+ SIZE_PATTERN = r'<th>\s*Size\s*</th>\s*<td>\s*(?P<S>.*?)\s*</td>'
+ OFFLINE_PATTERN = r'<div id="page_error">'
+
+ COOKIES = [("gigapeta.com", "lang", "us")]
+
+
+ def handleFree(self, pyfile):
+ captcha_key = str(randint(1, 100000000))
+ captcha_url = "http://gigapeta.com/img/captcha.gif?x=%s" % captcha_key
+
+ for _i in xrange(5):
+ self.checkErrors()
+
+ captcha = self.decryptCaptcha(captcha_url)
+ self.html = self.load(pyfile.url,
+ post={'captcha_key': captcha_key,
+ 'captcha' : captcha,
+ 'download' : "Download"},
+ follow_location=False)
+
+ m = re.search(r'Location\s*:\s*(.+)', self.req.http.header, re.I)
+ if m:
+ download_url = m.group(1)
+ break
+ elif "Entered figures don&#96;t coincide with the picture" in self.html:
+ self.invalidCaptcha()
+ else:
+ self.fail(_("No valid captcha code entered"))
+
+ self.download(download_url)
+
+
+ def checkErrors(self):
+ if "All threads for IP" in self.html:
+ self.logDebug("Your IP is already downloading a file")
+ self.wait(5 * 60, True)
+ self.retry()
+
+ self.info.pop('error', None)
diff --git a/pyload/plugin/hoster/GooIm.py b/pyload/plugin/hoster/GooIm.py
new file mode 100644
index 000000000..2090141ca
--- /dev/null
+++ b/pyload/plugin/hoster/GooIm.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# https://goo.im/devs/liquidsmooth/3.x/codina/Nightly/LS-KK-v3.2-2014-08-01-codina.zip
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class GooIm(SimpleHoster):
+ __name__ = "GooIm"
+ __type__ = "hoster"
+ __version__ = "0.04"
+
+ __pattern__ = r'https?://(?:www\.)?goo\.im/.+'
+
+ __description__ = """Goo.im hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
+
+
+ NAME_PATTERN = r'You will be redirected to .*(?P<N>[^/ ]+) in'
+ OFFLINE_PATTERN = r'The file you requested was not found'
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = True
+
+
+ def handleFree(self, pyfile):
+ self.wait(10)
+ self.download(pyfile.url, cookies=True)
diff --git a/pyload/plugin/hoster/GoogledriveCom.py b/pyload/plugin/hoster/GoogledriveCom.py
new file mode 100644
index 000000000..14a9d058d
--- /dev/null
+++ b/pyload/plugin/hoster/GoogledriveCom.py
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*
+#
+# Test links:
+# https://drive.google.com/file/d/0B6RNTe4ygItBQm15RnJiTmMyckU/view?pli=1
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+from pyload.utils import html_unescape
+
+
+class GoogledriveCom(SimpleHoster):
+ __name__ = "GoogledriveCom"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'https?://(?:www\.)?drive\.google\.com/file/.+'
+
+ __description__ = """Drive.google.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
+
+
+ DISPOSITION = False
+
+ NAME_PATTERN = r'"og:title" content="(?P<N>.*?)">'
+ OFFLINE_PATTERN = r'align="center"><p class="errorMessage"'
+
+
+ def setup(self):
+ self.multiDL = True
+ self.resumeDownload = True
+ self.chunkLimit = 1
+
+
+ def handleFree(self, pyfile):
+ try:
+ link1 = re.search(r'"(https://docs.google.com/uc\?id.*?export=download)",',
+ self.html.decode('unicode-escape')).group(1)
+
+ except AttributeError:
+ self.error(_("Hop #1 not found"))
+
+ else:
+ self.logDebug("Next hop: %s" % link1)
+
+ self.html = self.load(link1).decode('unicode-escape')
+
+ try:
+ link2 = html_unescape(re.search(r'href="(/uc\?export=download.*?)">',
+ self.html).group(1))
+
+ except AttributeError:
+ self.error(_("Hop #2 not found"))
+
+ else:
+ self.logDebug("Next hop: %s" % link2)
+
+ link3 = self.load("https://docs.google.com" + link2, just_header=True)
+ self.logDebug("DL-Link: %s" % link3['location'])
+
+ self.link = link3['location']
diff --git a/pyload/plugin/hoster/HellshareCz.py b/pyload/plugin/hoster/HellshareCz.py
new file mode 100644
index 000000000..2caaeb143
--- /dev/null
+++ b/pyload/plugin/hoster/HellshareCz.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+
+from urlparse import urljoin
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class HellshareCz(SimpleHoster):
+ __name__ = "HellshareCz"
+ __type__ = "hoster"
+ __version__ = "0.85"
+
+ __pattern__ = r'http://(?:www\.)?hellshare\.(?:cz|com|sk|hu|pl)/[^?]*/\d+'
+
+ __description__ = """Hellshare.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ CHECK_TRAFFIC = True
+ LOGIN_ACCOUNT = True
+
+ NAME_PATTERN = r'<h1 id="filename"[^>]*>(?P<N>[^<]+)</h1>'
+ SIZE_PATTERN = r'<strong id="FileSize_master">(?P<S>[\d.,]+)&nbsp;(?P<U>[\w^_]+)</strong>'
+ OFFLINE_PATTERN = r'<h1>File not found.</h1>'
+
+ LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'<a href="([^?]+/(\d+)/\?do=(fileDownloadButton|relatedFileDownloadButton-\2)-showDownloadWindow)"'
+
+
+ def setup(self):
+ self.resumeDownload = self.multiDL = bool(self.account)
+ self.chunkLimit = 1
diff --git a/pyload/plugin/hoster/HellspyCz.py b/pyload/plugin/hoster/HellspyCz.py
new file mode 100644
index 000000000..049dd8df3
--- /dev/null
+++ b/pyload/plugin/hoster/HellspyCz.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class HellspyCz(DeadHoster):
+ __name__ = "HellspyCz"
+ __type__ = "hoster"
+ __version__ = "0.28"
+
+ __pattern__ = r'http://(?:www\.)?(?:hellspy\.(?:cz|com|sk|hu|pl)|sciagaj\.pl)(/\S+/\d+)'
+
+ __description__ = """HellSpy.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/HotfileCom.py b/pyload/plugin/hoster/HotfileCom.py
new file mode 100644
index 000000000..a9b1aa099
--- /dev/null
+++ b/pyload/plugin/hoster/HotfileCom.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class HotfileCom(DeadHoster):
+ __name__ = "HotfileCom"
+ __type__ = "hoster"
+ __version__ = "0.37"
+
+ __pattern__ = r'https?://(?:www\.)?hotfile\.com/dl/\d+/\w+'
+
+ __description__ = """Hotfile.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("sitacuisses", "sitacuisses@yhoo.de"),
+ ("spoob", "spoob@pyload.org"),
+ ("mkaay", "mkaay@mkaay.de"),
+ ("JoKoT3", "jokot3@gmail.com")]
diff --git a/pyload/plugin/hoster/HugefilesNet.py b/pyload/plugin/hoster/HugefilesNet.py
new file mode 100644
index 000000000..413191c52
--- /dev/null
+++ b/pyload/plugin/hoster/HugefilesNet.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class HugefilesNet(XFSHoster):
+ __name__ = "HugefilesNet"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'http://(?:www\.)?hugefiles\.net/\w{12}'
+
+ __description__ = """Hugefiles.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ SIZE_PATTERN = r'File Size:</span>\s*<span[^>]*>(?P<S>[^<]+)</span></div>'
+
+ FORM_INPUTS_MAP = {'ctype': re.compile(r'\d+')}
diff --git a/pyload/plugin/hoster/HundredEightyUploadCom.py b/pyload/plugin/hoster/HundredEightyUploadCom.py
new file mode 100644
index 000000000..14fe6db68
--- /dev/null
+++ b/pyload/plugin/hoster/HundredEightyUploadCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class HundredEightyUploadCom(XFSHoster):
+ __name__ = "HundredEightyUploadCom"
+ __type__ = "hoster"
+ __version__ = "0.04"
+
+ __pattern__ = r'http://(?:www\.)?180upload\.com/\w{12}'
+
+ __description__ = """180upload.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
diff --git a/pyload/plugin/hoster/IFileWs.py b/pyload/plugin/hoster/IFileWs.py
new file mode 100644
index 000000000..8effe015a
--- /dev/null
+++ b/pyload/plugin/hoster/IFileWs.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class IFileWs(DeadHoster):
+ __name__ = "IFileWs"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?ifile\.ws/\w{12}'
+
+ __description__ = """Ifile.ws hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("z00nx", "z00nx0@gmail.com")]
diff --git a/pyload/plugin/hoster/IcyFilesCom.py b/pyload/plugin/hoster/IcyFilesCom.py
new file mode 100644
index 000000000..2a5b1d55a
--- /dev/null
+++ b/pyload/plugin/hoster/IcyFilesCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class IcyFilesCom(DeadHoster):
+ __name__ = "IcyFilesCom"
+ __type__ = "hoster"
+ __version__ = "0.06"
+
+ __pattern__ = r'http://(?:www\.)?icyfiles\.com/(.+)'
+
+ __description__ = """IcyFiles.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("godofdream", "soilfiction@gmail.com")]
diff --git a/pyload/plugin/hoster/IfileIt.py b/pyload/plugin/hoster/IfileIt.py
new file mode 100644
index 000000000..58e64aff1
--- /dev/null
+++ b/pyload/plugin/hoster/IfileIt.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class IfileIt(DeadHoster):
+ __name__ = "IfileIt"
+ __type__ = "hoster"
+ __version__ = "0.29"
+
+ __pattern__ = r'^unmatchable$'
+
+ __description__ = """Ifile.it"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/IfolderRu.py b/pyload/plugin/hoster/IfolderRu.py
new file mode 100644
index 000000000..b6e98674f
--- /dev/null
+++ b/pyload/plugin/hoster/IfolderRu.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class IfolderRu(SimpleHoster):
+ __name__ = "IfolderRu"
+ __type__ = "hoster"
+ __version__ = "0.39"
+
+ __pattern__ = r'http://(?:www\.)?(?:ifolder\.ru|rusfolder\.(?:com|net|ru))/(?:files/)?(?P<ID>\d+)'
+
+ __description__ = """Ifolder.ru hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ SIZE_REPLACEMENTS = [(u'Кб', 'KB'), (u'Мб', 'MB'), (u'Гб', 'GB')]
+
+ NAME_PATTERN = ur'(?:<div><span>)?НазваМОе:(?:</span>)? <b>(?P<N>[^<]+)</b><(?:/div|br)>'
+ SIZE_PATTERN = ur'(?:<div><span>)?РазЌер:(?:</span>)? <b>(?P<S>[^<]+)</b><(?:/div|br)>'
+ OFFLINE_PATTERN = ur'<p>Ѐайл МПЌер <b>[^<]*</b> (Ме МайЎеМ|уЎалеМ) !!!</p>'
+
+ SESSION_ID_PATTERN = r'<a href=(http://ints\.(?:rusfolder\.com|ifolder\.ru)/ints/sponsor/\?bi=\d*&session=([^&]+)&u=[^>]+)>'
+ INTS_SESSION_PATTERN = r'\(\'ints_session\'\);\s*if\(tag\)\{tag\.value = "([^"]+)";\}'
+ HIDDEN_INPUT_PATTERN = r'var v = .*?name=\'(.+?)\' value=\'1\''
+
+ LINK_FREE_PATTERN = r'<a id="download_file_href" href="([^"]+)"'
+
+ WRONG_CAPTCHA_PATTERN = ur'<font color=Red>МеверМый кПЎ,<br>ввеЎОте еще раз</font><br>'
+
+
+ def setup(self):
+ self.resumeDownload = self.multiDL = bool(self.account)
+ self.chunkLimit = 1
+
+
+ def handleFree(self, pyfile):
+ self.html = self.load("http://rusfolder.com/%s" % self.info['pattern']['ID'], cookies=True, decode=True)
+ self.getFileInfo()
+
+ url = re.search(r"location\.href = '(http://ints\..*?=)'", self.html).group(1)
+ self.html = self.load(url, cookies=True, decode=True)
+
+ url, session_id = re.search(self.SESSION_ID_PATTERN, self.html).groups()
+ self.html = self.load(url, cookies=True, decode=True)
+
+ url = "http://ints.rusfolder.com/ints/frame/?session=%s" % session_id
+ self.html = self.load(url, cookies=True)
+
+ self.wait(31, False)
+
+ captcha_url = "http://ints.rusfolder.com/random/images/?session=%s" % session_id
+ for _i in xrange(5):
+ self.html = self.load(url, cookies=True)
+ action, inputs = self.parseHtmlForm('ID="Form1"')
+ inputs['ints_session'] = re.search(self.INTS_SESSION_PATTERN, self.html).group(1)
+ inputs[re.search(self.HIDDEN_INPUT_PATTERN, self.html).group(1)] = '1'
+ inputs['confirmed_number'] = self.decryptCaptcha(captcha_url, cookies=True)
+ inputs['action'] = '1'
+ self.logDebug(inputs)
+
+ self.html = self.load(url, decode=True, cookies=True, post=inputs)
+ if self.WRONG_CAPTCHA_PATTERN in self.html:
+ self.invalidCaptcha()
+ else:
+ break
+ else:
+ self.fail(_("Invalid captcha"))
+
+ self.link = re.search(self.LINK_PATTERN, self.html).group(1)
diff --git a/pyload/plugin/hoster/JumbofilesCom.py b/pyload/plugin/hoster/JumbofilesCom.py
new file mode 100644
index 000000000..fa2ffdbff
--- /dev/null
+++ b/pyload/plugin/hoster/JumbofilesCom.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class JumbofilesCom(SimpleHoster):
+ __name__ = "JumbofilesCom"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?jumbofiles\.com/(?P<ID>\w{12})'
+
+ __description__ = """JumboFiles.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("godofdream", "soilfiction@gmail.com")]
+
+
+ INFO_PATTERN = r'<TR><TD>(?P<N>[^<]+?)\s*<small>\((?P<S>[\d.,]+)\s*(?P<U>[\w^_]+)'
+ OFFLINE_PATTERN = r'Not Found or Deleted / Disabled due to inactivity or DMCA'
+ LINK_FREE_PATTERN = r'<meta http-equiv="refresh" content="10;url=(.+)">'
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = True
+
+
+ def handleFree(self, pyfile):
+ post_data = {"id": self.info['pattern']['ID'], "op": "download3", "rand": ""}
+ html = self.load(self.pyfile.url, post=post_data, decode=True)
+ self.link = re.search(self.LINK_FREE_PATTERN, html).group(1)
diff --git a/pyload/plugin/hoster/JunocloudMe.py b/pyload/plugin/hoster/JunocloudMe.py
new file mode 100644
index 000000000..4fc6457d7
--- /dev/null
+++ b/pyload/plugin/hoster/JunocloudMe.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class JunocloudMe(XFSHoster):
+ __name__ = "JunocloudMe"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'http://(?:\w+\.)?junocloud\.me/\w{12}'
+
+ __description__ = """Junocloud.me hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("guidobelix", "guidobelix@hotmail.it")]
+
+
+ URL_REPLACEMENTS = [(r'//(www\.)?junocloud', "//dl3.junocloud")]
+
+ OFFLINE_PATTERN = r'>No such file with this filename<'
+ TEMP_OFFLINE_PATTERN = r'The page may have been renamed, removed or be temporarily unavailable.<'
diff --git a/pyload/plugin/hoster/Keep2ShareCc.py b/pyload/plugin/hoster/Keep2ShareCc.py
new file mode 100644
index 000000000..d655cf6ba
--- /dev/null
+++ b/pyload/plugin/hoster/Keep2ShareCc.py
@@ -0,0 +1,109 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urlparse import urljoin
+
+from pyload.plugin.internal.CaptchaService import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class Keep2ShareCc(SimpleHoster):
+ __name__ = "Keep2ShareCc"
+ __type__ = "hoster"
+ __version__ = "0.21"
+
+ __pattern__ = r'https?://(?:www\.)?(keep2share|k2s|keep2s)\.cc/file/(?P<ID>\w+)'
+
+ __description__ = """Keep2Share.cc hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ URL_REPLACEMENTS = [(__pattern__ + ".*", "http://k2s.cc/file/\g<ID>")]
+
+ NAME_PATTERN = r'File: <span>(?P<N>.+)</span>'
+ SIZE_PATTERN = r'Size: (?P<S>[^<]+)</div>'
+
+ OFFLINE_PATTERN = r'File not found or deleted|Sorry, this file is blocked or deleted|Error 404'
+ TEMP_OFFLINE_PATTERN = r'Downloading blocked due to'
+
+ LINK_FREE_PATTERN = r'"([^"]+url.html?file=.+?)"|window\.location\.href = \'(.+?)\';'
+ LINK_PREMIUM_PATTERN = r'window\.location\.href = \'(.+?)\';'
+
+ CAPTCHA_PATTERN = r'src="(/file/captcha\.html.+?)"'
+
+ WAIT_PATTERN = r'Please wait ([\d:]+) to download this file'
+ TEMP_ERROR_PATTERN = r'>\s*(Download count files exceed|Traffic limit exceed|Free account does not allow to download more than one file at the same time)'
+ ERROR_PATTERN = r'>\s*(Free user can\'t download large files|You no can access to this file|This download available only for premium users|This is private file)'
+
+
+ def checkErrors(self):
+ m = re.search(self.TEMP_ERROR_PATTERN, self.html)
+ if m:
+ self.info['error'] = m.group(1)
+ self.wantReconnect = True
+ self.retry(wait_time=30 * 60, reason=m.group(0))
+
+ m = re.search(self.ERROR_PATTERN, self.html)
+ if m:
+ errmsg = self.info['error'] = m.group(1)
+ self.error(errmsg)
+
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m:
+ self.logDebug("Hoster told us to wait for %s" % m.group(1))
+
+ # string to time convert courtesy of https://stackoverflow.com/questions/10663720
+ ftr = [3600, 60, 1]
+ wait_time = sum(a * b for a, b in zip(ftr, map(int, m.group(1).split(':'))))
+
+ self.wantReconnect = True
+ self.retry(wait_time=wait_time, reason="Please wait to download this file")
+
+ self.info.pop('error', None)
+
+
+ def handleFree(self, pyfile):
+ self.fid = re.search(r'<input type="hidden" name="slow_id" value="([^"]+)">', self.html).group(1)
+ self.html = self.load(pyfile.url, post={'yt0': '', 'slow_id': self.fid})
+
+ self.checkErrors()
+
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+
+ if m is None:
+ self.handleCaptcha()
+
+ self.wait(30)
+
+ self.html = self.load(pyfile.url)
+
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("Free download link not found"))
+
+ self.link = m.group(1)
+ def handleCaptcha(self):
+ recaptcha = ReCaptcha(self)
+ post_data = {'free' : 1,
+ 'freeDownloadRequest': 1,
+ 'uniqueId' : self.fid,
+ 'yt0' : ''}
+
+ m = re.search(self.CAPTCHA_PATTERN, self.html)
+ if m:
+ captcha_url = urljoin("http://k2s.cc/", m.group(1))
+ post_data['CaptchaForm[code]'] = self.decryptCaptcha(captcha_url)
+ else:
+ response, challenge = recaptcha.challenge()
+ post_data.update({'recaptcha_challenge_field': challenge,
+ 'recaptcha_response_field' : response})
+
+ self.html = self.load(self.pyfile.url, post=post_data)
+
+ if 'verification code is incorrect' not in self.html:
+ self.correctCaptcha()
+ else:
+ self.invalidCaptcha()
diff --git a/pyload/plugin/hoster/KickloadCom.py b/pyload/plugin/hoster/KickloadCom.py
new file mode 100644
index 000000000..5079570af
--- /dev/null
+++ b/pyload/plugin/hoster/KickloadCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class KickloadCom(DeadHoster):
+ __name__ = "KickloadCom"
+ __type__ = "hoster"
+ __version__ = "0.21"
+
+ __pattern__ = r'http://(?:www\.)?kickload\.com/get/.+'
+
+ __description__ = """Kickload.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("mkaay", "mkaay@mkaay.de")]
diff --git a/pyload/plugin/hoster/KingfilesNet.py b/pyload/plugin/hoster/KingfilesNet.py
new file mode 100644
index 000000000..ad856dfb6
--- /dev/null
+++ b/pyload/plugin/hoster/KingfilesNet.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.captcha import SolveMedia
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class KingfilesNet(SimpleHoster):
+ __name__ = "KingfilesNet"
+ __type__ = "hoster"
+ __version__ = "0.07"
+
+ __pattern__ = r'http://(?:www\.)?kingfiles\.net/(?P<ID>\w{12})'
+
+ __description__ = """Kingfiles.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ NAME_PATTERN = r'name="fname" value="(?P<N>.+?)">'
+ SIZE_PATTERN = r'>Size: .+?">(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+
+ OFFLINE_PATTERN = r'>(File Not Found</b><br><br>|File Not Found</h2>)'
+
+ RAND_ID_PATTERN = r'type=\"hidden\" name=\"rand\" value=\"(.+)\">'
+
+ LINK_FREE_PATTERN = r'var download_url = \'(.+)\';'
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = True
+
+
+ def handleFree(self, pyfile):
+ # Click the free user button
+ post_data = {'op' : "download1",
+ 'usr_login' : "",
+ 'id' : self.info['pattern']['ID'],
+ 'fname' : pyfile.name,
+ 'referer' : "",
+ 'method_free': "+"}
+
+ self.html = self.load(pyfile.url, post=post_data, cookies=True, decode=True)
+
+ solvemedia = SolveMedia(self)
+ response, challenge = solvemedia.challenge()
+
+ # Make the downloadlink appear and load the file
+ m = re.search(self.RAND_ID_PATTERN, self.html)
+ if m is None:
+ self.error(_("Random key not found"))
+
+ rand = m.group(1)
+ self.logDebug("rand = ", rand)
+
+ post_data = {'op' : "download2",
+ 'id' : self.info['pattern']['ID'],
+ 'rand' : rand,
+ 'referer' : pyfile.url,
+ 'method_free' : "+",
+ 'method_premium' : "",
+ 'adcopy_response' : response,
+ 'adcopy_challenge': challenge,
+ 'down_direct' : "1"}
+
+ self.html = self.load(pyfile.url, post=post_data, cookies=True, decode=True)
+
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("Download url not found"))
+
+ self.link = m.group(1)
diff --git a/pyload/plugin/hoster/LemUploadsCom.py b/pyload/plugin/hoster/LemUploadsCom.py
new file mode 100644
index 000000000..deb0d374f
--- /dev/null
+++ b/pyload/plugin/hoster/LemUploadsCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class LemUploadsCom(DeadHoster):
+ __name__ = "LemUploadsCom"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'https?://(?:www\.)?lemuploads\.com/\w{12}'
+
+ __description__ = """LemUploads.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("t4skforce", "t4skforce1337[AT]gmail[DOT]com")]
diff --git a/pyload/plugin/hoster/LetitbitNet.py b/pyload/plugin/hoster/LetitbitNet.py
new file mode 100644
index 000000000..dfdae5784
--- /dev/null
+++ b/pyload/plugin/hoster/LetitbitNet.py
@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*-
+#
+# API Documentation:
+# http://api.letitbit.net/reg/static/api.pdf
+#
+# Test links:
+# http://letitbit.net/download/07874.0b5709a7d3beee2408bb1f2eefce/random.bin.html
+
+import re
+
+from urlparse import urljoin
+
+from pyload.utils import json_loads, json_dumps
+from pyload.network.RequestFactory import getURL
+from pyload.plugin.internal.CaptchaService import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster, secondsToMidnight
+
+
+def api_response(url):
+ json_data = ["yw7XQy2v9", ["download/info", {"link": url}]]
+ api_rep = getURL("http://api.letitbit.net/json",
+ post={'r': json_dumps(json_data)})
+ return json_loads(api_rep)
+
+
+def getInfo(urls):
+ for url in urls:
+ api_rep = api_response(url)
+ if api_rep['status'] == 'OK':
+ info = api_rep['data'][0]
+ yield (info['name'], info['size'], 2, url)
+ else:
+ yield (url, 0, 1, url)
+
+
+class LetitbitNet(SimpleHoster):
+ __name__ = "LetitbitNet"
+ __type__ = "hoster"
+ __version__ = "0.30"
+
+ __pattern__ = r'https?://(?:www\.)?(letitbit|shareflare)\.net/download/.+'
+
+ __description__ = """Letitbit.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
+ ("z00nx", "z00nx0@gmail.com")]
+
+
+ URL_REPLACEMENTS = [(r"(?<=http://)([^/]+)", "letitbit.net")]
+
+ SECONDS_PATTERN = r'seconds\s*=\s*(\d+);'
+ CAPTCHA_CONTROL_FIELD = r'recaptcha_control_field\s=\s\'(.+?)\''
+
+
+ def setup(self):
+ self.resumeDownload = True
+
+
+ def getFileInfo(self):
+ api_rep = api_response(self.pyfile.url)
+ if api_rep['status'] == 'OK':
+ self.api_data = api_rep['data'][0]
+ self.pyfile.name = self.api_data['name']
+ self.pyfile.size = self.api_data['size']
+ else:
+ self.offline()
+
+
+ def handleFree(self, pyfile):
+ action, inputs = self.parseHtmlForm('id="ifree_form"')
+ if not action:
+ self.error(_("ifree_form"))
+
+ pyfile.size = float(inputs['sssize'])
+ self.logDebug(action, inputs)
+ inputs['desc'] = ""
+
+ self.html = self.load(urljoin("http://letitbit.net/", action), post=inputs, cookies=True)
+
+ m = re.search(self.SECONDS_PATTERN, self.html)
+ seconds = int(m.group(1)) if m else 60
+
+ self.logDebug("Seconds found", seconds)
+
+ m = re.search(self.CAPTCHA_CONTROL_FIELD, self.html)
+ recaptcha_control_field = m.group(1)
+
+ self.logDebug("ReCaptcha control field found", recaptcha_control_field)
+
+ self.wait(seconds)
+
+ res = self.load("http://letitbit.net/ajax/download3.php", post=" ", cookies=True)
+ if res != '1':
+ self.error(_("Unknown response - ajax_check_url"))
+
+ self.logDebug(res)
+
+ recaptcha = ReCaptcha(self)
+ response, challenge = recaptcha.challenge()
+
+ post_data = {"recaptcha_challenge_field": challenge,
+ "recaptcha_response_field": response,
+ "recaptcha_control_field": recaptcha_control_field}
+
+ self.logDebug("Post data to send", post_data)
+
+ res = self.load("http://letitbit.net/ajax/check_recaptcha.php", post=post_data, cookies=True)
+
+ self.logDebug(res)
+
+ if not res:
+ self.invalidCaptcha()
+
+ if res == "error_free_download_blocked":
+ self.logWarning(_("Daily limit reached"))
+ self.wait(secondsToMidnight(gmt=2), True)
+
+ if res == "error_wrong_captcha":
+ self.invalidCaptcha()
+ self.retry()
+
+ elif res.startswith('['):
+ urls = json_loads(res)
+
+ elif res.startswith('http://'):
+ urls = [res]
+
+ else:
+ self.error(_("Unknown response - captcha check"))
+
+ self.correctCaptcha()
+
+ for download_url in urls:
+ try:
+ self.download(download_url)
+ break
+ except Exception, e:
+ self.logError(e)
+ else:
+ self.fail(_("Download did not finish correctly"))
+
+
+ def handlePremium(self, pyfile):
+ api_key = self.user
+ premium_key = self.account.getAccountData(self.user)['password']
+
+ json_data = [api_key, ["download/direct_links", {"pass": premium_key, "link": pyfile.url}]]
+ api_rep = self.load('http://api.letitbit.net/json', post={'r': json_dumps(json_data)})
+ self.logDebug("API Data: " + api_rep)
+ api_rep = json_loads(api_rep)
+
+ if api_rep['status'] == 'FAIL':
+ self.fail(api_rep['data'])
+
+ self.link = api_rep['data'][0][0]
diff --git a/pyload/plugin/hoster/LinksnappyCom.py b/pyload/plugin/hoster/LinksnappyCom.py
new file mode 100644
index 000000000..fe3104579
--- /dev/null
+++ b/pyload/plugin/hoster/LinksnappyCom.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urlparse import urlsplit
+
+from pyload.utils import json_loads, json_dumps
+from pyload.plugin.internal.MultiHoster import MultiHoster
+
+
+class LinksnappyCom(MultiHoster):
+ __name__ = "LinksnappyCom"
+ __type__ = "hoster"
+ __version__ = "0.08"
+
+ __pattern__ = r'https?://(?:[^/]+\.)?linksnappy\.com'
+
+ __description__ = """Linksnappy.com multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ SINGLE_CHUNK_HOSTERS = ["easybytez.com"]
+
+
+ def handlePremium(self, pyfile):
+ host = self._get_host(pyfile.url)
+ json_params = json_dumps({'link' : pyfile.url,
+ 'type' : host,
+ 'username': self.user,
+ 'password': self.account.getAccountData(self.user)['password']})
+
+ r = self.load("http://gen.linksnappy.com/genAPI.php",
+ post={'genLinks': json_params})
+
+ self.logDebug("JSON data: " + r)
+
+ j = json_loads(r)['links'][0]
+
+ if j['error']:
+ self.error(_("Error converting the link"))
+
+ pyfile.name = j['filename']
+ self.link = j['generated']
+
+ if host in self.SINGLE_CHUNK_HOSTERS:
+ self.chunkLimit = 1
+ else:
+ self.setup()
+
+
+ @staticmethod
+ def _get_host(url):
+ host = urlsplit(url).netloc
+ return re.search(r'[\w-]+\.\w+$', host).group(0)
diff --git a/pyload/plugin/hoster/LoadTo.py b/pyload/plugin/hoster/LoadTo.py
new file mode 100644
index 000000000..42d76b4fa
--- /dev/null
+++ b/pyload/plugin/hoster/LoadTo.py
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# http://www.load.to/JWydcofUY6/random.bin
+# http://www.load.to/oeSmrfkXE/random100.bin
+
+import re
+
+from pyload.plugin.internal.captcha import SolveMedia
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class LoadTo(SimpleHoster):
+ __name__ = "LoadTo"
+ __type__ = "hoster"
+ __version__ = "0.22"
+
+ __pattern__ = r'http://(?:www\.)?load\.to/\w+'
+
+ __description__ = """Load.to hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("halfman", "Pulpan3@gmail.com"),
+ ("stickell", "l.stickell@yahoo.it")]
+
+
+ NAME_PATTERN = r'<h1>(?P<N>.+)</h1>'
+ SIZE_PATTERN = r'Size: (?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+ OFFLINE_PATTERN = r'>Can\'t find file'
+
+ LINK_FREE_PATTERN = r'<form method="post" action="(.+?)"'
+ WAIT_PATTERN = r'type="submit" value="Download \((\d+)\)"'
+
+ URL_REPLACEMENTS = [(r'(\w)$', r'\1/')]
+
+
+ def setup(self):
+ self.multiDL = True
+ self.chunkLimit = 1
+
+
+ def handleFree(self, pyfile):
+ # Search for Download URL
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("LINK_FREE_PATTERN not found"))
+
+ download_url = m.group(1)
+
+ # Set Timer - may be obsolete
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m:
+ self.wait(m.group(1))
+
+ # Load.to is using solvemedia captchas since ~july 2014:
+ solvemedia = SolveMedia(self)
+ captcha_key = solvemedia.detect_key()
+
+ if captcha_key is None:
+ self.download(download_url)
+ else:
+ response, challenge = solvemedia.challenge(captcha_key)
+ self.download(download_url,
+ post={'adcopy_challenge': challenge,
+ 'adcopy_response' : response,
+ 'returnUrl' : pyfile.url})
diff --git a/pyload/plugin/hoster/LomafileCom.py b/pyload/plugin/hoster/LomafileCom.py
new file mode 100644
index 000000000..18f315bd6
--- /dev/null
+++ b/pyload/plugin/hoster/LomafileCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class LomafileCom(DeadHoster):
+ __name__ = "LomafileCom"
+ __type__ = "hoster"
+ __version__ = "0.52"
+
+ __pattern__ = r'http://lomafile\.com/\w{12}'
+
+ __description__ = """Lomafile.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("nath_schwarz", "nathan.notwhite@gmail.com"),
+ ("guidobelix", "guidobelix@hotmail.it")]
diff --git a/pyload/plugin/hoster/LuckyShareNet.py b/pyload/plugin/hoster/LuckyShareNet.py
new file mode 100644
index 000000000..d9cc5fe88
--- /dev/null
+++ b/pyload/plugin/hoster/LuckyShareNet.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from bottle import json_loads
+
+from pyload.plugin.internal.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class LuckyShareNet(SimpleHoster):
+ __name__ = "LuckyShareNet"
+ __type__ = "hoster"
+ __version__ = "0.06"
+
+ __pattern__ = r'https?://(?:www\.)?luckyshare\.net/(?P<ID>\d{10,})'
+
+ __description__ = """LuckyShare.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ INFO_PATTERN = r'<h1 class=\'file_name\'>(?P<N>\S+)</h1>\s*<span class=\'file_size\'>Filesize: (?P<S>[\d.,]+)(?P<U>[\w^_]+)</span>'
+ OFFLINE_PATTERN = r'There is no such file available'
+
+
+ def parseJson(self, rep):
+ if 'AJAX Error' in rep:
+ html = self.load(self.pyfile.url, decode=True)
+ m = re.search(r"waitingtime = (\d+);", html)
+ if m:
+ seconds = int(m.group(1))
+ self.logDebug("You have to wait %d seconds between free downloads" % seconds)
+ self.retry(wait_time=seconds)
+ else:
+ self.error(_("Unable to detect wait time between free downloads"))
+ elif 'Hash expired' in rep:
+ self.retry(reason=_("Hash expired"))
+ return json_loads(rep)
+
+
+ # TODO: There should be a filesize limit for free downloads
+ # TODO: Some files could not be downloaded in free mode
+ def handleFree(self, pyfile):
+ rep = self.load(r"http://luckyshare.net/download/request/type/time/file/" + self.info['pattern']['ID'], decode=True)
+
+ self.logDebug("JSON: " + rep)
+
+ json = self.parseJson(rep)
+ self.wait(json['time'])
+
+ recaptcha = ReCaptcha(self)
+
+ for _i in xrange(5):
+ response, challenge = recaptcha.challenge()
+ rep = self.load(r"http://luckyshare.net/download/verify/challenge/%s/response/%s/hash/%s" %
+ (challenge, response, json['hash']), decode=True)
+ self.logDebug("JSON: " + rep)
+ if 'link' in rep:
+ json.update(self.parseJson(rep))
+ self.correctCaptcha()
+ break
+ elif 'Verification failed' in rep:
+ self.invalidCaptcha()
+ else:
+ self.error(_("Unable to get downlaod link"))
+
+ if not json['link']:
+ self.fail(_("No Download url retrieved/all captcha attempts failed"))
+
+ self.download(json['link'])
diff --git a/module/plugins/hoster/MediafireCom.py b/pyload/plugin/hoster/MediafireCom.py
index 5adf004d0..5adf004d0 100644
--- a/module/plugins/hoster/MediafireCom.py
+++ b/pyload/plugin/hoster/MediafireCom.py
diff --git a/pyload/plugin/hoster/MegaCoNz.py b/pyload/plugin/hoster/MegaCoNz.py
new file mode 100644
index 000000000..9648e8316
--- /dev/null
+++ b/pyload/plugin/hoster/MegaCoNz.py
@@ -0,0 +1,217 @@
+# -*- coding: utf-8 -*-
+
+import os
+import random
+import re
+
+from array import array
+from base64 import standard_b64decode
+
+from Crypto.Cipher import AES
+from Crypto.Util import Counter
+# from pycurl import SSL_CIPHER_LIST
+
+from pyload.utils import json_loads, json_dumps
+from pyload.plugin.Hoster import Hoster
+from pyload.utils import decode, fs_decode, fs_encode
+
+
+############################ General errors ###################################
+# EINTERNAL (-1): An internal error has occurred. Please submit a bug report, detailing the exact circumstances in which this error occurred
+# EARGS (-2): You have passed invalid arguments to this command
+# EAGAIN (-3): (always at the request level) A temporary congestion or server malfunction prevented your request from being processed. No data was altered. Retry. Retries must be spaced with exponential backoff
+# ERATELIMIT (-4): You have exceeded your command weight per time quota. Please wait a few seconds, then try again (this should never happen in sane real-life applications)
+#
+############################ Upload errors ####################################
+# EFAILED (-5): The upload failed. Please restart it from scratch
+# ETOOMANY (-6): Too many concurrent IP addresses are accessing this upload target URL
+# ERANGE (-7): The upload file packet is out of range or not starting and ending on a chunk boundary
+# EEXPIRED (-8): The upload target URL you are trying to access has expired. Please request a fresh one
+#
+############################ Stream/System errors #############################
+# ENOENT (-9): Object (typically, node or user) not found
+# ECIRCULAR (-10): Circular linkage attempted
+# EACCESS (-11): Access violation (e.g., trying to write to a read-only share)
+# EEXIST (-12): Trying to create an object that already exists
+# EINCOMPLETE (-13): Trying to access an incomplete resource
+# EKEY (-14): A decryption operation failed (never returned by the API)
+# ESID (-15): Invalid or expired user session, please relogin
+# EBLOCKED (-16): User blocked
+# EOVERQUOTA (-17): Request over quota
+# ETEMPUNAVAIL (-18): Resource temporarily not available, please try again later
+# ETOOMANYCONNECTIONS (-19): Too many connections on this resource
+# EWRITE (-20): Write failed
+# EREAD (-21): Read failed
+# EAPPKEY (-22): Invalid application key; request not processed
+
+
+class MegaCoNz(Hoster):
+ __name__ = "MegaCoNz"
+ __type__ = "hoster"
+ __version__ = "0.26"
+
+ __pattern__ = r'(?:https?://(?:www\.)?mega\.co\.nz/|mega:|chrome:.+?)#(?P<TYPE>N|)!(?P<ID>[\w^_]+)!(?P<KEY>[\w,\\-]+)'
+
+ __description__ = """Mega.co.nz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "ranan@pyload.org"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ API_URL = "https://eu.api.mega.co.nz/cs"
+ FILE_SUFFIX = ".crypted"
+
+
+ def b64_decode(self, data):
+ data = data.replace("-", "+").replace("_", "/")
+ return standard_b64decode(data + '=' * (-len(data) % 4))
+
+
+ def getCipherKey(self, key):
+ """ Construct the cipher key from the given data """
+ a = array("I", self.b64_decode(key))
+
+ k = array("I", (a[0] ^ a[4], a[1] ^ a[5], a[2] ^ a[6], a[3] ^ a[7]))
+ iv = a[4:6] + array("I", (0, 0))
+ meta_mac = a[6:8]
+
+ return k, iv, meta_mac
+
+
+ def api_response(self, **kwargs):
+ """ Dispatch a call to the api, see https://mega.co.nz/#developers """
+
+ # generate a session id, no idea where to obtain elsewhere
+ uid = random.randint(10 << 9, 10 ** 10)
+
+ res = self.load(self.API_URL, get={'id': uid}, post=json_dumps([kwargs]))
+ self.logDebug("Api Response: " + res)
+ return json_loads(res)
+
+
+ def decryptAttr(self, data, key):
+ k, iv, meta_mac = self.getCipherKey(key)
+ cbc = AES.new(k, AES.MODE_CBC, "\0" * 16)
+ attr = decode(cbc.decrypt(self.b64_decode(data)))
+
+ self.logDebug("Decrypted Attr: %s" % attr)
+ if not attr.startswith("MEGA"):
+ self.fail(_("Decryption failed"))
+
+ # Data is padded, 0-bytes must be stripped
+ return json_loads(re.search(r'{.+?}', attr).group(0))
+
+
+ def decryptFile(self, key):
+ """ Decrypts the file at lastDownload` """
+
+ # upper 64 bit of counter start
+ n = self.b64_decode(key)[16:24]
+
+ # convert counter to long and shift bytes
+ k, iv, meta_mac = self.getCipherKey(key)
+ ctr = Counter.new(128, initial_value=long(n.encode("hex"), 16) << 64)
+ cipher = AES.new(k, AES.MODE_CTR, counter=ctr)
+
+ self.pyfile.setStatus("decrypting")
+ self.pyfile.setProgress(0)
+
+ file_crypted = fs_encode(self.lastDownload)
+ file_decrypted = file_crypted.rsplit(self.FILE_SUFFIX)[0]
+
+ try:
+ f = open(file_crypted, "rb")
+ df = open(file_decrypted, "wb")
+
+ except IOError, e:
+ self.fail(e)
+
+ chunk_size = 2 ** 15 # buffer size, 32k
+ # file_mac = [0, 0, 0, 0] # calculate CBC-MAC for checksum
+
+ chunks = os.path.getsize(file_crypted) / chunk_size + 1
+ for i in xrange(chunks):
+ buf = f.read(chunk_size)
+ if not buf:
+ break
+
+ chunk = cipher.decrypt(buf)
+ df.write(chunk)
+
+ self.pyfile.setProgress(int((100.0 / chunks) * i))
+
+ # chunk_mac = [iv[0], iv[1], iv[0], iv[1]]
+ # for i in xrange(0, chunk_size, 16):
+ # block = chunk[i:i+16]
+ # if len(block) % 16:
+ # block += '=' * (16 - (len(block) % 16))
+ # block = array("I", block)
+
+ # chunk_mac = [chunk_mac[0] ^ a_[0], chunk_mac[1] ^ block[1], chunk_mac[2] ^ block[2], chunk_mac[3] ^ block[3]]
+ # chunk_mac = aes_cbc_encrypt_a32(chunk_mac, k)
+
+ # file_mac = [file_mac[0] ^ chunk_mac[0], file_mac[1] ^ chunk_mac[1], file_mac[2] ^ chunk_mac[2], file_mac[3] ^ chunk_mac[3]]
+ # file_mac = aes_cbc_encrypt_a32(file_mac, k)
+
+ self.pyfile.setProgress(100)
+
+ f.close()
+ df.close()
+
+ # if file_mac[0] ^ file_mac[1], file_mac[2] ^ file_mac[3] != meta_mac:
+ # os.remove(file_decrypted)
+ # self.fail(_("Checksum mismatch"))
+
+ os.remove(file_crypted)
+ self.lastDownload = fs_decode(file_decrypted)
+
+
+ def checkError(self, code):
+ ecode = abs(code)
+
+ if ecode in (9, 16, 21):
+ self.offline()
+
+ elif ecode in (3, 13, 17, 18, 19):
+ self.tempOffline()
+
+ elif ecode in (1, 4, 6, 10, 15, 21):
+ self.retry(5, 30, _("Error code: [%s]") % -ecode)
+
+ else:
+ self.fail(_("Error code: [%s]") % -ecode)
+
+
+ def process(self, pyfile):
+ pattern = re.match(self.__pattern__, pyfile.url).groupdict()
+ id = pattern['ID']
+ key = pattern['KEY']
+ public = pattern['TYPE'] == ''
+
+ self.logDebug("ID: %s" % id, "Key: %s" % key, "Type: %s" % ("public" if public else "node"))
+
+ # g is for requesting a download url
+ # this is similar to the calls in the mega js app, documentation is very bad
+ if public:
+ mega = self.api_response(a="g", g=1, p=id, ssl=1)[0]
+ else:
+ mega = self.api_response(a="g", g=1, n=id, ssl=1)[0]
+
+ if isinstance(mega, int):
+ self.checkError(mega)
+ elif "e" in mega:
+ self.checkError(mega['e'])
+
+ attr = self.decryptAttr(mega['at'], key)
+
+ pyfile.name = attr['n'] + self.FILE_SUFFIX
+ pyfile.size = mega['s']
+
+ # self.req.http.c.setopt(SSL_CIPHER_LIST, "RC4-MD5:DEFAULT")
+
+ self.download(mega['g'])
+
+ self.decryptFile(key)
+
+ # Everything is finished and final name can be set
+ pyfile.name = attr['n']
diff --git a/pyload/plugin/hoster/MegaDebridEu.py b/pyload/plugin/hoster/MegaDebridEu.py
new file mode 100644
index 000000000..842ad4de9
--- /dev/null
+++ b/pyload/plugin/hoster/MegaDebridEu.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urllib import unquote_plus
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHoster import MultiHoster
+
+
+class MegaDebridEu(MultiHoster):
+ __name__ = "MegaDebridEu"
+ __type__ = "hoster"
+ __version__ = "0.46"
+
+ __pattern__ = r'http://((?:www\d+\.|s\d+\.)?mega-debrid\.eu|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/download/file/[\w^_]+'
+
+ __description__ = """mega-debrid.eu multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("D.Ducatel", "dducatel@je-geek.fr")]
+
+
+ API_URL = "https://www.mega-debrid.eu/api.php"
+
+
+ def getFilename(self, url):
+ try:
+ return unquote_plus(url.rsplit("/", 1)[1])
+ except IndexError:
+ return ""
+
+
+ def handlePremium(self, pyfile):
+ if not self.api_load():
+ self.exitOnFail("Unable to connect to Mega-debrid.eu")
+
+ self.link = self.debridLink(pyfile.url)
+
+ filename = self.getFilename(self.link)
+ if filename:
+ pyfile.name = filename
+
+
+ def api_load(self):
+ """
+ Connexion to the mega-debrid API
+ Return True if succeed
+ """
+ user, data = self.account.selectAccount()
+ jsonResponse = self.load(self.API_URL,
+ get={'action': 'connectUser', 'login': user, 'password': data['password']})
+ res = json_loads(jsonResponse)
+
+ if res['response_code'] == "ok":
+ self.token = res['token']
+ return True
+ else:
+ return False
+
+
+ def debridLink(self, linkToDebrid):
+ """
+ Debrid a link
+ Return The debrided link if succeed or original link if fail
+ """
+ jsonResponse = self.load(self.API_URL, get={'action': 'getLink', 'token': self.token},
+ post={"link": linkToDebrid})
+ res = json_loads(jsonResponse)
+
+ if res['response_code'] == "ok":
+ debridedLink = res['debridLink'][1:-1]
+ return debridedLink
+ else:
+ self.exitOnFail("Unable to debrid %s" % linkToDebrid)
+
+
+ def exitOnFail(self, msg):
+ """
+ exit the plugin on fail case
+ And display the reason of this failure
+ """
+ if self.getConfig("unloadFailing"):
+ self.logError(_(msg))
+ self.resetAccount()
+ else:
+ self.fail(_(msg))
diff --git a/pyload/plugin/hoster/MegaFilesSe.py b/pyload/plugin/hoster/MegaFilesSe.py
new file mode 100644
index 000000000..3cfd41da4
--- /dev/null
+++ b/pyload/plugin/hoster/MegaFilesSe.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class MegaFilesSe(DeadHoster):
+ __name__ = "MegaFilesSe"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?megafiles\.se/\w{12}'
+
+ __description__ = """MegaFiles.se hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("t4skforce", "t4skforce1337[AT]gmail[DOT]com")]
diff --git a/pyload/plugin/hoster/MegaRapidCz.py b/pyload/plugin/hoster/MegaRapidCz.py
new file mode 100644
index 000000000..b7b9e3ffe
--- /dev/null
+++ b/pyload/plugin/hoster/MegaRapidCz.py
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pycurl import HTTPHEADER
+
+from pyload.network.HTTPRequest import BadHeader
+from pyload.network.RequestFactory import getRequest
+from pyload.plugin.internal.SimpleHoster import SimpleHoster, parseFileInfo
+
+
+def getInfo(urls):
+ h = getRequest()
+ h.c.setopt(HTTPHEADER,
+ ["Accept: text/html",
+ "User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0"])
+
+ for url in urls:
+ html = h.load(url, decode=True)
+ yield parseFileInfo(MegaRapidCz, url, html)
+
+
+class MegaRapidCz(SimpleHoster):
+ __name__ = "MegaRapidCz"
+ __type__ = "hoster"
+ __version__ = "0.56"
+
+ __pattern__ = r'http://(?:www\.)?(share|mega)rapid\.cz/soubor/\d+/.+'
+
+ __description__ = """MegaRapid.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("MikyWoW", "mikywow@seznam.cz"),
+ ("zoidberg", "zoidberg@mujmail.cz"),
+ ("stickell", "l.stickell@yahoo.it"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ NAME_PATTERN = r'<h1[^>]*><span[^>]*>(?:<a[^>]*>)?(?P<N>[^<]+)'
+ SIZE_PATTERN = r'<td class="i">Velikost:</td>\s*<td class="h"><strong>\s*(?P<S>[\d.,]+) (?P<U>[\w^_]+)</strong></td>'
+ OFFLINE_PATTERN = ur'Nastala chyba 404|Soubor byl smazán'
+
+ CHECK_TRAFFIC = True
+
+ LINK_PREMIUM_PATTERN = r'<a href="([^"]+)" title="Stahnout">([^<]+)</a>'
+
+ ERR_LOGIN_PATTERN = ur'<div class="error_div"><strong>Stahování je přístupné pouze přihlášenÃœm uÅŸivatelům'
+ ERR_CREDIT_PATTERN = ur'<div class="error_div"><strong>Stahování zdarma je moÅŸné jen přes náš'
+
+
+ def setup(self):
+ self.chunkLimit = 1
+
+
+ def handlePremium(self, pyfile):
+ m = re.search(self.LINK_PREMIUM_PATTERN, self.html)
+ if m:
+ self.link = m.group(1)
+ else:
+ if re.search(self.ERR_LOGIN_PATTERN, self.html):
+ self.relogin(self.user)
+ self.retry(wait_time=60, reason=_("User login failed"))
+ elif re.search(self.ERR_CREDIT_PATTERN, self.html):
+ self.fail(_("Not enough credit left"))
+ else:
+ self.fail(_("Download link not found"))
diff --git a/module/plugins/hoster/MegacrypterCom.py b/pyload/plugin/hoster/MegacrypterCom.py
index f8fcb97fe..f8fcb97fe 100644
--- a/module/plugins/hoster/MegacrypterCom.py
+++ b/pyload/plugin/hoster/MegacrypterCom.py
diff --git a/pyload/plugin/hoster/MegareleaseOrg.py b/pyload/plugin/hoster/MegareleaseOrg.py
new file mode 100644
index 000000000..c2c7fe357
--- /dev/null
+++ b/pyload/plugin/hoster/MegareleaseOrg.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class MegareleaseOrg(DeadHoster):
+ __name__ = "MegareleaseOrg"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'https?://(?:www\.)?megarelease\.org/\w{12}'
+
+ __description__ = """Megarelease.org hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("derek3x", "derek3x@vmail.me"),
+ ("stickell", "l.stickell@yahoo.it")]
diff --git a/pyload/plugin/hoster/MegasharesCom.py b/pyload/plugin/hoster/MegasharesCom.py
new file mode 100644
index 000000000..483969e2e
--- /dev/null
+++ b/pyload/plugin/hoster/MegasharesCom.py
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from time import time
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class MegasharesCom(SimpleHoster):
+ __name__ = "MegasharesCom"
+ __type__ = "hoster"
+ __version__ = "0.28"
+
+ __pattern__ = r'http://(?:www\.)?(d\d{2}\.)?megashares\.com/((index\.php)?\?d\d{2}=|dl/)\w+'
+
+ __description__ = """Megashares.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ NAME_PATTERN = r'<h1 class="black xxl"[^>]*title="(?P<N>[^"]+)">'
+ SIZE_PATTERN = r'<strong><span class="black">Filesize:</span></strong> (?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+ OFFLINE_PATTERN = r'<dd class="red">(Invalid Link Request|Link has been deleted|Invalid link)'
+
+ LINK_PATTERN = r'<div id="show_download_button_%d"[^>]*>\s*<a href="([^"]+)">'
+
+ PASSPORT_LEFT_PATTERN = r'Your Download Passport is: <[^>]*>(\w+).*?You have.*?<[^>]*>.*?([\d.]+) (\w+)'
+ PASSPORT_RENEW_PATTERN = r'(\d+):<strong>(\d+)</strong>:<strong>(\d+)</strong>'
+ REACTIVATE_NUM_PATTERN = r'<input[^>]*id="random_num" value="(\d+)" />'
+ REACTIVATE_PASSPORT_PATTERN = r'<input[^>]*id="passport_num" value="(\w+)" />'
+ REQUEST_URI_PATTERN = r'var request_uri = "([^"]+)";'
+ NO_SLOTS_PATTERN = r'<dd class="red">All download slots for this link are currently filled'
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = self.premium
+
+
+ def handlePremium(self, pyfile):
+ self.handleDownload(True)
+
+
+ def handleFree(self, pyfile):
+ if self.NO_SLOTS_PATTERN in self.html:
+ self.retry(wait_time=5 * 60)
+
+ m = re.search(self.REACTIVATE_PASSPORT_PATTERN, self.html)
+ if m:
+ passport_num = m.group(1)
+ request_uri = re.search(self.REQUEST_URI_PATTERN, self.html).group(1)
+
+ for _i in xrange(5):
+ random_num = re.search(self.REACTIVATE_NUM_PATTERN, self.html).group(1)
+
+ verifyinput = self.decryptCaptcha("http://d01.megashares.com/index.php",
+ get={'secgfx': "gfx", 'random_num': random_num})
+
+ self.logInfo(_("Reactivating passport %s: %s %s") % (passport_num, random_num, verifyinput))
+
+ res = self.load("http://d01.megashares.com%s" % request_uri,
+ get={'rs' : "check_passport_renewal",
+ 'rsargs[]': verifyinput,
+ 'rsargs[]': random_num,
+ 'rsargs[]': passport_num,
+ 'rsargs[]': "replace_sec_pprenewal",
+ 'rsrnd[]' : str(int(time() * 1000))})
+
+ if 'Thank you for reactivating your passport.' in res:
+ self.correctCaptcha()
+ self.retry()
+ else:
+ self.invalidCaptcha()
+ else:
+ self.fail(_("Failed to reactivate passport"))
+
+ m = re.search(self.PASSPORT_RENEW_PATTERN, self.html)
+ if m:
+ time = [int(x) for x in m.groups()]
+ renew = time[0] + (time[1] * 60) + (time[2] * 60)
+ self.logDebug("Waiting %d seconds for a new passport" % renew)
+ self.retry(wait_time=renew, reason=_("Passport renewal"))
+
+ # Check traffic left on passport
+ m = re.search(self.PASSPORT_LEFT_PATTERN, self.html, re.M | re.S)
+ if m is None:
+ self.fail(_("Passport not found"))
+
+ self.logInfo(_("Download passport: %s") % m.group(1))
+ data_left = float(m.group(2)) * 1024 ** {'B': 0, 'KB': 1, 'MB': 2, 'GB': 3}[m.group(3)]
+ self.logInfo(_("Data left: %s %s (%d MB needed)") % (m.group(2), m.group(3), self.pyfile.size / 1048576))
+
+ if not data_left:
+ self.retry(wait_time=600, reason=_("Passport renewal"))
+
+ self.handleDownload(False)
+
+
+ def handleDownload(self, premium=False):
+ # Find download link;
+ m = re.search(self.LINK_PATTERN % (1 if premium else 2), self.html)
+ msg = _('%s download URL' % ('Premium' if premium else 'Free'))
+ if m is None:
+ self.error(msg)
+
+ download_url = m.group(1)
+ self.logDebug("%s: %s" % (msg, download_url))
+ self.download(download_url)
diff --git a/pyload/plugin/hoster/MegauploadCom.py b/pyload/plugin/hoster/MegauploadCom.py
new file mode 100644
index 000000000..c1d5b4524
--- /dev/null
+++ b/pyload/plugin/hoster/MegauploadCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class MegauploadCom(DeadHoster):
+ __name__ = "MegauploadCom"
+ __type__ = "hoster"
+ __version__ = "0.31"
+
+ __pattern__ = r'http://(?:www\.)?megaupload\.com/\?.*&?(d|v)=\w+'
+
+ __description__ = """Megaupload.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("spoob", "spoob@pyload.org")]
diff --git a/pyload/plugin/hoster/MegavideoCom.py b/pyload/plugin/hoster/MegavideoCom.py
new file mode 100644
index 000000000..442b0f292
--- /dev/null
+++ b/pyload/plugin/hoster/MegavideoCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class MegavideoCom(DeadHoster):
+ __name__ = "MegavideoCom"
+ __type__ = "hoster"
+ __version__ = "0.21"
+
+ __pattern__ = r'http://(?:www\.)?megavideo\.com/\?.*&?(d|v)=\w+'
+
+ __description__ = """Megavideo.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("jeix", "jeix@hasnomail.de"),
+ ("mkaay", "mkaay@mkaay.de")]
diff --git a/pyload/plugin/hoster/MovReelCom.py b/pyload/plugin/hoster/MovReelCom.py
new file mode 100644
index 000000000..f273d623a
--- /dev/null
+++ b/pyload/plugin/hoster/MovReelCom.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class MovReelCom(XFSHoster):
+ __name__ = "MovReelCom"
+ __type__ = "hoster"
+ __version__ = "1.24"
+
+ __pattern__ = r'http://(?:www\.)?movreel\.com/\w{12}'
+
+ __description__ = """MovReel.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("JorisV83", "jorisv83-pyload@yahoo.com")]
+
+
+ LINK_PATTERN = r'<a href="([^"]+)">Download Link'
diff --git a/pyload/plugin/hoster/MultihostersCom.py b/pyload/plugin/hoster/MultihostersCom.py
new file mode 100644
index 000000000..3c9e81242
--- /dev/null
+++ b/pyload/plugin/hoster/MultihostersCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.hoster.ZeveraCom import ZeveraCom
+
+
+class MultihostersCom(ZeveraCom):
+ __name__ = "MultihostersCom"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'https?://(?:www\.)multihosters\.com/(getFiles\.ashx|Members/download\.ashx)\?.*ourl=.+'
+
+ __description__ = """Multihosters.com multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("tjeh", "tjeh@gmx.net")]
diff --git a/pyload/plugin/hoster/MultishareCz.py b/pyload/plugin/hoster/MultishareCz.py
new file mode 100644
index 000000000..252e9cdb5
--- /dev/null
+++ b/pyload/plugin/hoster/MultishareCz.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from random import random
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class MultishareCz(SimpleHoster):
+ __name__ = "MultishareCz"
+ __type__ = "hoster"
+ __version__ = "0.40"
+
+ __pattern__ = r'http://(?:www\.)?multishare\.cz/stahnout/(?P<ID>\d+)'
+
+ __description__ = """MultiShare.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ SIZE_REPLACEMENTS = [('&nbsp;', '')]
+
+ CHECK_TRAFFIC = True
+ MULTI_HOSTER = True
+
+ INFO_PATTERN = ur'(?:<li>Název|Soubor): <strong>(?P<N>[^<]+)</strong><(?:/li><li|br)>Velikost: <strong>(?P<S>[^<]+)</strong>'
+ OFFLINE_PATTERN = ur'<h1>Stáhnout soubor</h1><p><strong>PoşadovanÜ soubor neexistuje.</strong></p>'
+
+
+ def handleFree(self, pyfile):
+ self.download("http://www.multishare.cz/html/download_free.php", get={'ID': self.info['pattern']['ID']})
+
+
+ def handlePremium(self, pyfile):
+ self.download("http://www.multishare.cz/html/download_premium.php", get={'ID': self.info['pattern']['ID']})
+
+
+ def handleMulti(self, pyfile):
+ self.html = self.load('http://www.multishare.cz/html/mms_ajax.php', post={"link": pyfile.url}, decode=True)
+
+ self.checkInfo()
+
+ if not self.checkTrafficLeft():
+ self.fail(_("Not enough credit left to download file"))
+
+ self.download("http://dl%d.mms.multishare.cz/html/mms_process.php" % round(random() * 10000 * random()),
+ get={'u_ID' : self.acc_info['u_ID'],
+ 'u_hash': self.acc_info['u_hash'],
+ 'link' : pyfile.url},
+ disposition=True)
diff --git a/pyload/plugin/hoster/MyfastfileCom.py b/pyload/plugin/hoster/MyfastfileCom.py
new file mode 100644
index 000000000..c065c2331
--- /dev/null
+++ b/pyload/plugin/hoster/MyfastfileCom.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHoster import MultiHoster
+
+
+class MyfastfileCom(MultiHoster):
+ __name__ = "MyfastfileCom"
+ __type__ = "hoster"
+ __version__ = "0.08"
+
+ __pattern__ = r'http://\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/dl/'
+
+ __description__ = """Myfastfile.com multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+
+ def setup(self):
+ self.chunkLimit = -1
+
+
+ def handlePremium(self, pyfile):
+ self.html = self.load('http://myfastfile.com/api.php',
+ get={'user': self.user, 'pass': self.account.getAccountData(self.user)['password'],
+ 'link': pyfile.url})
+ self.logDebug("JSON data: " + self.html)
+
+ self.html = json_loads(self.html)
+ if self.html['status'] != 'ok':
+ self.fail(_("Unable to unrestrict link"))
+
+ self.link = self.html['link']
diff --git a/pyload/plugin/hoster/MystoreTo.py b/pyload/plugin/hoster/MystoreTo.py
new file mode 100644
index 000000000..e2288e344
--- /dev/null
+++ b/pyload/plugin/hoster/MystoreTo.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+#
+# Test link:
+# http://mystore.to/dl/mxcA50jKfP
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class MystoreTo(SimpleHoster):
+ __name__ = "MystoreTo"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'https?://(?:www\.)?mystore\.to/dl/.+'
+
+ __description__ = """Mystore.to hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "")]
+
+
+ NAME_PATTERN = r'<h1>(?P<N>.+?)<'
+ SIZE_PATTERN = r'FILESIZE: (?P<S>[\d\.,]+) (?P<U>[\w^_]+)'
+ OFFLINE_PATTERN = r'>file not found<'
+
+
+ def setup(self):
+ self.chunkLimit = 1
+ self.resumeDownload = True
+ self.multiDL = True
+
+
+ def handleFree(self, pyfile):
+ try:
+ fid = re.search(r'wert="(.+?)"', self.html).group(1)
+
+ except AttributeError:
+ self.error(_("File-ID not found"))
+
+ self.link = self.load("http://mystore.to/api/download",
+ post={'FID': fid})
diff --git a/module/plugins/hoster/MyvideoDe.py b/pyload/plugin/hoster/MyvideoDe.py
index 4b5fa99ca..4b5fa99ca 100644
--- a/module/plugins/hoster/MyvideoDe.py
+++ b/pyload/plugin/hoster/MyvideoDe.py
diff --git a/pyload/plugin/hoster/NahrajCz.py b/pyload/plugin/hoster/NahrajCz.py
new file mode 100644
index 000000000..6aa87a520
--- /dev/null
+++ b/pyload/plugin/hoster/NahrajCz.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class NahrajCz(DeadHoster):
+ __name__ = "NahrajCz"
+ __type__ = "hoster"
+ __version__ = "0.21"
+
+ __pattern__ = r'http://(?:www\.)?nahraj\.cz/content/download/.+'
+
+ __description__ = """Nahraj.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/NarodRu.py b/pyload/plugin/hoster/NarodRu.py
new file mode 100644
index 000000000..7b9da6e4e
--- /dev/null
+++ b/pyload/plugin/hoster/NarodRu.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from random import random
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class NarodRu(SimpleHoster):
+ __name__ = "NarodRu"
+ __type__ = "hoster"
+ __version__ = "0.12"
+
+ __pattern__ = r'http://(?:www\.)?narod(\.yandex)?\.ru/(disk|start/\d+\.\w+-narod\.yandex\.ru)/(?P<ID>\d+)/.+'
+
+ __description__ = """Narod.ru hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<dt class="name">(?:<[^<]*>)*(?P<N>[^<]+)</dt>'
+ SIZE_PATTERN = r'<dd class="size">(?P<S>\d[^<]*)</dd>'
+ OFFLINE_PATTERN = r'<title>404</title>|Ѐайл уЎалеМ с сервОса|ЗакПМчОлся срПк храМеМОя файла\.'
+
+ SIZE_REPLACEMENTS = [(u'КБ', 'KB'), (u'МБ', 'MB'), (u'ГБ', 'GB')]
+ URL_REPLACEMENTS = [("narod.yandex.ru/", "narod.ru/"),
+ (r"/start/\d+\.\w+-narod\.yandex\.ru/(\d{6,15})/\w+/(\w+)", r"/disk/\1/\2")]
+
+ CAPTCHA_PATTERN = r'<number url="(.*?)">(\w+)</number>'
+ LINK_FREE_PATTERN = r'<a class="h-link" rel="yandex_bar" href="(.+?)">'
+
+
+ def handleFree(self, pyfile):
+ for _i in xrange(5):
+ self.html = self.load('http://narod.ru/disk/getcapchaxml/?rnd=%d' % int(random() * 777))
+
+ m = re.search(self.CAPTCHA_PATTERN, self.html)
+ if m is None:
+ self.error(_("Captcha"))
+
+ post_data = {"action": "sendcapcha"}
+ captcha_url, post_data['key'] = m.groups()
+ post_data['rep'] = self.decryptCaptcha(captcha_url)
+
+ self.html = self.load(pyfile.url, post=post_data, decode=True)
+
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m:
+ url = 'http://narod.ru' + m.group(1)
+ self.correctCaptcha()
+ break
+
+ elif u'<b class="error-msg"><strong>ОшОблОсь?</strong>' in self.html:
+ self.invalidCaptcha()
+
+ else:
+ self.error(_("Download link"))
+
+ else:
+ self.fail(_("No valid captcha code entered"))
+
+ self.download(url)
diff --git a/module/plugins/hoster/NetloadIn.py b/pyload/plugin/hoster/NetloadIn.py
index 2ed298ffa..2ed298ffa 100644
--- a/module/plugins/hoster/NetloadIn.py
+++ b/pyload/plugin/hoster/NetloadIn.py
diff --git a/pyload/plugin/hoster/NitroflareCom.py b/pyload/plugin/hoster/NitroflareCom.py
new file mode 100644
index 000000000..85630a148
--- /dev/null
+++ b/pyload/plugin/hoster/NitroflareCom.py
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+#
+# Note:
+# Right now premium support is not added
+# Thus, any file that require premium support
+# cannot be downloaded. Only the file that is free to
+# download can be downloaded.
+
+import re
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.CaptchaService import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class NitroflareCom(SimpleHoster):
+ __name__ = "NitroflareCom"
+ __type__ = "hoster"
+ __version__ = "0.08"
+
+ __pattern__ = r'https?://(?:www\.)?nitroflare\.com/view/(?P<ID>[\w^_]+)'
+
+ __description__ = """Nitroflare.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("sahil", "sahilshekhawat01@gmail.com"),
+ ("Walter Purcaro", "vuolter@gmail.com"),
+ ("Stickell", "l.stickell@yahoo.it")]
+
+ # URL_REPLACEMENTS = [("http://", "https://")]
+
+ INFO_PATTERN = r'title="(?P<N>.+?)".+>(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+ OFFLINE_PATTERN = r'>File doesn\'t exist'
+
+ LINK_FREE_PATTERN = r'(https?://[\w\-]+\.nitroflare\.com/.+?)"'
+
+ RECAPTCHA_KEY = "6Lenx_USAAAAAF5L1pmTWvWcH73dipAEzNnmNLgy"
+
+ PREMIUM_ONLY_PATTERN = r'This file is available with Premium only'
+ WAIT_PATTERN = r'You have to wait .+'
+ ERROR_PATTERN = r'downloading is not possible'
+
+
+ def checkErrors(self):
+ if not self.html:
+ return
+
+ if not self.premium and re.search(self.PREMIUM_ONLY_PATTERN, self.html):
+ self.fail(_("Link require a premium account to be handled"))
+
+ elif hasattr(self, 'WAIT_PATTERN'):
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m:
+ wait_time = sum(int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1}[u.lower()] for v, u in
+ re.findall(r'(\d+)\s*(hr|hour|min|sec)', m.group(0), re.I))
+ self.wait(wait_time, wait_time > 300)
+ return
+
+ elif hasattr(self, 'ERROR_PATTERN'):
+ m = re.search(self.ERROR_PATTERN, self.html)
+ if m:
+ errmsg = self.info['error'] = m.group(1)
+ self.error(errmsg)
+
+ self.info.pop('error', None)
+
+
+ def handleFree(self, pyfile):
+ # used here to load the cookies which will be required later
+ self.load(pyfile.url, post={'goToFreePage': ""})
+
+ self.load("https://www.nitroflare.com/ajax/setCookie.php", post={'fileId': self.info['pattern']['ID']})
+ self.html = self.load("https://www.nitroflare.com/ajax/freeDownload.php",
+ post={'method': "startTimer", 'fileId': self.info['pattern']['ID']})
+
+ self.checkErrors()
+
+ try:
+ js_file = self.load("http://nitroflare.com/js/downloadFree.js?v=1.0.1")
+ var_time = re.search("var time = (\\d+);", js_file)
+ wait_time = int(var_time.groups()[0])
+
+ except Exception:
+ wait_time = 60
+
+ self.wait(wait_time)
+
+ recaptcha = ReCaptcha(self)
+ response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY)
+
+ self.html = self.load("https://www.nitroflare.com/ajax/freeDownload.php",
+ post={'method' : "fetchDownload",
+ 'recaptcha_challenge_field': challenge,
+ 'recaptcha_response_field' : response})
+
+ if "The captcha wasn't entered correctly" in self.html:
+ self.logWarning("The captcha wasn't entered correctly")
+ return
+
+ if "You have to fill the captcha" in self.html:
+ self.logWarning("Captcha unfilled")
+ return
+
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m:
+ self.link = m.group(1)
+ else:
+ self.logError("Unable to detect direct link")
diff --git a/pyload/plugin/hoster/NoPremiumPl.py b/pyload/plugin/hoster/NoPremiumPl.py
new file mode 100644
index 000000000..ddb9d78f8
--- /dev/null
+++ b/pyload/plugin/hoster/NoPremiumPl.py
@@ -0,0 +1,103 @@
+# -*- coding: utf-8 -*-
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHoster import MultiHoster
+
+
+class NoPremiumPl(MultiHoster):
+ __name__ = "NoPremiumPl"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'https?://direct\.nopremium\.pl.+'
+
+ __description__ = """NoPremium.pl multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("goddie", "dev@nopremium.pl")]
+
+
+ API_URL = "http://crypt.nopremium.pl"
+
+ API_QUERY = {'site' : "nopremium",
+ 'output' : "json",
+ 'username': "",
+ 'password': "",
+ 'url' : ""}
+
+ ERROR_CODES = {0 : "[%s] Incorrect login credentials",
+ 1 : "[%s] Not enough transfer to download - top-up your account",
+ 2 : "[%s] Incorrect / dead link",
+ 3 : "[%s] Error connecting to hosting, try again later",
+ 9 : "[%s] Premium account has expired",
+ 15: "[%s] Hosting no longer supported",
+ 80: "[%s] Too many incorrect login attempts, account blocked for 24h"}
+
+
+ def prepare(self):
+ super(NoPremiumPl, self).prepare()
+
+ data = self.account.getAccountData(self.user)
+
+ self.usr = data['usr']
+ self.pwd = data['pwd']
+
+
+ def runFileQuery(self, url, mode=None):
+ query = self.API_QUERY.copy()
+
+ query["username"] = self.usr
+ query["password"] = self.pwd
+ query["url"] = url
+
+ if mode == "fileinfo":
+ query['check'] = 2
+ query['loc'] = 1
+
+ self.logDebug(query)
+
+ return self.load(self.API_URL, post=query)
+
+
+ def handleFree(self, pyfile):
+ try:
+ data = self.runFileQuery(pyfile.url, 'fileinfo')
+
+ except Exception:
+ self.logDebug("runFileQuery error")
+ self.tempOffline()
+
+ try:
+ parsed = json_loads(data)
+
+ except Exception:
+ self.logDebug("loads error")
+ self.tempOffline()
+
+ self.logDebug(parsed)
+
+ if "errno" in parsed.keys():
+ if parsed["errno"] in self.ERROR_CODES:
+ # error code in known
+ self.fail(self.ERROR_CODES[parsed["errno"]] % self.__name__)
+ else:
+ # error code isn't yet added to plugin
+ self.fail(
+ parsed["errstring"]
+ or _("Unknown error (code: %s)") % parsed["errno"]
+ )
+
+ if "sdownload" in parsed:
+ if parsed["sdownload"] == "1":
+ self.fail(
+ _("Download from %s is possible only using NoPremium.pl website \
+ directly") % parsed["hosting"])
+
+ pyfile.name = parsed["filename"]
+ pyfile.size = parsed["filesize"]
+
+ try:
+ self.link = self.runFileQuery(pyfile.url, 'filedownload')
+
+ except Exception:
+ self.logDebug("runFileQuery error #2")
+ self.tempOffline()
diff --git a/pyload/plugin/hoster/NosuploadCom.py b/pyload/plugin/hoster/NosuploadCom.py
new file mode 100644
index 000000000..edb8c6508
--- /dev/null
+++ b/pyload/plugin/hoster/NosuploadCom.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class NosuploadCom(XFSHoster):
+ __name__ = "NosuploadCom"
+ __type__ = "hoster"
+ __version__ = "0.31"
+
+ __pattern__ = r'http://(?:www\.)?nosupload\.com/\?d=\w{12}'
+
+ __description__ = """Nosupload.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("igel", "igelkun@myopera.com")]
+
+
+ SIZE_PATTERN = r'<p><strong>Size:</strong> (?P<S>[\d.,]+) (?P<U>[\w^_]+)</p>'
+ LINK_PATTERN = r'<a class="select" href="(http://.+?)">Download</a>'
+
+ WAIT_PATTERN = r'Please wait.*?>(\d+)</span>'
+
+
+ def getDownloadLink(self):
+ # stage1: press the "Free Download" button
+ data = self.getPostParameters()
+ self.html = self.load(self.pyfile.url, post=data, ref=True, decode=True)
+
+ # stage2: wait some time and press the "Download File" button
+ data = self.getPostParameters()
+ wait_time = re.search(self.WAIT_PATTERN, self.html, re.M | re.S).group(1)
+ self.logDebug("Hoster told us to wait %s seconds" % wait_time)
+ self.wait(wait_time)
+ self.html = self.load(self.pyfile.url, post=data, ref=True, decode=True)
+
+ # stage3: get the download link
+ return re.search(self.LINK_PATTERN, self.html, re.S).group(1)
diff --git a/pyload/plugin/hoster/NovafileCom.py b/pyload/plugin/hoster/NovafileCom.py
new file mode 100644
index 000000000..e79ba5980
--- /dev/null
+++ b/pyload/plugin/hoster/NovafileCom.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# http://novafile.com/vfun4z6o2cit
+# http://novafile.com/s6zrr5wemuz4
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class NovafileCom(XFSHoster):
+ __name__ = "NovafileCom"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'http://(?:www\.)?novafile\.com/\w{12}'
+
+ __description__ = """Novafile.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
+ ("stickell", "l.stickell@yahoo.it")]
+
+
+ ERROR_PATTERN = r'class="alert[^"]*alert-separate"[^>]*>\s*(?:<p>)?(.*?)\s*</'
+ WAIT_PATTERN = r'<p>Please wait <span id="count"[^>]*>(\d+)</span> seconds</p>'
+
+ LINK_PATTERN = r'<a href="(http://s\d+\.novafile\.com/.*?)" class="btn btn-green">Download File</a>'
diff --git a/pyload/plugin/hoster/NowDownloadSx.py b/pyload/plugin/hoster/NowDownloadSx.py
new file mode 100644
index 000000000..00101a379
--- /dev/null
+++ b/pyload/plugin/hoster/NowDownloadSx.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+from pyload.utils import fixup
+
+
+class NowDownloadSx(SimpleHoster):
+ __name__ = "NowDownloadSx"
+ __type__ = "hoster"
+ __version__ = "0.07"
+
+ __pattern__ = r'http://(?:www\.)?(nowdownload\.(at|ch|co|eu|sx)/(dl/|download\.php\?id=)|likeupload\.org/)\w+'
+
+ __description__ = """NowDownload.sx hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("godofdream", "soilfiction@gmail.com"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ INFO_PATTERN = r'Downloading</span> <br> (?P<N>.*) (?P<S>[\d.,]+) (?P<U>[\w^_]+) </h4>'
+ OFFLINE_PATTERN = r'>This file does not exist'
+
+ TOKEN_PATTERN = r'"(/api/token\.php\?token=\w+)"'
+ CONTINUE_PATTERN = r'"(/dl2/\w+/\w+)"'
+ WAIT_PATTERN = r'\.countdown\(\{until: \+(\d+),'
+ LINK_FREE_PATTERN = r'(http://s\d+\.coolcdn\.info/nowdownload/.+?)["\']'
+
+ NAME_REPLACEMENTS = [("&#?\w+;", fixup), (r'<[^>]*>', '')]
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = True
+ self.chunkLimit = -1
+
+
+ def handleFree(self, pyfile):
+ tokenlink = re.search(self.TOKEN_PATTERN, self.html)
+ continuelink = re.search(self.CONTINUE_PATTERN, self.html)
+ if tokenlink is None or continuelink is None:
+ self.error()
+
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m:
+ wait = int(m.group(1))
+ else:
+ wait = 60
+
+ baseurl = "http://www.nowdownload.at"
+ self.html = self.load(baseurl + str(tokenlink.group(1)))
+ self.wait(wait)
+
+ self.html = self.load(baseurl + str(continuelink.group(1)))
+
+ url = re.search(self.LINK_FREE_PATTERN, self.html)
+ if url is None:
+ self.error(_("Download link not found"))
+
+ self.download(str(url.group(1)))
diff --git a/pyload/plugin/hoster/NowVideoSx.py b/pyload/plugin/hoster/NowVideoSx.py
new file mode 100644
index 000000000..3c747c253
--- /dev/null
+++ b/pyload/plugin/hoster/NowVideoSx.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class NowVideoSx(SimpleHoster):
+ __name__ = "NowVideoSx"
+ __type__ = "hoster"
+ __version__ = "0.10"
+
+ __pattern__ = r'http://(?:www\.)?nowvideo\.(at|ch|co|eu|li|sx)/(video|mobile/#/videos)/(?P<ID>\w+)'
+
+ __description__ = """NowVideo.sx hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ URL_REPLACEMENTS = [(__pattern__ + ".*", r'http://www.nowvideo.sx/video/\g<ID>')]
+
+ NAME_PATTERN = r'<h4>(?P<N>.+?)<'
+ OFFLINE_PATTERN = r'>This file no longer exists'
+
+ LINK_FREE_PATTERN = r'<source src="(.+?)"'
+ LINK_PREMIUM_PATTERN = r'<div id="content_player" >\s*<a href="(.+?)"'
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = True
+
+
+ def handleFree(self, pyfile):
+ self.html = self.load("http://www.nowvideo.sx/mobile/video.php", get={'id': self.info['pattern']['ID']})
+
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("Free download link not found"))
+
+ self.download(m.group(1))
diff --git a/module/plugins/hoster/OboomCom.py b/pyload/plugin/hoster/OboomCom.py
index 43d41c538..43d41c538 100644
--- a/module/plugins/hoster/OboomCom.py
+++ b/pyload/plugin/hoster/OboomCom.py
diff --git a/pyload/plugin/hoster/OneFichierCom.py b/pyload/plugin/hoster/OneFichierCom.py
new file mode 100644
index 000000000..b9756e7ff
--- /dev/null
+++ b/pyload/plugin/hoster/OneFichierCom.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class OneFichierCom(SimpleHoster):
+ __name__ = "OneFichierCom"
+ __type__ = "hoster"
+ __version__ = "0.78"
+
+ __pattern__ = r'https?://(?:www\.)?(?:(?P<ID1>\w+)\.)?(?P<HOST>1fichier\.com|alterupload\.com|cjoint\.net|d(es)?fichiers\.com|dl4free\.com|megadl\.fr|mesfichiers\.org|piecejointe\.net|pjointe\.com|tenvoi\.com)(?:/\?(?P<ID2>\w+))?'
+
+ __description__ = """1fichier.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("fragonib", "fragonib[AT]yahoo[DOT]es"),
+ ("the-razer", "daniel_ AT gmx DOT net"),
+ ("zoidberg", "zoidberg@mujmail.cz"),
+ ("imclem", ""),
+ ("stickell", "l.stickell@yahoo.it"),
+ ("Elrick69", "elrick69[AT]rocketmail[DOT]com"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ NAME_PATTERN = r'>FileName :</td>\s*<td.*>(?P<N>.+?)<'
+ SIZE_PATTERN = r'>Size :</td>\s*<td.*>(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+
+ OFFLINE_PATTERN = r'File not found !\s*<'
+
+ COOKIES = [("1fichier.com", "LG", "en")]
+ DISPOSITION = False #: Remove in 0.4.10
+
+ WAIT_PATTERN = r'>You must wait (\d+) minutes'
+
+
+ def setup(self):
+ self.multiDL = self.premium
+ self.resumeDownload = True
+
+
+ def handleFree(self, pyfile):
+ id = self.info['pattern']['ID1'] or self.info['pattern']['ID2']
+ url, inputs = self.parseHtmlForm('action="https://1fichier.com/\?%s' % id)
+
+ if not url:
+ self.fail(_("Download link not found"))
+
+ if "pass" in inputs:
+ inputs['pass'] = self.getPassword()
+
+ inputs['submit'] = "Download"
+
+ self.download(url, post=inputs)
+
+
+ def handlePremium(self, pyfile):
+ self.download(pyfile.url, post={'dl': "Download", 'did': 0})
diff --git a/pyload/plugin/hoster/OronCom.py b/pyload/plugin/hoster/OronCom.py
new file mode 100644
index 000000000..f28d34391
--- /dev/null
+++ b/pyload/plugin/hoster/OronCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class OronCom(DeadHoster):
+ __name__ = "OronCom"
+ __type__ = "hoster"
+ __version__ = "0.14"
+
+ __pattern__ = r'https?://(?:www\.)?oron\.com/\w{12}'
+
+ __description__ = """Oron.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("chrox", "chrox@pyload.org"),
+ ("DHMH", "DHMH@pyload.org")]
diff --git a/pyload/plugin/hoster/OverLoadMe.py b/pyload/plugin/hoster/OverLoadMe.py
new file mode 100644
index 000000000..8c0436d78
--- /dev/null
+++ b/pyload/plugin/hoster/OverLoadMe.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from random import randrange
+from urllib import unquote
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHoster import MultiHoster
+from pyload.utils import parseFileSize
+
+
+class OverLoadMe(MultiHoster):
+ __name__ = "OverLoadMe"
+ __type__ = "hoster"
+ __version__ = "0.09"
+
+ __pattern__ = r'https?://.*overload\.me/.+'
+
+ __description__ = """Over-Load.me multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("marley", "marley@over-load.me")]
+
+
+ def getFilename(self, url):
+ try:
+ name = unquote(url.rsplit("/", 1)[1])
+ except IndexError:
+ name = "Unknown_Filename..."
+
+ if name.endswith("..."): #: incomplete filename, append random stuff
+ name += "%s.tmp" % randrange(100, 999)
+
+ return name
+
+
+ def setup(self):
+ self.chunkLimit = 5
+
+
+ def handlePremium(self, pyfile):
+ https = "https" if self.getConfig("ssl") else "http"
+ data = self.account.getAccountData(self.user)
+ page = self.load(https + "://api.over-load.me/getdownload.php",
+ get={'auth': data['password'],
+ 'link': pyfile.url})
+
+ data = json_loads(page)
+
+ self.logDebug(data)
+
+ if data['error'] == 1:
+ self.logWarning(data['msg'])
+ self.tempOffline()
+ else:
+ if pyfile.name is not None and pyfile.name.endswith('.tmp') and data['filename']:
+ pyfile.name = data['filename']
+ pyfile.size = parseFileSize(data['filesize'])
+
+ http_repl = ["http://", "https://"]
+ self.link = data['downloadlink'].replace(*http_repl if self.getConfig("ssl") else *http_repl[::-1])
+
+ if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown") or pyfile.name.endswith('..'):
+ # only use when name wasn't already set
+ pyfile.name = self.getFilename(self.link)
+
+
+ def checkFile(self):
+ if self.checkDownload({"error": "<title>An error occured while processing your request</title>"})
+ # usual this download can safely be retried
+ self.retry(wait_time=60, reason=_("An error occured while generating link."))
+
+ return super(OverLoadMe, self).checkFile()
diff --git a/pyload/plugin/hoster/PandaplaNet.py b/pyload/plugin/hoster/PandaplaNet.py
new file mode 100644
index 000000000..b9d5b6e5a
--- /dev/null
+++ b/pyload/plugin/hoster/PandaplaNet.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class PandaplaNet(DeadHoster):
+ __name__ = "PandaplaNet"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?pandapla\.net/\w{12}'
+
+ __description__ = """Pandapla.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("t4skforce", "t4skforce1337[AT]gmail[DOT]com")]
diff --git a/module/plugins/hoster/PornhostCom.py b/pyload/plugin/hoster/PornhostCom.py
index 70ce4f32e..70ce4f32e 100644
--- a/module/plugins/hoster/PornhostCom.py
+++ b/pyload/plugin/hoster/PornhostCom.py
diff --git a/module/plugins/hoster/PornhubCom.py b/pyload/plugin/hoster/PornhubCom.py
index 9f8a5eec2..9f8a5eec2 100644
--- a/module/plugins/hoster/PornhubCom.py
+++ b/pyload/plugin/hoster/PornhubCom.py
diff --git a/pyload/plugin/hoster/PotloadCom.py b/pyload/plugin/hoster/PotloadCom.py
new file mode 100644
index 000000000..4845299a5
--- /dev/null
+++ b/pyload/plugin/hoster/PotloadCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class PotloadCom(DeadHoster):
+ __name__ = "PotloadCom"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?potload\.com/\w{12}'
+
+ __description__ = """Potload.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
diff --git a/pyload/plugin/hoster/PremiumTo.py b/pyload/plugin/hoster/PremiumTo.py
new file mode 100644
index 000000000..07945f873
--- /dev/null
+++ b/pyload/plugin/hoster/PremiumTo.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+from os import remove
+
+from pyload.plugin.internal.MultiHoster import MultiHoster
+from pyload.utils import fs_encode
+
+
+class PremiumTo(MultiHoster):
+ __name__ = "PremiumTo"
+ __type__ = "hoster"
+ __version__ = "0.21"
+
+ __pattern__ = r'^unmatchable$'
+
+ __description__ = """Premium.to multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("zoidberg", "zoidberg@mujmail.cz"),
+ ("stickell", "l.stickell@yahoo.it")]
+
+
+ CHECK_TRAFFIC = True
+
+
+ def handlePremium(self, pyfile):
+ #raise timeout to 2min
+ self.download("http://premium.to/api/getfile.php",
+ get={'username': self.account.username,
+ 'password': self.account.password,
+ 'link' : pyfile.url},
+ disposition=True)
+
+
+ def checkFile(self):
+ if self.checkDownload({'nopremium': "No premium account available"}):
+ self.retry(60, 5 * 60, "No premium account available")
+
+ err = ''
+ if self.req.http.code == '420':
+ # Custom error code send - fail
+ file = fs_encode(self.lastDownload)
+ with open(file, "rb") as f:
+ err = f.read(256).strip()
+ remove(file)
+
+ if err:
+ self.fail(err)
+
+ return super(PremiumTo, self).checkFile()
diff --git a/pyload/plugin/hoster/PremiumizeMe.py b/pyload/plugin/hoster/PremiumizeMe.py
new file mode 100644
index 000000000..c1153280b
--- /dev/null
+++ b/pyload/plugin/hoster/PremiumizeMe.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHoster import MultiHoster
+
+
+class PremiumizeMe(MultiHoster):
+ __name__ = "PremiumizeMe"
+ __type__ = "hoster"
+ __version__ = "0.16"
+
+ __pattern__ = r'^unmatchable$' #: Since we want to allow the user to specify the list of hoster to use we let MultiHoster.activate
+
+ __description__ = """Premiumize.me multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Florian Franzen", "FlorianFranzen@gmail.com")]
+
+
+ def handlePremium(self, pyfile):
+ # In some cases hostsers do not supply us with a filename at download, so we
+ # are going to set a fall back filename (e.g. for freakshare or xfileshare)
+ pyfile.name = pyfile.name.split('/').pop() # Remove everthing before last slash
+
+ # Correction for automatic assigned filename: Removing html at end if needed
+ suffix_to_remove = ["html", "htm", "php", "php3", "asp", "shtm", "shtml", "cfml", "cfm"]
+ temp = pyfile.name.split('.')
+ if temp.pop() in suffix_to_remove:
+ pyfile.name = ".".join(temp)
+
+ # Get account data
+ user, data = self.account.selectAccount()
+
+ # Get rewritten link using the premiumize.me api v1 (see https://secure.premiumize.me/?show=api)
+ data = json_loads(self.load("https://api.premiumize.me/pm-api/v1.php",
+ get={'method' : "directdownloadlink",
+ 'params[login]': user,
+ 'params[pass]' : data['password'],
+ 'params[link]' : pyfile.url}))
+
+ # Check status and decide what to do
+ status = data['status']
+
+ if status == 200:
+ self.link = data['result']['location']
+ return
+
+ elif status == 400:
+ self.fail(_("Invalid link"))
+
+ elif status == 404:
+ self.offline()
+
+ elif status >= 500:
+ self.tempOffline()
+
+ else:
+ self.fail(data['statusmessage'])
diff --git a/pyload/plugin/hoster/PromptfileCom.py b/pyload/plugin/hoster/PromptfileCom.py
new file mode 100644
index 000000000..fb8c907e5
--- /dev/null
+++ b/pyload/plugin/hoster/PromptfileCom.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class PromptfileCom(SimpleHoster):
+ __name__ = "PromptfileCom"
+ __type__ = "hoster"
+ __version__ = "0.13"
+
+ __pattern__ = r'https?://(?:www\.)?promptfile\.com/'
+
+ __description__ = """Promptfile.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("igel", "igelkun@myopera.com")]
+
+
+ INFO_PATTERN = r'<span style="[^"]*" title="[^"]*">(?P<N>.*?) \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)</span>'
+ OFFLINE_PATTERN = r'<span style="[^"]*" title="File Not Found">File Not Found</span>'
+
+ CHASH_PATTERN = r'<input type="hidden" name="chash" value="([^"]*)" />'
+ LINK_FREE_PATTERN = r'<a href=\"(.+)\" target=\"_blank\" class=\"view_dl_link\">Download File</a>'
+
+
+ def handleFree(self, pyfile):
+ # STAGE 1: get link to continue
+ m = re.search(self.CHASH_PATTERN, self.html)
+ if m is None:
+ self.error(_("CHASH_PATTERN not found"))
+ chash = m.group(1)
+ self.logDebug("Read chash %s" % chash)
+ # continue to stage2
+ self.html = self.load(pyfile.url, decode=True, post={'chash': chash})
+
+ # STAGE 2: get the direct link
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("LINK_FREE_PATTERN not found"))
+
+ self.link = m.group(1)
diff --git a/pyload/plugin/hoster/PrzeklejPl.py b/pyload/plugin/hoster/PrzeklejPl.py
new file mode 100644
index 000000000..bfb27834a
--- /dev/null
+++ b/pyload/plugin/hoster/PrzeklejPl.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class PrzeklejPl(DeadHoster):
+ __name__ = "PrzeklejPl"
+ __type__ = "hoster"
+ __version__ = "0.11"
+
+ __pattern__ = r'http://(?:www\.)?przeklej\.pl/plik/.+'
+
+ __description__ = """Przeklej.pl hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/PutdriveCom.py b/pyload/plugin/hoster/PutdriveCom.py
new file mode 100644
index 000000000..562951e81
--- /dev/null
+++ b/pyload/plugin/hoster/PutdriveCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.hoster.ZeveraCom import ZeveraCom
+
+
+class PutdriveCom(ZeveraCom):
+ __name__ = "PutdriveCom"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'https?://(?:www\.)putdrive\.com/(getFiles\.ashx|Members/download\.ashx)\?.*ourl=.+'
+
+ __description__ = """Multihosters.com multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
diff --git a/pyload/plugin/hoster/QuickshareCz.py b/pyload/plugin/hoster/QuickshareCz.py
new file mode 100644
index 000000000..9300d230b
--- /dev/null
+++ b/pyload/plugin/hoster/QuickshareCz.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class QuickshareCz(SimpleHoster):
+ __name__ = "QuickshareCz"
+ __type__ = "hoster"
+ __version__ = "0.56"
+
+ __pattern__ = r'http://(?:[^/]*\.)?quickshare\.cz/stahnout-soubor/.+'
+
+ __description__ = """Quickshare.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<th width="145px">Název:</th>\s*<td style="word-wrap:break-word;">(?P<N>[^<]+)</td>'
+ SIZE_PATTERN = r'<th>Velikost:</th>\s*<td>(?P<S>[\d.,]+) (?P<U>[\w^_]+)</td>'
+ OFFLINE_PATTERN = r'<script type="text/javascript">location\.href=\'/chyba\';</script>'
+
+
+ def process(self, pyfile):
+ self.html = self.load(pyfile.url, decode=True)
+ self.getFileInfo()
+
+ # parse js variables
+ self.jsvars = dict((x, y.strip("'")) for x, y in re.findall(r"var (\w+) = ([\d.]+|'[^']*')", self.html))
+ self.logDebug(self.jsvars)
+ pyfile.name = self.jsvars['ID3']
+
+ # determine download type - free or premium
+ if self.premium:
+ if 'UU_prihlasen' in self.jsvars:
+ if self.jsvars['UU_prihlasen'] == '0':
+ self.logWarning(_("User not logged in"))
+ self.relogin(self.user)
+ self.retry()
+ elif float(self.jsvars['UU_kredit']) < float(self.jsvars['kredit_odecet']):
+ self.logWarning(_("Not enough credit left"))
+ self.premium = False
+
+ if self.premium:
+ self.handlePremium(pyfile)
+ else:
+ self.handleFree(pyfile)
+
+ if self.checkDownload({"error": re.compile(r"\AChyba!")}, max_size=100):
+ self.fail(_("File not m or plugin defect"))
+
+
+ def handleFree(self, pyfile):
+ # get download url
+ download_url = '%s/download.php' % self.jsvars['server']
+ data = dict((x, self.jsvars[x]) for x in self.jsvars if x in ("ID1", "ID2", "ID3", "ID4"))
+ self.logDebug("FREE URL1:" + download_url, data)
+
+ self.load(download_url, post=data, follow_location=False)
+ self.header = self.req.http.header
+
+ m = re.search(r'Location\s*:\s*(.+)', self.header, re.I)
+ if m is None:
+ self.fail(_("File not found"))
+ download_url = m.group(1)
+ self.logDebug("FREE URL2:" + download_url)
+
+ # check errors
+ m = re.search(r'/chyba/(\d+)', download_url)
+ if m:
+ if m.group(1) == '1':
+ self.retry(60, 2 * 60, "This IP is already downloading")
+ elif m.group(1) == '2':
+ self.retry(60, 60, "No free slots available")
+ else:
+ self.fail(_("Error %d") % m.group(1))
+
+ # download file
+ self.download(download_url)
+
+
+ def handlePremium(self, pyfile):
+ download_url = '%s/download_premium.php' % self.jsvars['server']
+ data = dict((x, self.jsvars[x]) for x in self.jsvars if x in ("ID1", "ID2", "ID4", "ID5"))
+ self.download(download_url, get=data)
diff --git a/pyload/plugin/hoster/RPNetBiz.py b/pyload/plugin/hoster/RPNetBiz.py
new file mode 100644
index 000000000..af56d8162
--- /dev/null
+++ b/pyload/plugin/hoster/RPNetBiz.py
@@ -0,0 +1,77 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.MultiHoster import MultiHoster
+from pyload.utils import json_loads
+
+
+class RPNetBiz(MultiHoster):
+ __name__ = "RPNetBiz"
+ __type__ = "hoster"
+ __version__ = "0.14"
+
+ __description__ = """RPNet.biz multi-hoster plugin"""
+ __license__ = "GPLv3"
+
+ __pattern__ = r'https?://.+rpnet\.biz'
+ __authors__ = [("Dman", "dmanugm@gmail.com")]
+
+
+ def setup(self):
+ self.chunkLimit = -1
+
+
+ def handlePremium(self, pyfile):
+ user, data = self.account.selectAccount()
+
+ # Get the download link
+ res = self.load("https://premium.rpnet.biz/client_api.php",
+ get={"username": user,
+ "password": data['password'],
+ "action" : "generate",
+ "links" : pyfile.url})
+
+ self.logDebug("JSON data: %s" % res)
+ link_status = json_loads(res)['links'][0] # get the first link... since we only queried one
+
+ # Check if we only have an id as a HDD link
+ if 'id' in link_status:
+ self.logDebug("Need to wait at least 30 seconds before requery")
+ self.setWait(30) # wait for 30 seconds
+ self.wait()
+ # Lets query the server again asking for the status on the link,
+ # we need to keep doing this until we reach 100
+ max_tries = 30
+ my_try = 0
+ while (my_try <= max_tries):
+ self.logDebug("Try: %d ; Max Tries: %d" % (my_try, max_tries))
+ res = self.load("https://premium.rpnet.biz/client_api.php",
+ get={"username": user,
+ "password": data['password'],
+ "action": "downloadInformation",
+ "id": link_status['id']})
+ self.logDebug("JSON data hdd query: %s" % res)
+ download_status = json_loads(res)['download']
+
+ if download_status['status'] == '100':
+ link_status['generated'] = download_status['rpnet_link']
+ self.logDebug("Successfully downloaded to rpnet HDD: %s" % link_status['generated'])
+ break
+ else:
+ self.logDebug("At %s%% for the file download" % download_status['status'])
+
+ self.setWait(30)
+ self.wait()
+ my_try += 1
+
+ if my_try > max_tries: # We went over the limit!
+ self.fail(_("Waited for about 15 minutes for download to finish but failed"))
+
+ if 'generated' in link_status:
+ self.link = link_status['generated']
+ return
+ elif 'error' in link_status:
+ self.fail(link_status['error'])
+ else:
+ self.fail(_("Something went wrong, not supposed to enter here"))
diff --git a/pyload/plugin/hoster/RapideoPl.py b/pyload/plugin/hoster/RapideoPl.py
new file mode 100644
index 000000000..9e9bbf58b
--- /dev/null
+++ b/pyload/plugin/hoster/RapideoPl.py
@@ -0,0 +1,103 @@
+# -*- coding: utf-8 -*-
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHoster import MultiHoster
+
+
+class RapideoPl(MultiHoster):
+ __name__ = "RapideoPl"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'^unmatchable$'
+
+ __description__ = """Rapideo.pl multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("goddie", "dev@rapideo.pl")]
+
+
+ API_URL = "http://enc.rapideo.pl"
+
+ API_QUERY = {'site' : "newrd",
+ 'output' : "json",
+ 'username': "",
+ 'password': "",
+ 'url' : ""}
+
+ ERROR_CODES = {0 : "[%s] Incorrect login credentials",
+ 1 : "[%s] Not enough transfer to download - top-up your account",
+ 2 : "[%s] Incorrect / dead link",
+ 3 : "[%s] Error connecting to hosting, try again later",
+ 9 : "[%s] Premium account has expired",
+ 15: "[%s] Hosting no longer supported",
+ 80: "[%s] Too many incorrect login attempts, account blocked for 24h"}
+
+
+ def prepare(self):
+ super(RapideoPl, self).prepare()
+
+ data = self.account.getAccountData(self.user)
+
+ self.usr = data['usr']
+ self.pwd = data['pwd']
+
+
+ def runFileQuery(self, url, mode=None):
+ query = self.API_QUERY.copy()
+
+ query["username"] = self.usr
+ query["password"] = self.pwd
+ query["url"] = url
+
+ if mode == "fileinfo":
+ query['check'] = 2
+ query['loc'] = 1
+
+ self.logDebug(query)
+
+ return self.load(self.API_URL, post=query)
+
+
+ def handleFree(self, pyfile):
+ try:
+ data = self.runFileQuery(pyfile.url, 'fileinfo')
+
+ except Exception:
+ self.logDebug("RunFileQuery error")
+ self.tempOffline()
+
+ try:
+ parsed = json_loads(data)
+
+ except Exception:
+ self.logDebug("Loads error")
+ self.tempOffline()
+
+ self.logDebug(parsed)
+
+ if "errno" in parsed.keys():
+ if parsed["errno"] in self.ERROR_CODES:
+ # error code in known
+ self.fail(self.ERROR_CODES[parsed["errno"]] % self.__name__)
+ else:
+ # error code isn't yet added to plugin
+ self.fail(
+ parsed["errstring"]
+ or _("Unknown error (code: %s)") % parsed["errno"]
+ )
+
+ if "sdownload" in parsed:
+ if parsed["sdownload"] == "1":
+ self.fail(
+ _("Download from %s is possible only using Rapideo.pl website \
+ directly") % parsed["hosting"])
+
+ pyfile.name = parsed["filename"]
+ pyfile.size = parsed["filesize"]
+
+ try:
+ self.link = self.runFileQuery(pyfile.url, 'filedownload')
+
+ except Exception:
+ self.logDebug("runFileQuery error #2")
+ self.tempOffline()
diff --git a/pyload/plugin/hoster/RapidfileshareNet.py b/pyload/plugin/hoster/RapidfileshareNet.py
new file mode 100644
index 000000000..1b1895b39
--- /dev/null
+++ b/pyload/plugin/hoster/RapidfileshareNet.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class RapidfileshareNet(XFSHoster):
+ __name__ = "RapidfileshareNet"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?rapidfileshare\.net/\w{12}'
+
+ __description__ = """Rapidfileshare.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("guidobelix", "guidobelix@hotmail.it")]
+
+
+ NAME_PATTERN = r'<input type="hidden" name="fname" value="(?P<N>.+?)">'
+ SIZE_PATTERN = r'>http://www.rapidfileshare.net/\w+?</font> \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)</font>'
+
+ OFFLINE_PATTERN = r'>No such file with this filename'
+ TEMP_OFFLINE_PATTERN = r'The page may have been renamed, removed or be temporarily unavailable.<'
diff --git a/pyload/plugin/hoster/RapidgatorNet.py b/pyload/plugin/hoster/RapidgatorNet.py
new file mode 100644
index 000000000..8cd883537
--- /dev/null
+++ b/pyload/plugin/hoster/RapidgatorNet.py
@@ -0,0 +1,169 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pycurl import HTTPHEADER
+
+from pyload.utils import json_loads
+from pyload.network.HTTPRequest import BadHeader
+from pyload.plugin.internal.CaptchaService import AdsCaptcha, ReCaptcha, SolveMedia
+from pyload.plugin.internal.SimpleHoster import SimpleHoster, secondsToMidnight
+
+
+class RapidgatorNet(SimpleHoster):
+ __name__ = "RapidgatorNet"
+ __type__ = "hoster"
+ __version__ = "0.32"
+
+ __pattern__ = r'http://(?:www\.)?(rapidgator\.net|rg\.to)/file/\w+'
+
+ __description__ = """Rapidgator.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
+ ("chrox", ""),
+ ("stickell", "l.stickell@yahoo.it"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ API_URL = "http://rapidgator.net/api/file"
+
+ COOKIES = [("rapidgator.net", "lang", "en")]
+
+ NAME_PATTERN = r'<title>Download file (?P<N>.*)</title>'
+ SIZE_PATTERN = r'File size:\s*<strong>(?P<S>[\d.,]+) (?P<U>[\w^_]+)</strong>'
+ OFFLINE_PATTERN = r'>(File not found|Error 404)'
+
+ JSVARS_PATTERN = r'\s+var\s*(startTimerUrl|getDownloadUrl|captchaUrl|fid|secs)\s*=\s*\'?(.*?)\'?;'
+
+ PREMIUM_ONLY_PATTERN = r'You can download files up to|This file can be downloaded by premium only<'
+ ERROR_PATTERN = r'You have reached your (daily|hourly) downloads limit'
+ WAIT_PATTERN = r'(Delay between downloads must be not less than|Try again in).+'
+
+ LINK_FREE_PATTERN = r'return \'(http://\w+.rapidgator.net/.*)\';'
+
+ RECAPTCHA_PATTERN = r'"http://api\.recaptcha\.net/challenge\?k=(.*?)"'
+ ADSCAPTCHA_PATTERN = r'(http://api\.adscaptcha\.com/Get\.aspx[^"\']*)'
+ SOLVEMEDIA_PATTERN = r'http://api\.solvemedia\.com/papi/challenge\.script\?k=(.*?)"'
+
+
+ def setup(self):
+ if self.account:
+ self.sid = self.account.getAccountInfo(self.user).get('sid', None)
+ else:
+ self.sid = None
+
+ if self.sid:
+ self.premium = True
+
+ self.resumeDownload = self.multiDL = self.premium
+ self.chunkLimit = 1
+
+
+ def api_response(self, cmd):
+ try:
+ json = self.load('%s/%s' % (self.API_URL, cmd),
+ get={'sid': self.sid,
+ 'url': self.pyfile.url}, decode=True)
+ self.logDebug("API:%s" % cmd, json, "SID: %s" % self.sid)
+ json = json_loads(json)
+ status = json['response_status']
+ msg = json['response_details']
+
+ except BadHeader, e:
+ self.logError("API: %s" % cmd, e, "SID: %s" % self.sid)
+ status = e.code
+ msg = e
+
+ if status == 200:
+ return json['response']
+
+ elif status == 423:
+ self.account.empty(self.user)
+ self.retry()
+
+ else:
+ self.account.relogin(self.user)
+ self.retry(wait_time=60)
+
+
+ def handlePremium(self, pyfile):
+ self.api_data = self.api_response('info')
+ self.api_data['md5'] = self.api_data['hash']
+
+ pyfile.name = self.api_data['filename']
+ pyfile.size = self.api_data['size']
+
+ self.link = self.api_response('download')['url']
+
+
+ def handleFree(self, pyfile):
+ jsvars = dict(re.findall(self.JSVARS_PATTERN, self.html))
+ self.logDebug(jsvars)
+
+ self.req.http.lastURL = pyfile.url
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
+
+ url = "http://rapidgator.net%s?fid=%s" % (
+ jsvars.get('startTimerUrl', '/download/AjaxStartTimer'), jsvars['fid'])
+ jsvars.update(self.getJsonResponse(url))
+
+ self.wait(jsvars.get('secs', 45), False)
+
+ url = "http://rapidgator.net%s?sid=%s" % (
+ jsvars.get('getDownloadUrl', '/download/AjaxGetDownload'), jsvars['sid'])
+ jsvars.update(self.getJsonResponse(url))
+
+ self.req.http.lastURL = pyfile.url
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With:"])
+
+ url = "http://rapidgator.net%s" % jsvars.get('captchaUrl', '/download/captcha')
+ self.html = self.load(url)
+
+ for _i in xrange(5):
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m:
+ self.link = m.group(1)
+ break
+ else:
+ captcha, captcha_key = self.handleCaptcha()
+ response, challenge = captcha.challenge(captcha_key)
+
+ self.html = self.load(url, post={'DownloadCaptchaForm[captcha]': "",
+ 'adcopy_challenge' : challenge,
+ 'adcopy_response' : response})
+
+ if "The verification code is incorrect" in self.html:
+ self.invalidCaptcha()
+ else:
+ self.correctCaptcha()
+ else:
+ self.error(_("Download link"))
+
+
+ def handleCaptcha(self):
+ m = re.search(self.ADSCAPTCHA_PATTERN, self.html)
+ if m:
+ captcha_key = m.group(1)
+ captcha = AdsCaptcha(self)
+ else:
+ m = re.search(self.RECAPTCHA_PATTERN, self.html)
+ if m:
+ captcha_key = m.group(1)
+ captcha = ReCaptcha(self)
+ else:
+ m = re.search(self.SOLVEMEDIA_PATTERN, self.html)
+ if m:
+ captcha_key = m.group(1)
+ captcha = SolveMedia(self)
+ else:
+ self.error(_("Captcha"))
+
+ return captcha, captcha_key
+
+
+ def getJsonResponse(self, url):
+ res = self.load(url, decode=True)
+ if not res.startswith('{'):
+ self.retry()
+ self.logDebug(url, res)
+ return json_loads(res)
diff --git a/pyload/plugin/hoster/RapiduNet.py b/pyload/plugin/hoster/RapiduNet.py
new file mode 100644
index 000000000..1e12ab776
--- /dev/null
+++ b/pyload/plugin/hoster/RapiduNet.py
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pycurl import HTTPHEADER
+from time import time, altzone
+
+from pyload.utils import json_loads
+from pyload.plugin.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class RapiduNet(SimpleHoster):
+ __name__ = "RapiduNet"
+ __type__ = "hoster"
+ __version__ = "0.07"
+
+ __pattern__ = r'https?://(?:www\.)?rapidu\.net/(?P<ID>\d{10})'
+
+ __description__ = """Rapidu.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("prOq", "")]
+
+
+ COOKIES = [("rapidu.net", "rapidu_lang", "en")]
+
+ INFO_PATTERN = r'<h1 title="(?P<N>.*)">.*</h1>\s*<small>(?P<S>\d+(\.\d+)?)\s(?P<U>\w+)</small>'
+ OFFLINE_PATTERN = r'404 - File not found'
+
+ ERROR_PATTERN = r'<div class="error">'
+
+ RECAPTCHA_KEY = r'6Ld12ewSAAAAAHoE6WVP_pSfCdJcBQScVweQh8Io'
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = self.premium
+
+
+ def handleFree(self, pyfile):
+ self.req.http.lastURL = pyfile.url
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
+
+ jsvars = self.getJsonResponse("https://rapidu.net/ajax.php",
+ get={'a': "getLoadTimeToDownload"},
+ post={'_go': ""},
+ decode=True)
+
+ if str(jsvars['timeToDownload']) is "stop":
+ t = (24 * 60 * 60) - (int(time()) % (24 * 60 * 60)) + altzone
+
+ self.logInfo("You've reach your daily download transfer")
+
+ self.retry(10, 10 if t < 1 else None, _("Try tomorrow again")) #@NOTE: check t in case of not synchronised clock
+
+ else:
+ self.wait(int(jsvars['timeToDownload']) - int(time()))
+
+ recaptcha = ReCaptcha(self)
+
+ for _i in xrange(10):
+ response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY)
+
+ jsvars = self.getJsonResponse("https://rapidu.net/ajax.php",
+ get={'a': "getCheckCaptcha"},
+ post={'_go' : "",
+ 'captcha1': challenge,
+ 'captcha2': response,
+ 'fileId' : self.info['pattern']['ID']},
+ decode=True)
+ if jsvars['message'] == 'success':
+ self.download(jsvars['url'])
+ break
+
+
+ def getJsonResponse(self, *args, **kwargs):
+ res = self.load(*args, **kwargs)
+ if not res.startswith('{'):
+ self.retry()
+
+ self.logDebug(res)
+
+ return json_loads(res)
diff --git a/pyload/plugin/hoster/RarefileNet.py b/pyload/plugin/hoster/RarefileNet.py
new file mode 100644
index 000000000..1010c92ca
--- /dev/null
+++ b/pyload/plugin/hoster/RarefileNet.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class RarefileNet(XFSHoster):
+ __name__ = "RarefileNet"
+ __type__ = "hoster"
+ __version__ = "0.09"
+
+ __pattern__ = r'http://(?:www\.)?rarefile\.net/\w{12}'
+
+ __description__ = """Rarefile.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ LINK_PATTERN = r'<a href="(.+?)">\1</a>'
diff --git a/pyload/plugin/hoster/RealdebridCom.py b/pyload/plugin/hoster/RealdebridCom.py
new file mode 100644
index 000000000..ae6f69d7c
--- /dev/null
+++ b/pyload/plugin/hoster/RealdebridCom.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from random import randrange
+from urllib import unquote
+from time import time
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHoster import MultiHoster
+from pyload.utils import parseFileSize
+
+
+class RealdebridCom(MultiHoster):
+ __name__ = "RealdebridCom"
+ __type__ = "hoster"
+ __version__ = "0.64"
+
+ __pattern__ = r'https?://((?:www\.|s\d+\.)?real-debrid\.com/dl/|[\w^_]\.rdb\.so/d/)[\w^_]+'
+
+ __description__ = """Real-Debrid.com multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Devirex Hazzard", "naibaf_11@yahoo.de")]
+
+
+ def getFilename(self, url):
+ try:
+ name = unquote(url.rsplit("/", 1)[1])
+ except IndexError:
+ name = "Unknown_Filename..."
+ if not name or name.endswith(".."): #: incomplete filename, append random stuff
+ name += "%s.tmp" % randrange(100, 999)
+ return name
+
+
+ def setup(self):
+ self.chunkLimit = 3
+
+
+ def handlePremium(self, pyfile):
+ data = json_loads(self.load("https://real-debrid.com/ajax/unrestrict.php",
+ get={'lang' : "en",
+ 'link' : pyfile.url,
+ 'password': self.getPassword(),
+ 'time' : int(time() * 1000)}))
+
+ self.logDebug("Returned Data: %s" % data)
+
+ if data['error'] != 0:
+ if data['message'] == "Your file is unavailable on the hoster.":
+ self.offline()
+ else:
+ self.logWarning(data['message'])
+ self.tempOffline()
+ else:
+ if pyfile.name is not None and pyfile.name.endswith('.tmp') and data['file_name']:
+ pyfile.name = data['file_name']
+ pyfile.size = parseFileSize(data['file_size'])
+ self.link = data['generated_links'][0][-1]
+
+ if self.getConfig("ssl"):
+ self.link = self.link.replace("http://", "https://")
+ else:
+ self.link = self.link.replace("https://", "http://")
+
+ if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown") or pyfile.name.endswith('..'):
+ #only use when name wasnt already set
+ pyfile.name = self.getFilename(self.link)
+
+
+ def checkFile(self):
+ if self.checkDownload({"error": "<title>An error occured while processing your request</title>"}):
+ #usual this download can safely be retried
+ self.retry(wait_time=60, reason=_("An error occured while generating link"))
+
+ return super(RealdebridCom, self).checkFile()
diff --git a/module/plugins/hoster/RedtubeCom.py b/pyload/plugin/hoster/RedtubeCom.py
index 1f18d09c7..1f18d09c7 100644
--- a/module/plugins/hoster/RedtubeCom.py
+++ b/pyload/plugin/hoster/RedtubeCom.py
diff --git a/pyload/plugin/hoster/RehostTo.py b/pyload/plugin/hoster/RehostTo.py
new file mode 100644
index 000000000..3e3e88c6c
--- /dev/null
+++ b/pyload/plugin/hoster/RehostTo.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+
+from urllib import unquote
+
+from pyload.plugin.internal.MultiHoster import MultiHoster
+
+
+class RehostTo(MultiHoster):
+ __name__ = "RehostTo"
+ __type__ = "hoster"
+ __version__ = "0.21"
+
+ __pattern__ = r'https?://.*rehost\.to\..+'
+
+ __description__ = """Rehost.com multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org")]
+
+
+ def handlePremium(self, pyfile):
+ self.download("http://rehost.to/process_download.php",
+ get={'user': "cookie",
+ 'pass': self.account.getAccountInfo(self.user)['session'],
+ 'dl' : pyfile.url},
+ disposition=True)
diff --git a/pyload/plugin/hoster/RemixshareCom.py b/pyload/plugin/hoster/RemixshareCom.py
new file mode 100644
index 000000000..a1cd2a37e
--- /dev/null
+++ b/pyload/plugin/hoster/RemixshareCom.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# http://remixshare.com/download/p946u
+#
+# Note:
+# The remixshare.com website is very very slow, so
+# if your download not starts because of pycurl timeouts:
+# Adjust timeouts in /usr/share/pyload/pyload/network/HTTPRequest.py
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class RemixshareCom(SimpleHoster):
+ __name__ = "RemixshareCom"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'https?://remixshare\.com/(download|dl)/\w+'
+
+ __description__ = """Remixshare.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ INFO_PATTERN = r'title=\'.+?\'>(?P<N>.+?)</span><span class=\'light2\'>&nbsp;\((?P<S>\d+)&nbsp;(?P<U>[\w^_]+)\)<'
+ OFFLINE_PATTERN = r'<h1>Ooops!<'
+
+ LINK_FREE_PATTERN = r'(http://remixshare\.com/downloadfinal/.+?)"'
+ TOKEN_PATTERN = r'var acc = (\d+)'
+ WAIT_PATTERN = r'var XYZ = r"(\d+)"'
+
+
+ def setup(self):
+ self.multiDL = True
+ self.chunkLimit = 1
+
+
+ def handleFree(self, pyfile):
+ b = re.search(self.LINK_FREE_PATTERN, self.html)
+ if not b:
+ self.error(_("Cannot parse download url"))
+
+ c = re.search(self.TOKEN_PATTERN, self.html)
+ if not c:
+ self.error(_("Cannot parse file token"))
+
+ self.link = b.group(1) + c.group(1)
+
+ #Check if we have to wait
+ seconds = re.search(self.WAIT_PATTERN, self.html)
+ if seconds:
+ self.logDebug("Wait " + seconds.group(1))
+ self.wait(seconds.group(1))
diff --git a/pyload/plugin/hoster/RgHostNet.py b/pyload/plugin/hoster/RgHostNet.py
new file mode 100644
index 000000000..d9e548721
--- /dev/null
+++ b/pyload/plugin/hoster/RgHostNet.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class RgHostNet(SimpleHoster):
+ __name__ = "RgHostNet"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?rghost\.net/\d+(?:r=\d+)?'
+
+ __description__ = """RgHost.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("z00nx", "z00nx0@gmail.com")]
+
+
+ INFO_PATTERN = r'<h1>\s+(<a[^>]+>)?(?P<N>[^<]+)(</a>)?\s+<small[^>]+>\s+\((?P<S>[^)]+)\)\s+</small>\s+</h1>'
+ OFFLINE_PATTERN = r'File is deleted|this page is not found'
+
+ LINK_FREE_PATTERN = r'<a\s+href="([^"]+)"\s+class="btn\s+large\s+download"[^>]+>Download</a>'
diff --git a/pyload/plugin/hoster/SafesharingEu.py b/pyload/plugin/hoster/SafesharingEu.py
new file mode 100644
index 000000000..af046af62
--- /dev/null
+++ b/pyload/plugin/hoster/SafesharingEu.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class SafesharingEu(XFSHoster):
+ __name__ = "SafesharingEu"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'https?://(?:www\.)?safesharing\.eu/\w{12}'
+
+ __description__ = """Safesharing.eu hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
+
+
+ ERROR_PATTERN = r'(?:<div class="alert alert-danger">)(.+?)(?:</div>)'
diff --git a/pyload/plugin/hoster/SecureUploadEu.py b/pyload/plugin/hoster/SecureUploadEu.py
new file mode 100644
index 000000000..4db413c90
--- /dev/null
+++ b/pyload/plugin/hoster/SecureUploadEu.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class SecureUploadEu(XFSHoster):
+ __name__ = "SecureUploadEu"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'https?://(?:www\.)?secureupload\.eu/\w{12}'
+
+ __description__ = """SecureUpload.eu hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("z00nx", "z00nx0@gmail.com")]
+
+
+ INFO_PATTERN = r'<h3>Downloading (?P<N>[^<]+) \((?P<S>[^<]+)\)</h3>'
diff --git a/pyload/plugin/hoster/SendspaceCom.py b/pyload/plugin/hoster/SendspaceCom.py
new file mode 100644
index 000000000..4d477579d
--- /dev/null
+++ b/pyload/plugin/hoster/SendspaceCom.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class SendspaceCom(SimpleHoster):
+ __name__ = "SendspaceCom"
+ __type__ = "hoster"
+ __version__ = "0.17"
+
+ __pattern__ = r'https?://(?:www\.)?sendspace\.com/file/\w+'
+
+ __description__ = """Sendspace.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<h2 class="bgray">\s*<(?:b|strong)>(?P<N>[^<]+)</'
+ SIZE_PATTERN = r'<div class="file_description reverse margin_center">\s*<b>File Size:</b>\s*(?P<S>[\d.,]+)(?P<U>[\w^_]+)\s*</div>'
+ OFFLINE_PATTERN = r'<div class="msg error" style="cursor: default">Sorry, the file you requested is not available.</div>'
+
+ LINK_FREE_PATTERN = r'<a id="download_button" href="([^"]+)"'
+
+ CAPTCHA_PATTERN = r'<td><img src="(/captchas/captcha\.php?captcha=([^"]+))"></td>'
+ USER_CAPTCHA_PATTERN = r'<td><img src="/captchas/captcha\.php?user=([^"]+))"></td>'
+
+
+ def handleFree(self, pyfile):
+ params = {}
+ for _i in xrange(3):
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m:
+ if 'captcha_hash' in params:
+ self.correctCaptcha()
+ download_url = m.group(1)
+ break
+
+ m = re.search(self.CAPTCHA_PATTERN, self.html)
+ if m:
+ if 'captcha_hash' in params:
+ self.invalidCaptcha()
+ captcha_url1 = "http://www.sendspace.com/" + m.group(1)
+ m = re.search(self.USER_CAPTCHA_PATTERN, self.html)
+ captcha_url2 = "http://www.sendspace.com/" + m.group(1)
+ params = {'captcha_hash': m.group(2),
+ 'captcha_submit': 'Verify',
+ 'captcha_answer': self.decryptCaptcha(captcha_url1) + " " + self.decryptCaptcha(captcha_url2)}
+ else:
+ params = {'download': "Regular Download"}
+
+ self.logDebug(params)
+ self.html = self.load(pyfile.url, post=params)
+ else:
+ self.fail(_("Download link not found"))
+
+ self.download(download_url)
diff --git a/pyload/plugin/hoster/Share4WebCom.py b/pyload/plugin/hoster/Share4WebCom.py
new file mode 100644
index 000000000..f2b4e49e9
--- /dev/null
+++ b/pyload/plugin/hoster/Share4WebCom.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.hoster.UnibytesCom import UnibytesCom
+
+
+class Share4WebCom(UnibytesCom):
+ __name__ = "Share4WebCom"
+ __type__ = "hoster"
+ __version__ = "0.11"
+
+ __pattern__ = r'https?://(?:www\.)?share4web\.com/get/\w+'
+
+ __description__ = """Share4web.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ HOSTER_DOMAIN = "share4web.com"
diff --git a/pyload/plugin/hoster/Share76Com.py b/pyload/plugin/hoster/Share76Com.py
new file mode 100644
index 000000000..d460726f2
--- /dev/null
+++ b/pyload/plugin/hoster/Share76Com.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class Share76Com(DeadHoster):
+ __name__ = "Share76Com"
+ __type__ = "hoster"
+ __version__ = "0.04"
+
+ __pattern__ = r'http://(?:www\.)?share76\.com/\w{12}'
+
+ __description__ = """Share76.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = []
diff --git a/pyload/plugin/hoster/ShareFilesCo.py b/pyload/plugin/hoster/ShareFilesCo.py
new file mode 100644
index 000000000..edd56572e
--- /dev/null
+++ b/pyload/plugin/hoster/ShareFilesCo.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class ShareFilesCo(DeadHoster):
+ __name__ = "ShareFilesCo"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?sharefiles\.co/\w{12}'
+
+ __description__ = """Sharefiles.co hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
diff --git a/pyload/plugin/hoster/SharebeesCom.py b/pyload/plugin/hoster/SharebeesCom.py
new file mode 100644
index 000000000..54de21095
--- /dev/null
+++ b/pyload/plugin/hoster/SharebeesCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class SharebeesCom(DeadHoster):
+ __name__ = "SharebeesCom"
+ __type__ = "hoster"
+ __version__ = "0.02"
+
+ __pattern__ = r'http://(?:www\.)?sharebees\.com/\w{12}'
+
+ __description__ = """ShareBees hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/ShareonlineBiz.py b/pyload/plugin/hoster/ShareonlineBiz.py
new file mode 100644
index 000000000..f3be1aeb2
--- /dev/null
+++ b/pyload/plugin/hoster/ShareonlineBiz.py
@@ -0,0 +1,184 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from time import time
+from urllib import unquote
+from urlparse import urlparse
+
+from pyload.network.RequestFactory import getURL
+from pyload.plugin.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class ShareonlineBiz(SimpleHoster):
+ __name__ = "ShareonlineBiz"
+ __type__ = "hoster"
+ __version__ = "0.48"
+
+ __pattern__ = r'https?://(?:www\.)?(share-online\.biz|egoshare\.com)/(download\.php\?id=|dl/)(?P<ID>\w+)'
+
+ __description__ = """Shareonline.biz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("spoob", "spoob@pyload.org"),
+ ("mkaay", "mkaay@mkaay.de"),
+ ("zoidberg", "zoidberg@mujmail.cz"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ URL_REPLACEMENTS = [(__pattern__ + ".*", "http://www.share-online.biz/dl/\g<ID>")]
+
+ CHECK_TRAFFIC = True
+
+ RECAPTCHA_KEY = "6LdatrsSAAAAAHZrB70txiV5p-8Iv8BtVxlTtjKX"
+
+ ERROR_PATTERN = r'<p class="b">Information:</p>\s*<div>\s*<strong>(.*?)</strong>'
+
+
+ @classmethod
+ def getInfo(cls, url="", html=""):
+ info = {'name': urlparse(unquote(url)).path.split('/')[-1] or _("Unknown"), 'size': 0, 'status': 3 if url else 1, 'url': url}
+
+ if url:
+ info['pattern'] = re.match(cls.__pattern__, url).groupdict()
+
+ field = getURL("http://api.share-online.biz/linkcheck.php",
+ get={'md5': "1"},
+ post={'links': info['pattern']['ID']},
+ decode=True).split(";")
+
+ if field[1] == "OK":
+ info['fileid'] = field[0]
+ info['status'] = 2
+ info['name'] = field[2]
+ info['size'] = field[3] #: in bytes
+ info['md5'] = field[4].strip().lower().replace("\n\n", "") #: md5
+
+ elif field[1] in ("DELETED", "NOT FOUND"):
+ info['status'] = 1
+
+ return info
+
+
+ def setup(self):
+ self.resumeDownload = self.premium
+ self.multiDL = False
+
+
+ def handleCaptcha(self):
+ recaptcha = ReCaptcha(self)
+
+ for _i in xrange(5):
+ response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY)
+
+ m = re.search(r'var wait=(\d+);', self.html)
+ self.setWait(int(m.group(1)) if m else 30)
+
+ res = self.load("%s/free/captcha/%d" % (self.pyfile.url, int(time() * 1000)),
+ post={'dl_free' : "1",
+ 'recaptcha_challenge_field': challenge,
+ 'recaptcha_response_field' : response})
+ if not res == '0':
+ self.correctCaptcha()
+ return res
+ else:
+ self.invalidCaptcha()
+ else:
+ self.invalidCaptcha()
+ self.fail(_("No valid captcha solution received"))
+
+
+ def handleFree(self, pyfile):
+ self.wait(3)
+
+ self.html = self.load("%s/free/" % pyfile.url,
+ post={'dl_free': "1", 'choice': "free"},
+ decode=True)
+
+ self.checkErrors()
+
+ res = self.handleCaptcha()
+ download_url = res.decode('base64')
+
+ if not download_url.startswith("http://"):
+ self.error(_("Wrong download url"))
+
+ self.wait()
+
+ self.download(download_url)
+
+
+ def checkFile(self):
+ check = self.checkDownload({'cookie': re.compile(r'<div id="dl_failure"'),
+ 'fail' : re.compile(r"<title>Share-Online")})
+
+ if check == "cookie":
+ self.invalidCaptcha()
+ self.retry(5, 60, _("Cookie failure"))
+
+ elif check == "fail":
+ self.invalidCaptcha()
+ self.retry(5, 5 * 60, _("Download failed"))
+
+ return super(ShareonlineBiz, self).checkFile()
+
+
+ def handlePremium(self, pyfile): #: should be working better loading (account) api internally
+ html = self.load("http://api.share-online.biz/account.php",
+ get={'username': self.user,
+ 'password': self.account.getAccountData(self.user)['password'],
+ 'act' : "download",
+ 'lid' : self.info['fileid']})
+
+ self.api_data = dlinfo = {}
+
+ for line in html.splitlines():
+ key, value = line.split(": ")
+ dlinfo[key.lower()] = value
+
+ self.logDebug(dlinfo)
+
+ if not dlinfo['status'] == "online":
+ self.offline()
+ else:
+ pyfile.name = dlinfo['name']
+ pyfile.size = int(dlinfo['size'])
+
+ dlLink = dlinfo['url']
+
+ if dlLink == "server_under_maintenance":
+ self.tempOffline()
+ else:
+ self.multiDL = True
+ self.download(dlLink)
+
+
+ def checkErrors(self):
+ m = re.search(r"/failure/(.*?)/1", self.req.lastEffectiveURL)
+ if m is None:
+ self.info.pop('error', None)
+ return
+
+ errmsg = m.group(1).lower()
+
+ try:
+ self.logError(errmsg, re.search(self.ERROR_PATTERN, self.html).group(1))
+ except Exception:
+ self.logError("Unknown error occurred", errmsg)
+
+ if errmsg is "invalid":
+ self.fail(_("File not available"))
+
+ elif errmsg in ("freelimit", "size", "proxy"):
+ self.fail(_("Premium account needed"))
+
+ elif errmsg in ("expired", "server"):
+ self.retry(wait_time=600, reason=errmsg)
+
+ elif 'slot' in errmsg:
+ self.wantReconnect = True
+ self.retry(24, 3600, errmsg)
+
+ else:
+ self.wantReconnect = True
+ self.retry(wait_time=60, reason=errmsg)
diff --git a/module/plugins/hoster/ShareplaceCom.py b/pyload/plugin/hoster/ShareplaceCom.py
index 61e0f8723..61e0f8723 100644
--- a/module/plugins/hoster/ShareplaceCom.py
+++ b/pyload/plugin/hoster/ShareplaceCom.py
diff --git a/pyload/plugin/hoster/SharingmatrixCom.py b/pyload/plugin/hoster/SharingmatrixCom.py
new file mode 100644
index 000000000..d1892be14
--- /dev/null
+++ b/pyload/plugin/hoster/SharingmatrixCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class SharingmatrixCom(DeadHoster):
+ __name__ = "SharingmatrixCom"
+ __type__ = "hoster"
+ __version__ = "0.01"
+
+ __pattern__ = r'http://(?:www\.)?sharingmatrix\.com/file/\w+'
+
+ __description__ = """Sharingmatrix.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("jeix", "jeix@hasnomail.de"),
+ ("paulking", "")]
diff --git a/pyload/plugin/hoster/ShragleCom.py b/pyload/plugin/hoster/ShragleCom.py
new file mode 100644
index 000000000..628537108
--- /dev/null
+++ b/pyload/plugin/hoster/ShragleCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class ShragleCom(DeadHoster):
+ __name__ = "ShragleCom"
+ __type__ = "hoster"
+ __version__ = "0.22"
+
+ __pattern__ = r'http://(?:www\.)?(cloudnator|shragle)\.com/files/(?P<ID>.+?)/'
+
+ __description__ = """Cloudnator.com (Shragle.com) hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/SimplyPremiumCom.py b/pyload/plugin/hoster/SimplyPremiumCom.py
new file mode 100644
index 000000000..50b278985
--- /dev/null
+++ b/pyload/plugin/hoster/SimplyPremiumCom.py
@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from datetime import datetime, timedelta
+
+from pyload.plugin.internal.MultiHoster import MultiHoster
+from pyload.plugin.internal.SimpleHoster import secondsToMidnight
+
+
+class SimplyPremiumCom(MultiHoster):
+ __name__ = "SimplyPremiumCom"
+ __type__ = "hoster"
+ __version__ = "0.08"
+
+ __pattern__ = r'https?://.+simply-premium\.com'
+
+ __description__ = """Simply-Premium.com multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("EvolutionClip", "evolutionclip@live.de")]
+
+
+ def setup(self):
+ self.chunkLimit = 16
+
+
+ def checkErrors(self):
+ if '<valid>0</valid>' in self.html or (
+ "You are not allowed to download from this host" in self.html and self.premium):
+ self.account.relogin(self.user)
+ self.retry()
+
+ elif "NOTFOUND" in self.html:
+ self.offline()
+
+ elif "downloadlimit" in self.html:
+ self.logWarning(_("Reached maximum connctions"))
+ self.retry(5, 60, _("Reached maximum connctions"))
+
+ elif "trafficlimit" in self.html:
+ self.logWarning(_("Reached daily limit for this host"))
+ self.retry(wait_time=secondsToMidnight(gmt=2), reason="Daily limit for this host reached")
+
+ elif "hostererror" in self.html:
+ self.logWarning(_("Hoster temporarily unavailable, waiting 1 minute and retry"))
+ self.retry(5, 60, _("Hoster is temporarily unavailable"))
+
+
+ def handlePremium(self, pyfile):
+ for i in xrange(5):
+ self.html = self.load("http://www.simply-premium.com/premium.php", get={'info': "", 'link': self.pyfile.url})
+
+ if self.html:
+ self.logDebug("JSON data: " + self.html)
+ break
+ else:
+ self.logInfo(_("Unable to get API data, waiting 1 minute and retry"))
+ self.retry(5, 60, _("Unable to get API data"))
+
+ self.checkErrors()
+
+ try:
+ self.pyfile.name = re.search(r'<name>([^<]+)</name>', self.html).group(1)
+
+ except AttributeError:
+ self.pyfile.name = ""
+
+ try:
+ self.pyfile.size = re.search(r'<size>(\d+)</size>', self.html).group(1)
+
+ except AttributeError:
+ self.pyfile.size = 0
+
+ try:
+ self.link = re.search(r'<download>([^<]+)</download>', self.html).group(1)
+
+ except AttributeError:
+ self.link = 'http://www.simply-premium.com/premium.php?link=' + self.pyfile.url
diff --git a/pyload/plugin/hoster/SimplydebridCom.py b/pyload/plugin/hoster/SimplydebridCom.py
new file mode 100644
index 000000000..4b740ff20
--- /dev/null
+++ b/pyload/plugin/hoster/SimplydebridCom.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.MultiHoster import MultiHoster, replace_patterns
+
+
+class SimplydebridCom(MultiHoster):
+ __name__ = "SimplydebridCom"
+ __type__ = "hoster"
+ __version__ = "0.15"
+
+ __pattern__ = r'http://\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/sd\.php'
+
+ __description__ = """Simply-debrid.com multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Kagenoshin", "kagenoshin@gmx.ch")]
+
+
+ def handlePremium(self, pyfile):
+ #fix the links for simply-debrid.com!
+ self.link = replace_patterns(pyfile.url, [("clz.to", "cloudzer.net/file")
+ ("http://share-online", "http://www.share-online")
+ ("ul.to", "uploaded.net/file")
+ ("uploaded.com", "uploaded.net")
+ ("filerio.com", "filerio.in")
+ ("lumfile.com", "lumfile.se")]
+
+ if 'fileparadox' in self.link:
+ self.link = self.link.replace("http://", "https://")
+
+ self.html = self.load("http://simply-debrid.com/api.php", get={'dl': self.link})
+ if 'tiger Link' in self.html or 'Invalid Link' in self.html or ('API' in self.html and 'ERROR' in self.html):
+ self.error(_("Unable to unrestrict link"))
+
+ self.link = self.html
+
+ self.wait(5)
+
+
+ def checkFile(self):
+ if self.checkDownload({"error": "No address associated with hostname"}):
+ self.retry(24, 3 * 60, _("Bad file downloaded"))
+
+ return super(SimplydebridCom, self).checkFile()
diff --git a/pyload/plugin/hoster/SmoozedCom.py b/pyload/plugin/hoster/SmoozedCom.py
new file mode 100644
index 000000000..715d99b40
--- /dev/null
+++ b/pyload/plugin/hoster/SmoozedCom.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHoster import MultiHoster
+
+
+class SmoozedCom(MultiHoster):
+ __name__ = "SmoozedCom"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'^unmatchable$' #: Since we want to allow the user to specify the list of hoster to use we let MultiHoster.activate
+
+ __description__ = """Smoozed.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("", "")]
+
+
+ def handlePremium(self, pyfile):
+ # In some cases hostsers do not supply us with a filename at download, so we
+ # are going to set a fall back filename (e.g. for freakshare or xfileshare)
+ pyfile.name = pyfile.name.split('/').pop() # Remove everthing before last slash
+
+ # Correction for automatic assigned filename: Removing html at end if needed
+ suffix_to_remove = ["html", "htm", "php", "php3", "asp", "shtm", "shtml", "cfml", "cfm"]
+ temp = pyfile.name.split('.')
+
+ if temp.pop() in suffix_to_remove:
+ pyfile.name = ".".join(temp)
+
+ # Check the link
+ get_data = {'session_key': self.account.getAccountInfo(self.user)['session'],
+ 'url' : pyfile.url}
+
+ data = json_loads(self.load("http://www2.smoozed.com/api/check", get=get_data))
+
+ if data["state"] != "ok":
+ self.fail(data["message"])
+
+ if data["data"].get("state", "ok") != "ok":
+ if data["data"] == "Offline":
+ self.offline()
+ else:
+ self.fail(data["data"]["message"])
+
+ pyfile.name = data["data"]["name"]
+ pyfile.size = int(data["data"]["size"])
+
+ # Start the download
+ header = self.load("http://www2.smoozed.com/api/download", get=get_data, just_header=True)
+
+ if not "location" in header:
+ self.fail(_("Unable to initialize download"))
+ else:
+ self.link = header["location"][-1] if isinstance(header["location"], list) else header["location"]
+
+
+ def checkFile(self):
+ if self.checkDownload({'error': '{"state":"error"}',
+ 'retry': '{"state":"retry"}'}):
+ self.fail(_("Error response received"))
+
+ return super(SmoozedCom, self).checkFile()
diff --git a/pyload/plugin/hoster/SockshareCom.py b/pyload/plugin/hoster/SockshareCom.py
new file mode 100644
index 000000000..e903e3daf
--- /dev/null
+++ b/pyload/plugin/hoster/SockshareCom.py
@@ -0,0 +1,17 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class SockshareCom(DeadHoster):
+ __name__ = "SockshareCom"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'http://(?:www\.)?sockshare\.com/(mobile/)?(file|embed)/(?P<ID>\w+)'
+
+ __description__ = """Sockshare.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("jeix", "jeix@hasnomail.de"),
+ ("stickell", "l.stickell@yahoo.it"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
diff --git a/module/plugins/hoster/SoundcloudCom.py b/pyload/plugin/hoster/SoundcloudCom.py
index fd5d1ea6c..fd5d1ea6c 100644
--- a/module/plugins/hoster/SoundcloudCom.py
+++ b/pyload/plugin/hoster/SoundcloudCom.py
diff --git a/pyload/plugin/hoster/SpeedLoadOrg.py b/pyload/plugin/hoster/SpeedLoadOrg.py
new file mode 100644
index 000000000..a20f87902
--- /dev/null
+++ b/pyload/plugin/hoster/SpeedLoadOrg.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class SpeedLoadOrg(DeadHoster):
+ __name__ = "SpeedLoadOrg"
+ __type__ = "hoster"
+ __version__ = "1.02"
+
+ __pattern__ = r'http://(?:www\.)?speedload\.org/(?P<ID>\w+)'
+
+ __description__ = """Speedload.org hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
diff --git a/pyload/plugin/hoster/SpeedfileCz.py b/pyload/plugin/hoster/SpeedfileCz.py
new file mode 100644
index 000000000..981ba861d
--- /dev/null
+++ b/pyload/plugin/hoster/SpeedfileCz.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class SpeedfileCz(DeadHoster):
+ __name__ = "SpeedFileCz"
+ __type__ = "hoster"
+ __version__ = "0.32"
+
+ __pattern__ = r'http://(?:www\.)?speedfile\.cz/.+'
+
+ __description__ = """Speedfile.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/SpeedyshareCom.py b/pyload/plugin/hoster/SpeedyshareCom.py
new file mode 100644
index 000000000..c92522d70
--- /dev/null
+++ b/pyload/plugin/hoster/SpeedyshareCom.py
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# http://speedy.sh/ep2qY/Zapp-Brannigan.jpg
+
+import re
+
+from urlparse import urljoin
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class SpeedyshareCom(SimpleHoster):
+ __name__ = "SpeedyshareCom"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'https?://(?:www\.)?(speedyshare\.com|speedy\.sh)/\w+'
+
+ __description__ = """Speedyshare.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
+
+
+ NAME_PATTERN = r'class=downloadfilename>(?P<N>.*)</span></td>'
+ SIZE_PATTERN = r'class=sizetagtext>(?P<S>.*) (?P<U>[kKmM]?[iI]?[bB]?)</div>'
+
+ OFFLINE_PATTERN = r'class=downloadfilenamenotfound>.*</span>'
+
+ LINK_FREE_PATTERN = r'<a href=\'(.*)\'><img src=/gf/slowdownload\.png alt=\'Slow Download\' border=0'
+
+
+ def setup(self):
+ self.multiDL = False
+ self.chunkLimit = 1
+
+
+ def handleFree(self, pyfile):
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.link = m.group(1)
diff --git a/pyload/plugin/hoster/StorageTo.py b/pyload/plugin/hoster/StorageTo.py
new file mode 100644
index 000000000..78b9a60bb
--- /dev/null
+++ b/pyload/plugin/hoster/StorageTo.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class StorageTo(DeadHoster):
+ __name__ = "StorageTo"
+ __type__ = "hoster"
+ __version__ = "0.01"
+
+ __pattern__ = r'http://(?:www\.)?storage\.to/get/.+'
+
+ __description__ = """Storage.to hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("mkaay", "mkaay@mkaay.de")]
diff --git a/module/plugins/hoster/StreamCz.py b/pyload/plugin/hoster/StreamCz.py
index 95e69abf4..95e69abf4 100644
--- a/module/plugins/hoster/StreamCz.py
+++ b/pyload/plugin/hoster/StreamCz.py
diff --git a/pyload/plugin/hoster/StreamcloudEu.py b/pyload/plugin/hoster/StreamcloudEu.py
new file mode 100644
index 000000000..01e334491
--- /dev/null
+++ b/pyload/plugin/hoster/StreamcloudEu.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class StreamcloudEu(XFSHoster):
+ __name__ = "StreamcloudEu"
+ __type__ = "hoster"
+ __version__ = "0.10"
+
+ __pattern__ = r'http://(?:www\.)?streamcloud\.eu/\w{12}'
+
+ __description__ = """Streamcloud.eu hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("seoester", "seoester@googlemail.com")]
+
+
+ WAIT_PATTERN = r'var count = (\d+)'
+
+ LINK_PATTERN = r'file: "(http://(stor|cdn)\d+\.streamcloud\.eu:?\d*/.*/video\.(mp4|flv))",'
+
+
+ def setup(self):
+ self.multiDL = True
+ self.chunkLimit = 1
+ self.resumeDownload = self.premium
diff --git a/pyload/plugin/hoster/TurbobitNet.py b/pyload/plugin/hoster/TurbobitNet.py
new file mode 100644
index 000000000..c69158c39
--- /dev/null
+++ b/pyload/plugin/hoster/TurbobitNet.py
@@ -0,0 +1,164 @@
+# -*- coding: utf-8 -*-
+
+import random
+import re
+import time
+
+from Crypto.Cipher import ARC4
+from binascii import hexlify, unhexlify
+from pycurl import HTTPHEADER
+from urllib import quote
+
+from pyload.network.RequestFactory import getURL
+from pyload.plugin.internal.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster, timestamp
+
+
+class TurbobitNet(SimpleHoster):
+ __name__ = "TurbobitNet"
+ __type__ = "hoster"
+ __version__ = "0.19"
+
+ __pattern__ = r'http://(?:www\.)?turbobit\.net/(?:download/free/)?(?P<ID>\w+)'
+
+ __description__ = """Turbobit.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
+ ("prOq", "")]
+
+
+ URL_REPLACEMENTS = [(__pattern__ + ".*", "http://turbobit.net/\g<ID>.html")]
+
+ COOKIES = [("turbobit.net", "user_lang", "en")]
+
+ NAME_PATTERN = r'id="file-title">(?P<N>.+?)<'
+ SIZE_PATTERN = r'class="file-size">(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+ OFFLINE_PATTERN = r'<h2>File Not Found</h2>|html\(\'File (?:was )?not found'
+
+ LINK_FREE_PATTERN = LINK_PREMIUM_PATTERN = r'(/download/redirect/[^"\']+)'
+
+ LIMIT_WAIT_PATTERN = r'<div id=\'timeout\'>(\d+)<'
+ CAPTCHA_PATTERN = r'<img alt="Captcha" src="(.+?)"'
+
+
+ def handleFree(self, pyfile):
+ self.html = self.load("http://turbobit.net/download/free/%s" % self.info['pattern']['ID'],
+ decode=True)
+
+ rtUpdate = self.getRtUpdate()
+
+ self.solveCaptcha()
+
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
+
+ self.html = self.load(self.getDownloadUrl(rtUpdate))
+
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With:"])
+
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m:
+ self.link = m.group(1)
+
+
+ def solveCaptcha(self):
+ for _i in xrange(5):
+ m = re.search(self.LIMIT_WAIT_PATTERN, self.html)
+ if m:
+ wait_time = int(m.group(1))
+ self.wait(wait_time, wait_time > 60)
+ self.retry()
+
+ action, inputs = self.parseHtmlForm("action='#'")
+ if not inputs:
+ self.error(_("Captcha form not found"))
+ self.logDebug(inputs)
+
+ if inputs['captcha_type'] == 'recaptcha':
+ recaptcha = ReCaptcha(self)
+ inputs['recaptcha_response_field'], inputs['recaptcha_challenge_field'] = recaptcha.challenge()
+ else:
+ m = re.search(self.CAPTCHA_PATTERN, self.html)
+ if m is None:
+ self.error(_("captcha"))
+ captcha_url = m.group(1)
+ inputs['captcha_response'] = self.decryptCaptcha(captcha_url)
+
+ self.logDebug(inputs)
+ self.html = self.load(self.url, post=inputs)
+
+ if '<div class="captcha-error">Incorrect, try again!<' in self.html:
+ self.invalidCaptcha()
+ else:
+ self.correctCaptcha()
+ break
+ else:
+ self.fail(_("Invalid captcha"))
+
+
+ def getRtUpdate(self):
+ rtUpdate = self.getStorage("rtUpdate")
+ if not rtUpdate:
+ if self.getStorage("version") != self.__version__ \
+ or int(self.getStorage("timestamp", 0)) + 86400000 < timestamp():
+ # that's right, we are even using jdownloader updates
+ rtUpdate = getURL("http://update0.jdownloader.org/pluginstuff/tbupdate.js")
+ rtUpdate = self.decrypt(rtUpdate.splitlines()[1])
+ # but we still need to fix the syntax to work with other engines than rhino
+ rtUpdate = re.sub(r'for each\(var (\w+) in(\[[^\]]+\])\)\{',
+ r'zza=\2;for(var zzi=0;zzi<zza.length;zzi++){\1=zza[zzi];', rtUpdate)
+ rtUpdate = re.sub(r"for\((\w+)=", r"for(var \1=", rtUpdate)
+
+ self.setStorage("rtUpdate", rtUpdate)
+ self.setStorage("timestamp", timestamp())
+ self.setStorage("version", self.__version__)
+ else:
+ self.logError(_("Unable to download, wait for update..."))
+ self.tempOffline()
+
+ return rtUpdate
+
+
+ def getDownloadUrl(self, rtUpdate):
+ self.req.http.lastURL = self.url
+
+ m = re.search("(/\w+/timeout\.js\?\w+=)([^\"\'<>]+)", self.html)
+ if m:
+ url = "http://turbobit.net%s%s" % m.groups()
+ else:
+ url = "http://turbobit.net/files/timeout.js?ver=%s" % "".join(random.choice('0123456789ABCDEF') for _i in xrange(32))
+
+ fun = self.load(url)
+
+ self.setWait(65, False)
+
+ for b in [1, 3]:
+ self.jscode = "var id = \'%s\';var b = %d;var inn = \'%s\';%sout" % (
+ self.info['pattern']['ID'], b, quote(fun), rtUpdate)
+
+ try:
+ out = self.js.eval(self.jscode)
+ self.logDebug("URL", self.js.engine, out)
+ if out.startswith('/download/'):
+ return "http://turbobit.net%s" % out.strip()
+
+ except Exception, e:
+ self.logError(e)
+ else:
+ if self.retries >= 2:
+ # retry with updated js
+ self.delStorage("rtUpdate")
+ else:
+ self.retry()
+
+ self.wait()
+
+
+ def decrypt(self, data):
+ cipher = ARC4.new(hexlify('E\x15\xa1\x9e\xa3M\xa0\xc6\xa0\x84\xb6H\x83\xa8o\xa0'))
+ return unhexlify(cipher.encrypt(unhexlify(data)))
+
+
+ def getLocalTimeString(self):
+ lt = time.localtime()
+ tz = time.altzone if lt.tm_isdst else time.timezone
+ return "%s GMT%+03d%02d" % (time.strftime("%a %b %d %Y %H:%M:%S", lt), -tz // 3600, tz % 3600)
diff --git a/pyload/plugin/hoster/TurbouploadCom.py b/pyload/plugin/hoster/TurbouploadCom.py
new file mode 100644
index 000000000..e964d1365
--- /dev/null
+++ b/pyload/plugin/hoster/TurbouploadCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class TurbouploadCom(DeadHoster):
+ __name__ = "TurbouploadCom"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?turboupload\.com/(\w+)'
+
+ __description__ = """Turboupload.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/TusfilesNet.py b/pyload/plugin/hoster/TusfilesNet.py
new file mode 100644
index 000000000..20a948925
--- /dev/null
+++ b/pyload/plugin/hoster/TusfilesNet.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+
+from pyload.network.HTTPRequest import BadHeader
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class TusfilesNet(XFSHoster):
+ __name__ = "TusfilesNet"
+ __type__ = "hoster"
+ __version__ = "0.09"
+
+ __pattern__ = r'https?://(?:www\.)?tusfiles\.net/\w{12}'
+
+ __description__ = """Tusfiles.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com"),
+ ("guidobelix", "guidobelix@hotmail.it")]
+
+
+ INFO_PATTERN = r'\](?P<N>.+) - (?P<S>[\d.,]+) (?P<U>[\w^_]+)\['
+ OFFLINE_PATTERN = r'>File Not Found|<Title>TusFiles - Fast Sharing Files!|The file you are trying to download is no longer available'
+
+
+ def setup(self):
+ self.chunkLimit = -1
+ self.multiDL = True
+ self.resumeDownload = True
+
+
+ def downloadLink(self, link):
+ try:
+ return super(TusfilesNet, self).downloadLink(link)
+
+ except BadHeader, e:
+ if e.code is 503:
+ self.multiDL = False
+ raise Retry("503")
diff --git a/pyload/plugin/hoster/TwoSharedCom.py b/pyload/plugin/hoster/TwoSharedCom.py
new file mode 100644
index 000000000..8c6864414
--- /dev/null
+++ b/pyload/plugin/hoster/TwoSharedCom.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class TwoSharedCom(SimpleHoster):
+ __name__ = "TwoSharedCom"
+ __type__ = "hoster"
+ __version__ = "0.13"
+
+ __pattern__ = r'http://(?:www\.)?2shared\.com/(account/)?(download|get|file|document|photo|video|audio)/.+'
+
+ __description__ = """2Shared.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<h1>(?P<N>.*)</h1>'
+ SIZE_PATTERN = r'<span class="dtitle">File size:</span>\s*(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+ OFFLINE_PATTERN = r'The file link that you requested is not valid\.|This file was deleted\.'
+
+ LINK_FREE_PATTERN = r'window.location =\'(.+?)\';'
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = True
diff --git a/pyload/plugin/hoster/UlozTo.py b/pyload/plugin/hoster/UlozTo.py
new file mode 100644
index 000000000..0e4156ad0
--- /dev/null
+++ b/pyload/plugin/hoster/UlozTo.py
@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*-
+
+import re
+import time
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+def convertDecimalPrefix(m):
+ # decimal prefixes used in filesize and traffic
+ return ("%%.%df" % {'k': 3, 'M': 6, 'G': 9}[m.group(2)] % float(m.group(1))).replace('.', '')
+
+
+class UlozTo(SimpleHoster):
+ __name__ = "UlozTo"
+ __type__ = "hoster"
+ __version__ = "1.04"
+
+ __pattern__ = r'http://(?:www\.)?(uloz\.to|ulozto\.(cz|sk|net)|bagruj\.cz|zachowajto\.pl)/(?:live/)?(?P<ID>\w+/[^/?]*)'
+
+ __description__ = """Uloz.to hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ INFO_PATTERN = r'<p>File <strong>(?P<N>[^<]+)</strong> is password protected</p>'
+ NAME_PATTERN = r'<title>(?P<N>[^<]+) \| Uloz\.to</title>'
+ SIZE_PATTERN = r'<span id="fileSize">.*?(?P<S>[\d.,]+\s[kMG]?B)</span>'
+ OFFLINE_PATTERN = r'<title>404 - Page not found</title>|<h1 class="h1">File (has been deleted|was banned)</h1>'
+
+ URL_REPLACEMENTS = [(r"(?<=http://)([^/]+)", "www.ulozto.net")]
+ SIZE_REPLACEMENTS = [('([\d.]+)\s([kMG])B', convertDecimalPrefix)]
+
+ ADULT_PATTERN = r'<form action="([^\"]*)" method="post" id="frm-askAgeForm">'
+ PASSWD_PATTERN = r'<div class="passwordProtectedFile">'
+ VIPLINK_PATTERN = r'<a href="[^"]*\?disclaimer=1" class="linkVip">'
+ TOKEN_PATTERN = r'<input type="hidden" name="_token_" .*?value="(.+?)"'
+
+
+ def setup(self):
+ self.chunkLimit = 16 if self.premium else 1
+ self.multiDL = self.premium
+ self.resumeDownload = True
+
+
+ def process(self, pyfile):
+ pyfile.url = re.sub(r"(?<=http://)([^/]+)", "www.ulozto.net", pyfile.url)
+ self.html = self.load(pyfile.url, decode=True, cookies=True)
+
+ if re.search(self.ADULT_PATTERN, self.html):
+ self.logInfo(_("Adult content confirmation needed"))
+
+ m = re.search(self.TOKEN_PATTERN, self.html)
+ if m is None:
+ self.error(_("TOKEN_PATTERN not found"))
+ token = m.group(1)
+
+ self.html = self.load(pyfile.url, get={'do': "askAgeForm-submit"},
+ post={"agree": "Confirm", "_token_": token}, cookies=True)
+
+ if self.PASSWD_PATTERN in self.html:
+ password = self.getPassword()
+
+ if password:
+ self.logInfo(_("Password protected link, trying ") + password)
+ self.html = self.load(pyfile.url, get={'do': "passwordProtectedForm-submit"},
+ post={"password": password, "password_send": 'Send'}, cookies=True)
+
+ if self.PASSWD_PATTERN in self.html:
+ self.fail(_("Incorrect password"))
+ else:
+ self.fail(_("No password found"))
+
+ if re.search(self.VIPLINK_PATTERN, self.html):
+ self.html = self.load(pyfile.url, get={'disclaimer': "1"})
+
+ self.getFileInfo()
+
+ if self.premium and self.checkTrafficLeft():
+ self.handlePremium(pyfile)
+ else:
+ self.handleFree(pyfile)
+
+ self.doCheckDownload()
+
+
+ def handleFree(self, pyfile):
+ action, inputs = self.parseHtmlForm('id="frm-downloadDialog-freeDownloadForm"')
+ if not action or not inputs:
+ self.error(_("Free download form not found"))
+
+ self.logDebug("inputs.keys = " + str(inputs.keys()))
+ # get and decrypt captcha
+ if all(key in inputs for key in ("captcha_value", "captcha_id", "captcha_key")):
+ # Old version - last seen 9.12.2013
+ self.logDebug('Using "old" version')
+
+ captcha_value = self.decryptCaptcha("http://img.uloz.to/captcha/%s.png" % inputs['captcha_id'])
+ self.logDebug("CAPTCHA ID: " + inputs['captcha_id'] + ", CAPTCHA VALUE: " + captcha_value)
+
+ inputs.update({'captcha_id': inputs['captcha_id'], 'captcha_key': inputs['captcha_key'], 'captcha_value': captcha_value})
+
+ elif all(key in inputs for key in ("captcha_value", "timestamp", "salt", "hash")):
+ # New version - better to get new parameters (like captcha reload) because of image url - since 6.12.2013
+ self.logDebug('Using "new" version')
+
+ xapca = self.load("http://www.ulozto.net/reloadXapca.php", get={'rnd': str(int(time.time()))})
+ self.logDebug("xapca = " + str(xapca))
+
+ data = json_loads(xapca)
+ captcha_value = self.decryptCaptcha(str(data['image']))
+ self.logDebug("CAPTCHA HASH: " + data['hash'], "CAPTCHA SALT: " + str(data['salt']), "CAPTCHA VALUE: " + captcha_value)
+
+ inputs.update({'timestamp': data['timestamp'], 'salt': data['salt'], 'hash': data['hash'], 'captcha_value': captcha_value})
+ else:
+ self.error(_("CAPTCHA form changed"))
+
+ self.multiDL = True
+ self.download("http://www.ulozto.net" + action, post=inputs, cookies=True, disposition=True)
+
+
+ def handlePremium(self, pyfile):
+ self.download(pyfile.url, get={'do': "directDownload"}, disposition=True)
+
+
+ def doCheckDownload(self):
+ check = self.checkDownload({
+ "wrong_captcha": re.compile(r'<ul class="error">\s*<li>Error rewriting the text.</li>'),
+ "offline" : re.compile(self.OFFLINE_PATTERN),
+ "passwd" : self.PASSWD_PATTERN,
+ "server_error" : 'src="http://img.ulozto.cz/error403/vykricnik.jpg"', # paralell dl, server overload etc.
+ "not_found" : "<title>UloÅŸ.to</title>"
+ })
+
+ if check == "wrong_captcha":
+ #self.delStorage("captcha_id")
+ #self.delStorage("captcha_text")
+ self.invalidCaptcha()
+ self.retry(reason=_("Wrong captcha code"))
+
+ elif check == "offline":
+ self.offline()
+
+ elif check == "passwd":
+ self.fail(_("Wrong password"))
+
+ elif check == "server_error":
+ self.logError(_("Server error, try downloading later"))
+ self.multiDL = False
+ self.wait(1 * 60 * 60, True)
+ self.retry()
+
+ elif check == "not_found":
+ self.fail(_("Server error - file not downloadable"))
diff --git a/pyload/plugin/hoster/UloziskoSk.py b/pyload/plugin/hoster/UloziskoSk.py
new file mode 100644
index 000000000..ce40c9f7a
--- /dev/null
+++ b/pyload/plugin/hoster/UloziskoSk.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class UloziskoSk(SimpleHoster):
+ __name__ = "UloziskoSk"
+ __type__ = "hoster"
+ __version__ = "0.25"
+
+ __pattern__ = r'http://(?:www\.)?ulozisko\.sk/.+'
+
+ __description__ = """Ulozisko.sk hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<div class="down1">(?P<N>[^<]+)</div>'
+ SIZE_PATTERN = ur'Veğkosť súboru: <strong>(?P<S>[\d.,]+) (?P<U>[\w^_]+)</strong><br />'
+ OFFLINE_PATTERN = ur'<span class = "red">ZadanÜ súbor neexistuje z jedného z nasledujúcich dÎvodov:</span>'
+
+ LINK_FREE_PATTERN = r'<form name = "formular" action = "([^"]+)" method = "post">'
+ ID_PATTERN = r'<input type = "hidden" name = "id" value = "([^"]+)" />'
+ CAPTCHA_PATTERN = r'<img src="(/obrazky/obrazky\.php\?fid=[^"]+)" alt="" />'
+ IMG_PATTERN = ur'<strong>PRE ZVÄČŠENIE KLIKNITE NA OBRÁZOK</strong><br /><a href = "([^"]+)">'
+
+
+ def process(self, pyfile):
+ self.html = self.load(pyfile.url, decode=True)
+ self.getFileInfo()
+
+ m = re.search(self.IMG_PATTERN, self.html)
+ if m:
+ url = "http://ulozisko.sk" + m.group(1)
+ self.download(url)
+ else:
+ self.handleFree(pyfile)
+
+
+ def handleFree(self, pyfile):
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("LINK_FREE_PATTERN not found"))
+ parsed_url = 'http://www.ulozisko.sk' + m.group(1)
+
+ m = re.search(self.ID_PATTERN, self.html)
+ if m is None:
+ self.error(_("ID_PATTERN not found"))
+ id = m.group(1)
+
+ self.logDebug("URL:" + parsed_url + ' ID:' + id)
+
+ m = re.search(self.CAPTCHA_PATTERN, self.html)
+ if m is None:
+ self.error(_("CAPTCHA_PATTERN not found"))
+ captcha_url = 'http://www.ulozisko.sk' + m.group(1)
+
+ captcha = self.decryptCaptcha(captcha_url, cookies=True)
+
+ self.logDebug("CAPTCHA_URL:" + captcha_url + ' CAPTCHA:' + captcha)
+
+ self.download(parsed_url,
+ post={"antispam": captcha,
+ "id" : id,
+ "name" : pyfile.name,
+ "but" : "++++STIAHNI+S%DABOR++++"})
diff --git a/pyload/plugin/hoster/UnibytesCom.py b/pyload/plugin/hoster/UnibytesCom.py
new file mode 100644
index 000000000..2c9b9ca5f
--- /dev/null
+++ b/pyload/plugin/hoster/UnibytesCom.py
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urlparse import urljoin
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class UnibytesCom(SimpleHoster):
+ __name__ = "UnibytesCom"
+ __type__ = "hoster"
+ __version__ = "0.12"
+
+ __pattern__ = r'https?://(?:www\.)?unibytes\.com/[\w .-]{11}B'
+
+ __description__ = """UniBytes.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ HOSTER_DOMAIN = "unibytes.com"
+
+ INFO_PATTERN = r'<span[^>]*?id="fileName"[^>]*>(?P<N>[^>]+)</span>\s*\((?P<S>\d.*?)\)'
+
+ WAIT_PATTERN = r'Wait for <span id="slowRest">(\d+)</span> sec'
+ LINK_FREE_PATTERN = r'<a href="([^"]+)">Download</a>'
+
+
+ def handleFree(self, pyfile):
+ domain = "http://www.%s/" % self.HOSTER_DOMAIN
+ action, post_data = self.parseHtmlForm('id="startForm"')
+
+
+ for _i in xrange(8):
+ self.logDebug(action, post_data)
+ self.html = self.load(urljoin(domain, action), post=post_data, follow_location=False)
+
+ m = re.search(r'location:\s*(\S+)', self.req.http.header, re.I)
+ if m:
+ url = m.group(1)
+ break
+
+ if '>Somebody else is already downloading using your IP-address<' in self.html:
+ self.wait(10 * 60, True)
+ self.retry()
+
+ if post_data['step'] == 'last':
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m:
+ url = m.group(1)
+ self.correctCaptcha()
+ break
+ else:
+ self.invalidCaptcha()
+
+ last_step = post_data['step']
+ action, post_data = self.parseHtmlForm('id="stepForm"')
+
+ if last_step == 'timer':
+ m = re.search(self.WAIT_PATTERN, self.html)
+ self.wait(m.group(1) if m else 60, False)
+
+ elif last_step in ("captcha", "last"):
+ post_data['captcha'] = self.decryptCaptcha(urljoin(domain, "/captcha.jpg"))
+
+ else:
+ self.fail(_("No valid captcha code entered"))
+
+ self.download(url)
diff --git a/pyload/plugin/hoster/UnrestrictLi.py b/pyload/plugin/hoster/UnrestrictLi.py
new file mode 100644
index 000000000..c81bb0554
--- /dev/null
+++ b/pyload/plugin/hoster/UnrestrictLi.py
@@ -0,0 +1,82 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.MultiHoster import MultiHoster
+from pyload.plugin.internal.SimpleHoster import secondsToMidnight
+
+
+class UnrestrictLi(MultiHoster):
+ __name__ = "UnrestrictLi"
+ __type__ = "hoster"
+ __version__ = "0.21"
+
+ __pattern__ = r'https?://(?:www\.)?(unrestrict|unr)\.li/dl/[\w^_]+'
+
+ __description__ = """Unrestrict.li multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ LOGIN_ACCOUNT = False
+
+
+ def setup(self):
+ self.chunkLimit = 16
+ self.resumeDownload = True
+
+
+ def handleFree(self, pyfile):
+ for _i in xrange(5):
+ self.html = self.load('https://unrestrict.li/unrestrict.php',
+ post={'link': pyfile.url, 'domain': 'long'})
+
+ self.logDebug("JSON data: " + self.html)
+
+ if self.html:
+ break
+ else:
+ self.logInfo(_("Unable to get API data, waiting 1 minute and retry"))
+ self.retry(5, 60, "Unable to get API data")
+
+ if 'Expired session' in self.html \
+ or ("You are not allowed to download from this host" in self.html and self.premium):
+ self.account.relogin(self.user)
+ self.retry()
+
+ elif "File offline" in self.html:
+ self.offline()
+
+ elif "You are not allowed to download from this host" in self.html:
+ self.fail(_("You are not allowed to download from this host"))
+
+ elif "You have reached your daily limit for this host" in self.html:
+ self.logWarning(_("Reached daily limit for this host"))
+ self.retry(5, secondsToMidnight(gmt=2), "Daily limit for this host reached")
+
+ elif "ERROR_HOSTER_TEMPORARILY_UNAVAILABLE" in self.html:
+ self.logInfo(_("Hoster temporarily unavailable, waiting 1 minute and retry"))
+ self.retry(5, 60, "Hoster is temporarily unavailable")
+
+ self.html = json_loads(self.html)
+ self.link = self.html.keys()[0]
+ self.api_data = self.html[self.link]
+
+ if hasattr(self, 'api_data'):
+ self.setNameSize()
+
+
+ def checkFile(self):
+ super(UnrestrictLi, self).checkFile()
+
+ if self.getConfig("history"):
+ self.load("https://unrestrict.li/history/", get={'delete': "all"})
+ self.logInfo(_("Download history deleted"))
+
+
+ def setNameSize(self):
+ if 'name' in self.api_data:
+ self.pyfile.name = self.api_data['name']
+ if 'size' in self.api_data:
+ self.pyfile.size = self.api_data['size']
diff --git a/pyload/plugin/hoster/UpleaCom.py b/pyload/plugin/hoster/UpleaCom.py
new file mode 100644
index 000000000..855d9ed65
--- /dev/null
+++ b/pyload/plugin/hoster/UpleaCom.py
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urlparse import urljoin
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class UpleaCom(XFSHoster):
+ __name__ = "UpleaCom"
+ __type__ = "hoster"
+ __version__ = "0.06"
+
+ __pattern__ = r'https?://(?:www\.)?uplea\.com/dl/\w{15}'
+
+ __description__ = """Uplea.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Redleon", "")]
+
+
+ NAME_PATTERN = r'class="agmd size18">(?P<N>.+?)<'
+ SIZE_PATTERN = r'size14">(?P<S>[\d.,]+) (?P<U>[\w^_])</span>'
+
+ OFFLINE_PATTERN = r'>You followed an invalid or expired link'
+
+ LINK_PATTERN = r'"(http?://\w+\.uplea\.com/anonym/.*?)"'
+
+ WAIT_PATTERN = r'timeText:([\d.]+),'
+ STEP_PATTERN = r'<a href="(/step/.+)">'
+
+
+ def setup(self):
+ self.multiDL = False
+ self.chunkLimit = 1
+ self.resumeDownload = True
+
+
+ def handleFree(self, pyfile):
+ m = re.search(self.STEP_PATTERN, self.html)
+ if m is None:
+ self.error(_("STEP_PATTERN not found"))
+
+ self.html = self.load(urljoin("http://uplea.com/", m.group(1)))
+
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m:
+ self.wait(m.group(1), True)
+ self.retry()
+
+ m = re.search(self.LINK_PATTERN, self.html)
+ if m is None:
+ self.error(_("LINK_PATTERN not found"))
+
+ self.link = m.group(1)
+ self.wait(15)
diff --git a/pyload/plugin/hoster/UploadStationCom.py b/pyload/plugin/hoster/UploadStationCom.py
new file mode 100644
index 000000000..d77bdb760
--- /dev/null
+++ b/pyload/plugin/hoster/UploadStationCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class UploadStationCom(DeadHoster):
+ __name__ = "UploadStationCom"
+ __type__ = "hoster"
+ __version__ = "0.52"
+
+ __pattern__ = r'http://(?:www\.)?uploadstation\.com/file/(?P<ID>\w+)'
+
+ __description__ = """UploadStation.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("fragonib", "fragonib[AT]yahoo[DOT]es"),
+ ("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/UploadableCh.py b/pyload/plugin/hoster/UploadableCh.py
new file mode 100644
index 000000000..c54ecb495
--- /dev/null
+++ b/pyload/plugin/hoster/UploadableCh.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from time import sleep
+
+from pyload.plugin.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class UploadableCh(SimpleHoster):
+ __name__ = "UploadableCh"
+ __type__ = "hoster"
+ __version__ = "0.08"
+
+ __pattern__ = r'http://(?:www\.)?uploadable\.ch/file/(?P<ID>\w+)'
+
+ __description__ = """Uploadable.ch hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ URL_REPLACEMENTS = [(__pattern__ + ".*", r'http://www.uploadable.ch/file/\g<ID>')]
+
+ INFO_PATTERN = r'div id=\"file_name\" title=.*>(?P<N>.+)<span class=\"filename_normal\">\((?P<S>[\d.]+) (?P<U>\w+)\)</span><'
+
+ OFFLINE_PATTERN = r'>(File not available|This file is no longer available)'
+ TEMP_OFFLINE_PATTERN = r'<div class="icon_err">'
+
+ WAIT_PATTERN = r'>Please wait.+?<'
+
+ RECAPTCHA_KEY = "6LdlJuwSAAAAAPJbPIoUhyqOJd7-yrah5Nhim5S3"
+
+
+ def handleFree(self, pyfile):
+ # Click the "free user" button and wait
+ a = self.load(pyfile.url, cookies=True, post={'downloadLink': "wait"}, decode=True)
+ self.logDebug(a)
+
+ self.wait(30)
+
+ # Make the recaptcha appear and show it the pyload interface
+ b = self.load(pyfile.url, cookies=True, post={'checkDownload': "check"}, decode=True)
+ self.logDebug(b) #: Expected output: {"success":"showCaptcha"}
+
+ recaptcha = ReCaptcha(self)
+
+ response, challenge = recaptcha.challenge(self.RECAPTCHA_KEY)
+
+ # Submit the captcha solution
+ self.load("http://www.uploadable.ch/checkReCaptcha.php",
+ cookies=True,
+ post={'recaptcha_challenge_field' : challenge,
+ 'recaptcha_response_field' : response,
+ 'recaptcha_shortencode_field': self.info['pattern']['ID']},
+ decode=True)
+
+ self.wait(3)
+
+ # Get ready for downloading
+ self.load(pyfile.url, cookies=True, post={'downloadLink': "show"}, decode=True)
+
+ self.wait(3)
+
+ # Download the file
+ self.download(pyfile.url, cookies=True, post={'download': "normal"}, disposition=True)
+
+
+ def checkFile(self):
+ if self.checkDownload({'wait': re.compile("Please wait for")}):
+ self.logInfo("Downloadlimit reached, please wait or reconnect")
+ self.wait(60 * 60, True)
+ self.retry()
+
+ return super(UploadableCh, self).checkFile()
diff --git a/pyload/plugin/hoster/UploadboxCom.py b/pyload/plugin/hoster/UploadboxCom.py
new file mode 100644
index 000000000..01e4c6854
--- /dev/null
+++ b/pyload/plugin/hoster/UploadboxCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class UploadboxCom(DeadHoster):
+ __name__ = "Uploadbox"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'http://(?:www\.)?uploadbox\.com/files/.+'
+
+ __description__ = """UploadBox.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/UploadedTo.py b/pyload/plugin/hoster/UploadedTo.py
new file mode 100644
index 000000000..f9b121bfe
--- /dev/null
+++ b/pyload/plugin/hoster/UploadedTo.py
@@ -0,0 +1,117 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from time import sleep
+
+from pyload.network.RequestFactory import getURL
+from pyload.plugin.internal.CaptchaService import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class UploadedTo(SimpleHoster):
+ __name__ = "UploadedTo"
+ __type__ = "hoster"
+ __version__ = "0.84"
+
+ __pattern__ = r'https?://(?:www\.)?(uploaded\.(to|net)|ul\.to)(/file/|/?\?id=|.*?&id=|/)(?P<ID>\w+)'
+
+ __description__ = """Uploaded.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ API_KEY = "lhF2IeeprweDfu9ccWlxXVVypA5nA3EL"
+
+ URL_REPLACEMENTS = [(__pattern__ + ".*", r'http://uploaded.net/file/\g<ID>')]
+
+ LINK_PREMIUM_PATTERN = r'<div class="tfree".*\s*<form method="post" action="(.+?)"'
+
+ WAIT_PATTERN = r'Current waiting period: <span>(\d+)'
+ DL_LIMIT_ERROR = r'You have reached the max. number of possible free downloads for this hour'
+
+
+ @classmethod
+ def apiInfo(cls, url="", get={}, post={}):
+ info = super(UploadedTo, cls).apiInfo(url)
+
+ for _i in xrange(5):
+ html = getURL("http://uploaded.net/api/filemultiple",
+ get={"apikey": cls.API_KEY, 'id_0': re.match(cls.__pattern__, url).group('ID')},
+ decode=True)
+
+ if html != "can't find request":
+ api = html.split(",", 4)
+ if api[0] == "online":
+ info.update({'name': api[4].strip(), 'size': api[2], 'status': 2})
+ else:
+ info['status'] = 1
+ break
+ else:
+ sleep(3)
+
+ return info
+
+
+ def setup(self):
+ self.multiDL = self.resumeDownload = self.premium
+ self.chunkLimit = 1 # critical problems with more chunks
+
+
+ def checkErrors(self):
+ if 'var free_enabled = false;' in self.html:
+ self.logError(_("Free-download capacities exhausted"))
+ self.retry(24, 5 * 60)
+
+ elif "limit-size" in self.html:
+ self.fail(_("File too big for free download"))
+
+ elif "limit-slot" in self.html: # Temporary restriction so just wait a bit
+ self.wait(30 * 60, True)
+ self.retry()
+
+ elif "limit-parallel" in self.html:
+ self.fail(_("Cannot download in parallel"))
+
+ elif "limit-dl" in self.html or self.DL_LIMIT_ERROR in self.html: # limit-dl
+ self.wait(3 * 60 * 60, True)
+ self.retry()
+
+ elif '"err":"captcha"' in self.html:
+ self.invalidCaptcha()
+
+ else:
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m:
+ self.wait(m.group(1))
+
+
+ def handleFree(self, pyfile):
+ self.load("http://uploaded.net/language/en", just_header=True)
+
+ self.html = self.load("http://uploaded.net/js/download.js", decode=True)
+
+ recaptcha = ReCaptcha(self)
+ response, challenge = recaptcha.challenge()
+
+ self.html = self.load("http://uploaded.net/io/ticket/captcha/%s" % self.info['pattern']['ID'],
+ post={'recaptcha_challenge_field': challenge,
+ 'recaptcha_response_field' : response})
+
+ if "type:'download'" in self.html:
+ self.correctCaptcha()
+ try:
+ self.link = re.search("url:'([^']+)", self.html).group(1)
+
+ except Exception:
+ pass
+
+ self.checkErrors()
+
+
+ def checkFile(self):
+ if self.checkDownload({'limit-dl': self.DL_LIMIT_ERROR}):
+ self.wait(3 * 60 * 60, True)
+ self.retry()
+
+ return super(UploadedTo, self).checkFile()
diff --git a/pyload/plugin/hoster/UploadhereCom.py b/pyload/plugin/hoster/UploadhereCom.py
new file mode 100644
index 000000000..77970a97b
--- /dev/null
+++ b/pyload/plugin/hoster/UploadhereCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class UploadhereCom(DeadHoster):
+ __name__ = "UploadhereCom"
+ __type__ = "hoster"
+ __version__ = "0.12"
+
+ __pattern__ = r'http://(?:www\.)?uploadhere\.com/\w{10}'
+
+ __description__ = """Uploadhere.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/UploadheroCom.py b/pyload/plugin/hoster/UploadheroCom.py
new file mode 100644
index 000000000..917053f18
--- /dev/null
+++ b/pyload/plugin/hoster/UploadheroCom.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# http://uploadhero.co/dl/wQBRAVSM
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class UploadheroCom(SimpleHoster):
+ __name__ = "UploadheroCom"
+ __type__ = "hoster"
+ __version__ = "0.17"
+
+ __pattern__ = r'http://(?:www\.)?uploadhero\.com?/dl/\w+'
+
+ __description__ = """UploadHero.co plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("mcmyst", "mcmyst@hotmail.fr"),
+ ("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'<div class="nom_de_fichier">(?P<N>.*?)</div>'
+ SIZE_PATTERN = r'Taille du fichier : </span><strong>(?P<S>.*?)</strong>'
+ OFFLINE_PATTERN = r'<p class="titre_dl_2">|<div class="raison"><strong>Le lien du fichier ci-dessus n\'existe plus.'
+
+ COOKIES = [("uploadhero.co", "lang", "en")]
+
+ IP_BLOCKED_PATTERN = r'href="(/lightbox_block_download\.php\?min=.*?)"'
+ IP_WAIT_PATTERN = r'<span id="minutes">(\d+)</span>.*\s*<span id="seconds">(\d+)</span>'
+
+ CAPTCHA_PATTERN = r'"(/captchadl\.php\?\w+)"'
+
+ LINK_FREE_PATTERN = r'var magicomfg = \'<a href="(http://[^<>"]*?)"|"(http://storage\d+\.uploadhero\.co/\?d=\w+/[^<>"/]+)"'
+ LINK_PREMIUM_PATTERN = r'<a href="([^"]+)" id="downloadnow"'
+
+
+ def handleFree(self, pyfile):
+ self.checkErrors()
+
+ m = re.search(self.CAPTCHA_PATTERN, self.html)
+ if m is None:
+ self.error(_("CAPTCHA_PATTERN not found"))
+ captcha_url = "http://uploadhero.co" + m.group(1)
+
+ for _i in xrange(5):
+ captcha = self.decryptCaptcha(captcha_url)
+ self.html = self.load(pyfile.url, get={"code": captcha})
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m:
+ self.correctCaptcha()
+ download_url = m.group(1) or m.group(2)
+ break
+ else:
+ self.invalidCaptcha()
+ else:
+ self.fail(_("No valid captcha code entered"))
+
+ self.download(download_url)
+
+
+ def checkErrors(self):
+ m = re.search(self.IP_BLOCKED_PATTERN, self.html)
+ if m:
+ self.html = self.load("http://uploadhero.co%s" % m.group(1))
+
+ m = re.search(self.IP_WAIT_PATTERN, self.html)
+ wait_time = (int(m.group(1)) * 60 + int(m.group(2))) if m else 5 * 60
+ self.wait(wait_time, True)
+ self.retry()
+
+ self.info.pop('error', None)
diff --git a/pyload/plugin/hoster/UploadingCom.py b/pyload/plugin/hoster/UploadingCom.py
new file mode 100644
index 000000000..461b0113a
--- /dev/null
+++ b/pyload/plugin/hoster/UploadingCom.py
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pycurl import HTTPHEADER
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.SimpleHoster import SimpleHoster, timestamp
+
+
+class UploadingCom(SimpleHoster):
+ __name__ = "UploadingCom"
+ __type__ = "hoster"
+ __version__ = "0.40"
+
+ __pattern__ = r'http://(?:www\.)?uploading\.com/files/(?:get/)?(?P<ID>\w+)'
+
+ __description__ = """Uploading.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("jeix", "jeix@hasnomail.de"),
+ ("mkaay", "mkaay@mkaay.de"),
+ ("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'id="file_title">(?P<N>.+)</'
+ SIZE_PATTERN = r'size tip_container">(?P<S>[\d.,]+) (?P<U>[\w^_]+)<'
+ OFFLINE_PATTERN = r'(Page|file) not found'
+
+ COOKIES = [("uploading.com", "lang", "1"),
+ (".uploading.com", "language", "1"),
+ (".uploading.com", "setlang", "en"),
+ (".uploading.com", "_lang", "en")]
+
+
+ def process(self, pyfile):
+ if not "/get/" in pyfile.url:
+ pyfile.url = pyfile.url.replace("/files", "/files/get")
+
+ self.html = self.load(pyfile.url, decode=True)
+ self.getFileInfo()
+
+ if self.premium:
+ self.handlePremium(pyfile)
+ else:
+ self.handleFree(pyfile)
+
+
+ def handlePremium(self, pyfile):
+ postData = {'action': 'get_link',
+ 'code' : self.info['pattern']['ID'],
+ 'pass' : 'undefined'}
+
+ self.html = self.load('http://uploading.com/files/get/?JsHttpRequest=%d-xml' % timestamp(), post=postData)
+ url = re.search(r'"link"\s*:\s*"(.*?)"', self.html)
+ if url:
+ url = url.group(1).replace("\\/", "/")
+ self.download(url)
+
+ raise Exception("Plugin defect")
+
+
+ def handleFree(self, pyfile):
+ m = re.search('<h2>((Daily )?Download Limit)</h2>', self.html)
+ if m:
+ pyfile.error = m.group(1)
+ self.logWarning(pyfile.error)
+ self.retry(6, (6 * 60 if m.group(2) else 15) * 60, pyfile.error)
+
+ ajax_url = "http://uploading.com/files/get/?ajax"
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
+ self.req.http.lastURL = pyfile.url
+
+ res = json_loads(self.load(ajax_url, post={'action': 'second_page', 'code': self.info['pattern']['ID']}))
+
+ if 'answer' in res and 'wait_time' in res['answer']:
+ wait_time = int(res['answer']['wait_time'])
+ self.logInfo(_("Waiting %d seconds") % wait_time)
+ self.wait(wait_time)
+ else:
+ self.error(_("No AJAX/WAIT"))
+
+ res = json_loads(self.load(ajax_url, post={'action': 'get_link', 'code': self.info['pattern']['ID'], 'pass': 'false'}))
+
+ if 'answer' in res and 'link' in res['answer']:
+ url = res['answer']['link']
+ else:
+ self.error(_("No AJAX/URL"))
+
+ self.html = self.load(url)
+ m = re.search(r'<form id="file_form" action="(.*?)"', self.html)
+ if m:
+ url = m.group(1)
+ else:
+ self.error(_("No URL"))
+
+ self.download(url)
diff --git a/pyload/plugin/hoster/UploadkingCom.py b/pyload/plugin/hoster/UploadkingCom.py
new file mode 100644
index 000000000..6f4374096
--- /dev/null
+++ b/pyload/plugin/hoster/UploadkingCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class UploadkingCom(DeadHoster):
+ __name__ = "UploadkingCom"
+ __type__ = "hoster"
+ __version__ = "0.14"
+
+ __pattern__ = r'http://(?:www\.)?uploadking\.com/\w{10}'
+
+ __description__ = """UploadKing.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
diff --git a/pyload/plugin/hoster/UpstoreNet.py b/pyload/plugin/hoster/UpstoreNet.py
new file mode 100644
index 000000000..98e5c0d64
--- /dev/null
+++ b/pyload/plugin/hoster/UpstoreNet.py
@@ -0,0 +1,69 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.captcha import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class UpstoreNet(SimpleHoster):
+ __name__ = "UpstoreNet"
+ __type__ = "hoster"
+ __version__ = "0.05"
+
+ __pattern__ = r'https?://(?:www\.)?upstore\.net/'
+
+ __description__ = """Upstore.Net File Download Hoster"""
+ __license__ = "GPLv3"
+ __authors__ = [("igel", "igelkun@myopera.com")]
+
+
+ INFO_PATTERN = r'<div class="comment">.*?</div>\s*\n<h2 style="margin:0">(?P<N>.*?)</h2>\s*\n<div class="comment">\s*\n\s*(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+ OFFLINE_PATTERN = r'<span class="error">File not found</span>'
+
+ WAIT_PATTERN = r'var sec = (\d+)'
+ CHASH_PATTERN = r'<input type="hidden" name="hash" value="([^"]*)">'
+ LINK_FREE_PATTERN = r'<a href="(https?://.*?)" target="_blank"><b>'
+
+
+ def handleFree(self, pyfile):
+ # STAGE 1: get link to continue
+ m = re.search(self.CHASH_PATTERN, self.html)
+ if m is None:
+ self.error(_("CHASH_PATTERN not found"))
+ chash = m.group(1)
+ self.logDebug("Read hash " + chash)
+ # continue to stage2
+ post_data = {'hash': chash, 'free': 'Slow download'}
+ self.html = self.load(pyfile.url, post=post_data, decode=True)
+
+ # STAGE 2: solv captcha and wait
+ # first get the infos we need: recaptcha key and wait time
+ recaptcha = ReCaptcha(self)
+
+ # try the captcha 5 times
+ for i in xrange(5):
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m is None:
+ self.error(_("Wait pattern not found"))
+ wait_time = int(m.group(1))
+
+ # then, do the waiting
+ self.wait(wait_time)
+
+ # then, handle the captcha
+ response, challenge = recaptcha.challenge()
+ post_data.update({'recaptcha_challenge_field': challenge,
+ 'recaptcha_response_field' : response})
+
+ self.html = self.load(pyfile.url, post=post_data, decode=True)
+
+ # STAGE 3: get direct link
+ m = re.search(self.LINK_FREE_PATTERN, self.html, re.S)
+ if m:
+ break
+
+ if m is None:
+ self.error(_("Download link not found"))
+
+ self.link = m.group(1)
diff --git a/pyload/plugin/hoster/UptoboxCom.py b/pyload/plugin/hoster/UptoboxCom.py
new file mode 100644
index 000000000..da93b3c6b
--- /dev/null
+++ b/pyload/plugin/hoster/UptoboxCom.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class UptoboxCom(XFSHoster):
+ __name__ = "UptoboxCom"
+ __type__ = "hoster"
+ __version__ = "0.17"
+
+ __pattern__ = r'https?://(?:www\.)?(uptobox|uptostream)\.com/\w{12}'
+
+ __description__ = """Uptobox.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ INFO_PATTERN = r'"para_title">(?P<N>.+) \((?P<S>[\d.,]+) (?P<U>[\w^_]+)\)'
+ OFFLINE_PATTERN = r'>(File not found|Access Denied|404 Not Found)'
+
+ LINK_PATTERN = r'"(https?://\w+\.uptobox\.com/d/.*?)"'
+
+ ERROR_PATTERN = r'>(You have to wait.+till next download.)<' #@TODO: Check XFSHoster ERROR_PATTERN
+
+
+ def setup(self):
+ self.multiDL = True
+ self.chunkLimit = 1
+ self.resumeDownload = True
diff --git a/module/plugins/hoster/VeehdCom.py b/pyload/plugin/hoster/VeehdCom.py
index 91d7cc443..91d7cc443 100644
--- a/module/plugins/hoster/VeehdCom.py
+++ b/pyload/plugin/hoster/VeehdCom.py
diff --git a/pyload/plugin/hoster/VeohCom.py b/pyload/plugin/hoster/VeohCom.py
new file mode 100644
index 000000000..a4394736d
--- /dev/null
+++ b/pyload/plugin/hoster/VeohCom.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class VeohCom(SimpleHoster):
+ __name__ = "VeohCom"
+ __type__ = "hoster"
+ __version__ = "0.22"
+
+ __pattern__ = r'http://(?:www\.)?veoh\.com/(tv/)?(watch|videos)/(?P<ID>v\w+)'
+ __config__ = [("quality", "Low;High;Auto", "Quality", "Auto")]
+
+ __description__ = """Veoh.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ NAME_PATTERN = r'<meta name="title" content="(?P<N>.*?)"'
+ OFFLINE_PATTERN = r'>Sorry, we couldn\'t find the video you were looking for'
+
+ URL_REPLACEMENTS = [(__pattern__ + ".*", r'http://www.veoh.com/watch/\g<ID>')]
+
+ COOKIES = [("veoh.com", "lassieLocale", "en")]
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = True
+ self.chunkLimit = -1
+
+
+ def handleFree(self, pyfile):
+ quality = self.getConfig("quality")
+ if quality == "Auto":
+ quality = ("High", "Low")
+
+ for q in quality:
+ pattern = r'"fullPreviewHash%sPath":"(.+?)"' % q
+ m = re.search(pattern, self.html)
+ if m:
+ pyfile.name += ".mp4"
+ link = m.group(1).replace("\\", "")
+ self.download(link)
+ return
+ else:
+ self.logInfo(_("No %s quality video found") % q.upper())
+ else:
+ self.fail(_("No video found!"))
diff --git a/pyload/plugin/hoster/VidPlayNet.py b/pyload/plugin/hoster/VidPlayNet.py
new file mode 100644
index 000000000..094da09bd
--- /dev/null
+++ b/pyload/plugin/hoster/VidPlayNet.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+#
+# Test links:
+# BigBuckBunny_320x180.mp4 - 61.7 Mb - http://vidplay.net/38lkev0h3jv0
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class VidPlayNet(XFSHoster):
+ __name__ = "VidPlayNet"
+ __type__ = "hoster"
+ __version__ = "0.04"
+
+ __pattern__ = r'https?://(?:www\.)?vidplay\.net/\w{12}'
+
+ __description__ = """VidPlay.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("t4skforce", "t4skforce1337[AT]gmail[DOT]com")]
+
+
+ NAME_PATTERN = r'<b>Password:</b></div>\s*<h[1-6]>(?P<N>[^<]+)</h[1-6]>'
diff --git a/pyload/plugin/hoster/VimeoCom.py b/pyload/plugin/hoster/VimeoCom.py
new file mode 100644
index 000000000..c48ad3414
--- /dev/null
+++ b/pyload/plugin/hoster/VimeoCom.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class VimeoCom(SimpleHoster):
+ __name__ = "VimeoCom"
+ __type__ = "hoster"
+ __version__ = "0.04"
+
+ __pattern__ = r'https?://(?:www\.)?(player\.)?vimeo\.com/(video/)?(?P<ID>\d+)'
+ __config__ = [("quality", "Lowest;Mobile;SD;HD;Highest", "Quality", "Highest"),
+ ("original", "bool", "Try to download the original file first", True)]
+
+ __description__ = """Vimeo.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ NAME_PATTERN = r'<title>(?P<N>.+) on Vimeo<'
+ OFFLINE_PATTERN = r'class="exception_header"'
+ TEMP_OFFLINE_PATTERN = r'Please try again in a few minutes.<'
+
+ URL_REPLACEMENTS = [(__pattern__ + ".*", r'https://www.vimeo.com/\g<ID>')]
+
+ COOKIES = [("vimeo.com", "language", "en")]
+
+
+ def setup(self):
+ self.resumeDownload = True
+ self.multiDL = True
+ self.chunkLimit = -1
+
+
+ def handleFree(self, pyfile):
+ password = self.getPassword()
+
+ if self.js and 'class="btn iconify_down_b"' in self.html:
+ html = self.js.eval(self.load(pyfile.url, get={'action': "download", 'password': password}, decode=True))
+ pattern = r'href="(?P<URL>http://vimeo\.com.+?)".*?\>(?P<QL>.+?) '
+ else:
+ html = self.load("https://player.vimeo.com/video/" + self.info['pattern']['ID'], get={'password': password})
+ pattern = r'"(?P<QL>\w+)":{"profile".*?"(?P<URL>http://pdl\.vimeocdn\.com.+?)"'
+
+ link = dict((l.group('QL').lower(), l.group('URL')) for l in re.finditer(pattern, html))
+
+ if self.getConfig("original"):
+ if "original" in link:
+ self.download(link[q])
+ return
+ else:
+ self.logInfo(_("Original file not downloadable"))
+
+ quality = self.getConfig("quality")
+ if quality == "Highest":
+ qlevel = ("hd", "sd", "mobile")
+ elif quality == "Lowest":
+ qlevel = ("mobile", "sd", "hd")
+ else:
+ qlevel = quality.lower()
+
+ for q in qlevel:
+ if q in link:
+ self.download(link[q])
+ return
+ else:
+ self.logInfo(_("No %s quality video found") % q.upper())
+ else:
+ self.fail(_("No video found!"))
diff --git a/pyload/plugin/hoster/Vipleech4UCom.py b/pyload/plugin/hoster/Vipleech4UCom.py
new file mode 100644
index 000000000..100def197
--- /dev/null
+++ b/pyload/plugin/hoster/Vipleech4UCom.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class Vipleech4UCom(DeadHoster):
+ __name__ = "Vipleech4UCom"
+ __type__ = "hoster"
+ __version__ = "0.20"
+
+ __pattern__ = r'http://(?:www\.)?vipleech4u\.com/manager\.php'
+
+ __description__ = """Vipleech4u.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Kagenoshin", "kagenoshin@gmx.ch")]
diff --git a/pyload/plugin/hoster/WarserverCz.py b/pyload/plugin/hoster/WarserverCz.py
new file mode 100644
index 000000000..d44b751f9
--- /dev/null
+++ b/pyload/plugin/hoster/WarserverCz.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class WarserverCz(DeadHoster):
+ __name__ = "WarserverCz"
+ __type__ = "hoster"
+ __version__ = "0.13"
+
+ __pattern__ = r'http://(?:www\.)?warserver\.cz/stahnout/\d+'
+
+ __description__ = """Warserver.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
diff --git a/pyload/plugin/hoster/WebshareCz.py b/pyload/plugin/hoster/WebshareCz.py
new file mode 100644
index 000000000..58c9c6a44
--- /dev/null
+++ b/pyload/plugin/hoster/WebshareCz.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.network.RequestFactory import getURL
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class WebshareCz(SimpleHoster):
+ __name__ = "WebshareCz"
+ __type__ = "hoster"
+ __version__ = "0.16"
+
+ __pattern__ = r'https?://(?:www\.)?webshare\.cz/(?:#/)?file/(?P<ID>\w+)'
+
+ __description__ = """WebShare.cz hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it"),
+ ("rush", "radek.senfeld@gmail.com")]
+
+
+ @classmethod
+ def getInfo(cls, url="", html=""):
+ info = super(WebshareCz, cls).getInfo(url, html)
+
+ if url:
+ info['pattern'] = re.match(cls.__pattern__, url).groupdict()
+
+ api_data = getURL("https://webshare.cz/api/file_info/",
+ post={'ident': info['pattern']['ID']},
+ decode=True)
+
+ if 'File not found' in api_data:
+ info['status'] = 1
+ else:
+ info["status"] = 2
+ info['name'] = re.search('<name>(.+)</name>', api_data).group(1) or info['name']
+ info['size'] = re.search('<size>(.+)</size>', api_data).group(1) or info['size']
+
+ return info
+
+
+ def handleFree(self, pyfile):
+ wst = self.account.infos['wst'] if self.account and 'wst' in self.account.infos else ""
+
+ api_data = getURL('https://webshare.cz/api/file_link/',
+ post={'ident': self.info['pattern']['ID'], 'wst': wst},
+ decode=True)
+
+ self.logDebug("API data: " + api_data)
+
+ m = re.search('<link>(.+)</link>', api_data)
+ if m is None:
+ self.error(_("Unable to detect direct link"))
+
+ self.link = m.group(1)
+
+
+ def handlePremium(self, pyfile):
+ return self.handleFree(pyfile)
diff --git a/pyload/plugin/hoster/WrzucTo.py b/pyload/plugin/hoster/WrzucTo.py
new file mode 100644
index 000000000..de78d7af2
--- /dev/null
+++ b/pyload/plugin/hoster/WrzucTo.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pycurl import HTTPHEADER
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class WrzucTo(SimpleHoster):
+ __name__ = "WrzucTo"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'http://(?:www\.)?wrzuc\.to/(\w+(\.wt|\.html)|(\w+/?linki/\w+))'
+
+ __description__ = """Wrzuc.to hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'id="file_info">\s*<strong>(?P<N>.*?)</strong>'
+ SIZE_PATTERN = r'class="info">\s*<tr>\s*<td>(?P<S>.*?)</td>'
+
+ COOKIES = [("wrzuc.to", "language", "en")]
+
+
+ def setup(self):
+ self.multiDL = True
+
+
+ def handleFree(self, pyfile):
+ data = dict(re.findall(r'(md5|file): "(.*?)"', self.html))
+ if len(data) != 2:
+ self.error(_("No file ID"))
+
+ self.req.http.c.setopt(HTTPHEADER, ["X-Requested-With: XMLHttpRequest"])
+ self.req.http.lastURL = pyfile.url
+ self.load("http://www.wrzuc.to/ajax/server/prepair", post={"md5": data['md5']})
+
+ self.req.http.lastURL = pyfile.url
+ self.html = self.load("http://www.wrzuc.to/ajax/server/download_link", post={"file": data['file']})
+
+ data.update(re.findall(r'"(download_link|server_id)":"(.*?)"', self.html))
+ if len(data) != 4:
+ self.error(_("No download URL"))
+
+ download_url = "http://%s.wrzuc.to/pobierz/%s" % (data['server_id'], data['download_link'])
+ self.download(download_url)
diff --git a/pyload/plugin/hoster/WuploadCom.py b/pyload/plugin/hoster/WuploadCom.py
new file mode 100644
index 000000000..729db1d4d
--- /dev/null
+++ b/pyload/plugin/hoster/WuploadCom.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class WuploadCom(DeadHoster):
+ __name__ = "WuploadCom"
+ __type__ = "hoster"
+ __version__ = "0.23"
+
+ __pattern__ = r'http://(?:www\.)?wupload\..+?/file/((\w+/)?\d+)(/.*)?'
+
+ __description__ = """Wupload.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("jeix", "jeix@hasnomail.de"),
+ ("Paul King", "")]
diff --git a/pyload/plugin/hoster/X7To.py b/pyload/plugin/hoster/X7To.py
new file mode 100644
index 000000000..ac01bc5ff
--- /dev/null
+++ b/pyload/plugin/hoster/X7To.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class X7To(DeadHoster):
+ __name__ = "X7To"
+ __type__ = "hoster"
+ __version__ = "0.41"
+
+ __pattern__ = r'http://(?:www\.)?x7\.to/'
+
+ __description__ = """X7.to hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("ernieb", "ernieb")]
diff --git a/pyload/plugin/hoster/XFileSharingPro.py b/pyload/plugin/hoster/XFileSharingPro.py
new file mode 100644
index 000000000..8b9f7fcfa
--- /dev/null
+++ b/pyload/plugin/hoster/XFileSharingPro.py
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.XFSHoster import XFSHoster
+
+
+class XFileSharingPro(XFSHoster):
+ __name__ = "XFileSharingPro"
+ __type__ = "hoster"
+ __version__ = "0.44"
+
+ __pattern__ = r'^unmatchable$'
+
+ __description__ = """XFileSharingPro dummy hoster plugin for hook"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ URL_REPLACEMENTS = [("/embed-", "/")]
+
+
+ def _log(self, type, args):
+ msg = " | ".join(str(a).strip() for a in args if a)
+ logger = getattr(self.log, type)
+ logger("%s: %s: %s" % (self.__name__, self.HOSTER_NAME, msg or _("%s MARK" % type.upper())))
+
+
+ def init(self):
+ super(XFileSharingPro, self).init()
+
+ self.__pattern__ = self.core.pluginManager.hosterPlugins[self.__name__]['pattern']
+
+ self.HOSTER_DOMAIN = re.match(self.__pattern__, self.pyfile.url).group("DOMAIN").lower()
+ self.HOSTER_NAME = "".join(part.capitalize() for part in re.split(r'(\.|\d+)', self.HOSTER_DOMAIN) if part != '.')
+
+ if self.HOSTER_NAME[0].isdigit():
+ self.HOSTER_NAME = 'X' + self.HOSTER_NAME
+
+ account = self.core.accountManager.getAccountPlugin(self.HOSTER_NAME)
+
+ if account and account.canUse():
+ self.account = account
+
+ elif self.account:
+ self.account.HOSTER_DOMAIN = self.HOSTER_DOMAIN
+
+ else:
+ return
+
+ self.user, data = self.account.selectAccount()
+ self.req = self.account.getAccountRequest(self.user)
+ self.premium = self.account.isPremium(self.user)
+
+
+ def setup(self):
+ self.chunkLimit = 1
+ self.resumeDownload = self.premium
+ self.multiDL = True
diff --git a/module/plugins/hoster/XHamsterCom.py b/pyload/plugin/hoster/XHamsterCom.py
index 92340152f..92340152f 100644
--- a/module/plugins/hoster/XHamsterCom.py
+++ b/pyload/plugin/hoster/XHamsterCom.py
diff --git a/module/plugins/hoster/XVideosCom.py b/pyload/plugin/hoster/XVideosCom.py
index c5e2921cb..c5e2921cb 100644
--- a/module/plugins/hoster/XVideosCom.py
+++ b/pyload/plugin/hoster/XVideosCom.py
diff --git a/pyload/plugin/hoster/XdadevelopersCom.py b/pyload/plugin/hoster/XdadevelopersCom.py
new file mode 100644
index 000000000..386973a94
--- /dev/null
+++ b/pyload/plugin/hoster/XdadevelopersCom.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*
+#
+# Test links:
+# http://forum.xda-developers.com/devdb/project/dl/?id=10885
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class XdadevelopersCom(SimpleHoster):
+ __name__ = "XdadevelopersCom"
+ __type__ = "hoster"
+ __version__ = "0.03"
+
+ __pattern__ = r'https?://(?:www\.)?forum\.xda-developers\.com/devdb/project/dl/\?id=\d+'
+
+ __description__ = """Xda-developers.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zapp-brannigan", "fuerst.reinje@web.de")]
+
+
+ NAME_PATTERN = r'<label>Filename:</label>\s*<div>\s*(?P<N>.*?)\n'
+ SIZE_PATTERN = r'<label>Size:</label>\s*<div>\s*(?P<S>[\d.,]+)(?P<U>[\w^_]+)'
+ OFFLINE_PATTERN = r'</i> Device Filter</h3>'
+
+
+ def setup(self):
+ self.multiDL = True
+ self.resumeDownload = True
+ self.chunkLimit = 1
+
+
+ def handleFree(self, pyfile):
+ self.link = pyfile.url + "&task=get" #@TODO: Revert to `get={'task': "get"}` in 0.4.10
diff --git a/module/plugins/hoster/Xdcc.py b/pyload/plugin/hoster/Xdcc.py
index 277b7ad0c..277b7ad0c 100644
--- a/module/plugins/hoster/Xdcc.py
+++ b/pyload/plugin/hoster/Xdcc.py
diff --git a/pyload/plugin/hoster/YibaishiwuCom.py b/pyload/plugin/hoster/YibaishiwuCom.py
new file mode 100644
index 000000000..a53acdaf5
--- /dev/null
+++ b/pyload/plugin/hoster/YibaishiwuCom.py
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.utils import json_loads
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class YibaishiwuCom(SimpleHoster):
+ __name__ = "YibaishiwuCom"
+ __type__ = "hoster"
+ __version__ = "0.14"
+
+ __pattern__ = r'http://(?:www\.)?(?:u\.)?115\.com/file/(?P<ID>\w+)'
+
+ __description__ = """115.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ NAME_PATTERN = r'file_name: \'(?P<N>.+?)\''
+ SIZE_PATTERN = r'file_size: \'(?P<S>.+?)\''
+ OFFLINE_PATTERN = ur'<h3><i style="color:red;">哎呀提取码䞍存圚䞍劚搜搜看吧</i></h3>'
+
+ LINK_FREE_PATTERN = r'(/\?ct=(pickcode|download)[^"\']+)'
+
+
+ def handleFree(self, pyfile):
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("LINK_FREE_PATTERN not found"))
+
+ url = m.group(1)
+
+ self.logDebug(('FREEUSER' if m.group(2) == 'download' else 'GUEST') + ' URL', url)
+
+ res = json_loads(self.load("http://115.com" + url, decode=False))
+ if "urls" in res:
+ mirrors = res['urls']
+
+ elif "data" in res:
+ mirrors = res['data']
+
+ else:
+ mirrors = None
+
+ for mr in mirrors:
+ try:
+ url = mr['url'].replace("\\", "")
+ self.logDebug("Trying URL: " + url)
+ self.download(url)
+ break
+ except Exception:
+ continue
+ else:
+ self.fail(_("No working link found"))
diff --git a/module/plugins/hoster/YoupornCom.py b/pyload/plugin/hoster/YoupornCom.py
index 75606935d..75606935d 100644
--- a/module/plugins/hoster/YoupornCom.py
+++ b/pyload/plugin/hoster/YoupornCom.py
diff --git a/module/plugins/hoster/YourfilesTo.py b/pyload/plugin/hoster/YourfilesTo.py
index a600d822f..a600d822f 100644
--- a/module/plugins/hoster/YourfilesTo.py
+++ b/pyload/plugin/hoster/YourfilesTo.py
diff --git a/module/plugins/hoster/YoutubeCom.py b/pyload/plugin/hoster/YoutubeCom.py
index bf8785022..bf8785022 100644
--- a/module/plugins/hoster/YoutubeCom.py
+++ b/pyload/plugin/hoster/YoutubeCom.py
diff --git a/module/plugins/hoster/ZDF.py b/pyload/plugin/hoster/ZDF.py
index da6d6448e..da6d6448e 100644
--- a/module/plugins/hoster/ZDF.py
+++ b/pyload/plugin/hoster/ZDF.py
diff --git a/pyload/plugin/hoster/ZShareNet.py b/pyload/plugin/hoster/ZShareNet.py
new file mode 100644
index 000000000..12c65b206
--- /dev/null
+++ b/pyload/plugin/hoster/ZShareNet.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.DeadHoster import DeadHoster
+
+
+class ZShareNet(DeadHoster):
+ __name__ = "ZShareNet"
+ __type__ = "hoster"
+ __version__ = "0.21"
+
+ __pattern__ = r'https?://(?:ww[2w]\.)?zshares?\.net/.+'
+
+ __description__ = """ZShare.net hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("espes", ""),
+ ("Cptn Sandwich", "")]
diff --git a/pyload/plugin/hoster/ZeveraCom.py b/pyload/plugin/hoster/ZeveraCom.py
new file mode 100644
index 000000000..264a62a7d
--- /dev/null
+++ b/pyload/plugin/hoster/ZeveraCom.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urlparse import urljoin
+
+from pyload.plugin.internal.MultiHoster import MultiHoster
+
+
+class ZeveraCom(MultiHoster):
+ __name__ = "ZeveraCom"
+ __type__ = "hoster"
+ __version__ = "0.28"
+
+ __pattern__ = r'https?://(?:www\.)zevera\.com/(getFiles\.ashx|Members/download\.ashx)\?.*ourl=.+'
+
+ __description__ = """Zevera.com multi-hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ def handlePremium(self, pyfile):
+ self.link = "https://%s/getFiles.ashx?ourl=%s" % (self.account.HOSTER_DOMAIN, pyfile.url)
+
+
+ def checkFile(self):
+ if self.checkDownload({"error": 'action="ErrorDownload.aspx'}):
+ self.fail(_("Error response received"))
+
+ return super(ZeveraCom, self).checkFile()
diff --git a/pyload/plugin/hoster/ZippyshareCom.py b/pyload/plugin/hoster/ZippyshareCom.py
new file mode 100644
index 000000000..0aa59fdaa
--- /dev/null
+++ b/pyload/plugin/hoster/ZippyshareCom.py
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.CaptchaService import ReCaptcha
+from pyload.plugin.internal.SimpleHoster import SimpleHoster
+
+
+class ZippyshareCom(SimpleHoster):
+ __name__ = "ZippyshareCom"
+ __type__ = "hoster"
+ __version__ = "0.72"
+
+ __pattern__ = r'http://www\d{0,2}\.zippyshare\.com/v(/|iew\.jsp.*key=)(?P<KEY>[\w^_]+)'
+
+ __description__ = """Zippyshare.com hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ COOKIES = [("zippyshare.com", "ziplocale", "en")]
+
+ NAME_PATTERN = r'("\d{6,}/"[ ]*\+.+?"/|<title>Zippyshare.com - )(?P<N>.+?)("|</title>)'
+ SIZE_PATTERN = r'>Size:.+?">(?P<S>[\d.,]+) (?P<U>[\w^_]+)'
+ OFFLINE_PATTERN = r'>File does not exist on this server'
+
+ LINK_PREMIUM_PATTERN = r'document.location = \'(.+?)\''
+
+
+ def setup(self):
+ self.chunkLimit = -1
+ self.multiDL = True
+ self.resumeDownload = True
+
+
+ def handleFree(self, pyfile):
+ recaptcha = ReCaptcha(self)
+ captcha_key = recaptcha.detect_key()
+
+ if captcha_key:
+ try:
+ self.link = re.search(self.LINK_PREMIUM_PATTERN, self.html)
+ recaptcha.challenge()
+
+ except Exception, e:
+ self.error(e)
+
+ else:
+ self.link = '/'.join(("d", self.info['pattern']['KEY'], str(self.get_checksum()), self.pyfile.name))
+
+
+ def get_checksum(self):
+ try:
+ n = 2
+ b = int(re.search(r'var b = (\d+)', self.html).group(1))
+ checksum = int("%d3" % (n + n * 2 + b))
+
+ except Exception:
+ self.error(_("Unable to calculate checksum"))
+
+ else:
+ return checksum
diff --git a/module/plugins/internal/__init__.py b/pyload/plugin/hoster/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/plugins/internal/__init__.py
+++ b/pyload/plugin/hoster/__init__.py
diff --git a/pyload/plugin/internal/BasePlugin.py b/pyload/plugin/internal/BasePlugin.py
new file mode 100644
index 000000000..103e0d5cb
--- /dev/null
+++ b/pyload/plugin/internal/BasePlugin.py
@@ -0,0 +1,92 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urllib import unquote
+from urlparse import urljoin, urlparse
+
+from pyload.network.HTTPRequest import BadHeader
+from pyload.plugin.internal.SimpleHoster import fileUrl
+from pyload.plugin.Hoster import Hoster
+
+
+class BasePlugin(Hoster):
+ __name__ = "BasePlugin"
+ __type__ = "hoster"
+ __version__ = "0.34"
+
+ __pattern__ = r'^unmatchable$'
+
+ __description__ = """Base plugin when any other didnt fit"""
+ __license__ = "GPLv3"
+ __authors__ = [("RaNaN", "RaNaN@pyload.org"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ @classmethod
+ def getInfo(cls, url="", html=""): #@TODO: Move to hoster class in 0.4.10
+ url = unquote(url)
+ url_p = urlparse(url)
+ return {'name' : (url_p.path.split('/')[-1]
+ or url_p.query.split('=', 1)[::-1][0].split('&', 1)[0]
+ or url_p.netloc.split('.', 1)[0]),
+ 'size' : 0,
+ 'status': 3 if url else 8,
+ 'url' : url}
+
+
+ def setup(self):
+ self.chunkLimit = -1
+ self.multiDL = True
+ self.resumeDownload = True
+
+
+ def process(self, pyfile):
+ """main function"""
+
+ pyfile.name = self.getInfo(pyfile.url)['name']
+
+ if not pyfile.url.startswith("http"):
+ self.fail(_("No plugin matched"))
+
+ for _i in xrange(5):
+ try:
+ link = fileUrl(self, unquote(pyfile.url))
+
+ if link:
+ self.download(link, ref=False, disposition=True)
+ else:
+ self.fail(_("File not found"))
+
+ except BadHeader, e:
+ if e.code is 404:
+ self.offline()
+
+ elif e.code in (401, 403):
+ self.logDebug("Auth required", "Received HTTP status code: %d" % e.code)
+
+ account = self.core.accountManager.getAccountPlugin('Http')
+ servers = [x['login'] for x in account.getAllAccounts()]
+ server = urlparse(pyfile.url).netloc
+
+ if server in servers:
+ self.logDebug("Logging on to %s" % server)
+ self.req.addAuth(account.getAccountData(server)['password'])
+ else:
+ pwd = self.getPassword()
+ if ':' in pwd:
+ self.req.addAuth(pwd)
+ else:
+ self.fail(_("Authorization required"))
+ else:
+ self.fail(e)
+ else:
+ break
+ else:
+ self.fail(_("No file downloaded")) #@TODO: Move to hoster class in 0.4.10
+
+ check = self.checkDownload({'empty file': re.compile(r'\A\Z'),
+ 'html file' : re.compile(r'\A\s*<!DOCTYPE html'),
+ 'html error': re.compile(r'\A\s*(<.+>)?\d{3}(\Z|\s+)')})
+ if check:
+ self.fail(check.capitalize())
diff --git a/pyload/plugin/internal/DeadCrypter.py b/pyload/plugin/internal/DeadCrypter.py
new file mode 100644
index 000000000..ddeb0431d
--- /dev/null
+++ b/pyload/plugin/internal/DeadCrypter.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.Crypter import Crypter as _Crypter
+
+
+class DeadCrypter(_Crypter):
+ __name__ = "DeadCrypter"
+ __type__ = "crypter"
+ __version__ = "0.04"
+
+ __pattern__ = r'^unmatchable$'
+
+ __description__ = """Crypter is no longer available"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it")]
+
+
+ @classmethod
+ def apiInfo(cls, url="", get={}, post={}):
+ api = super(DeadCrypter, self).apiInfo(url, get, post)
+ api['status'] = 1
+ return api
+
+
+ def setup(self):
+ self.pyfile.error = "Crypter is no longer available"
+ self.offline() #@TODO: self.offline("Crypter is no longer available")
diff --git a/pyload/plugin/internal/DeadHoster.py b/pyload/plugin/internal/DeadHoster.py
new file mode 100644
index 000000000..1596943ae
--- /dev/null
+++ b/pyload/plugin/internal/DeadHoster.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.Hoster import Hoster as _Hoster
+
+
+class DeadHoster(_Hoster):
+ __name__ = "DeadHoster"
+ __type__ = "hoster"
+ __version__ = "0.14"
+
+ __pattern__ = r'^unmatchable$'
+
+ __description__ = """Hoster is no longer available"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz")]
+
+
+ @classmethod
+ def apiInfo(cls, url="", get={}, post={}):
+ api = super(DeadHoster, self).apiInfo(url, get, post)
+ api['status'] = 1
+ return api
+
+
+ def setup(self):
+ self.pyfile.error = "Hoster is no longer available"
+ self.offline() #@TODO: self.offline("Hoster is no longer available")
diff --git a/pyload/plugin/internal/MultiHook.py b/pyload/plugin/internal/MultiHook.py
new file mode 100644
index 000000000..2beccfcc5
--- /dev/null
+++ b/pyload/plugin/internal/MultiHook.py
@@ -0,0 +1,308 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from time import sleep
+
+from pyload.plugin.Hook import Hook
+from pyload.utils import decode, remove_chars
+
+
+class MultiHook(Hook):
+ __name__ = "MultiHook"
+ __type__ = "hook"
+ __version__ = "0.37"
+
+ __config__ = [("pluginmode" , "all;listed;unlisted", "Use for plugins" , "all"),
+ ("pluginlist" , "str" , "Plugin list (comma separated)" , "" ),
+ ("revertfailed" , "bool" , "Revert to standard download if fails", True ),
+ ("retry" , "int" , "Number of retries before revert" , 10 ),
+ ("retryinterval" , "int" , "Retry interval in minutes" , 1 ),
+ ("reload" , "bool" , "Reload plugin list" , True ),
+ ("reloadinterval", "int" , "Reload interval in hours" , 12 )]
+
+ __description__ = """Hook plugin for multi hoster/crypter"""
+ __license__ = "GPLv3"
+ __authors__ = [("pyLoad Team", "admin@pyload.org"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ MIN_INTERVAL = 1 * 60 * 60
+
+ DOMAIN_REPLACEMENTS = [(r'180upload\.com' , "hundredeightyupload.com"),
+ (r'1fichier\.com' , "onefichier.com" ),
+ (r'2shared\.com' , "twoshared.com" ),
+ (r'4shared\.com' , "fourshared.com" ),
+ (r'bayfiles\.net' , "bayfiles.com" ),
+ (r'cloudnator\.com' , "shragle.com" ),
+ (r'dfiles\.eu' , "depositfiles.com" ),
+ (r'easy-share\.com' , "crocko.com" ),
+ (r'freakshare\.net' , "freakshare.com" ),
+ (r'hellshare\.com' , "hellshare.cz" ),
+ (r'ifile\.it' , "filecloud.io" ),
+ (r'nowdownload\.\w+', "nowdownload.sx" ),
+ (r'nowvideo\.\w+' , "nowvideo.sx" ),
+ (r'putlocker\.com' , "firedrive.com" ),
+ (r'share-?rapid\.cz', "multishare.cz" ),
+ (r'ul\.to' , "uploaded.to" ),
+ (r'uploaded\.net' , "uploaded.to" ),
+ (r'uploadhero\.co' , "uploadhero.com" ),
+ (r'zshares\.net' , "zshare.net" ),
+ (r'(\d+.+)' , "X\1" )]
+
+
+ def setup(self):
+ self.plugins = []
+ self.supported = []
+ self.new_supported = []
+
+ self.account = None
+ self.pluginclass = None
+ self.pluginmodule = None
+ self.pluginname = None
+ self.plugintype = None
+
+ self._initPlugin()
+
+
+ def _initPlugin(self):
+ plugin, type = self.core.pluginManager.findPlugin(self.__name__)
+
+ if not plugin:
+ self.logWarning("Hook plugin will be deactivated due missing plugin reference")
+ self.setConfig('activated', False)
+ else:
+ self.pluginname = self.__name__
+ self.plugintype = type
+ self.pluginmodule = self.core.pluginManager.loadModule(type, self.__name__)
+ self.pluginclass = getattr(self.pluginmodule, self.__name__)
+
+
+ def _loadAccount(self):
+ self.account = self.core.accountManager.getAccountPlugin(self.pluginname)
+
+ if self.account and not self.account.canUse():
+ self.account = None
+
+ if not self.account and hasattr(self.pluginclass, "LOGIN_ACCOUNT") and self.pluginclass.LOGIN_ACCOUNT:
+ self.logWarning("Hook plugin will be deactivated due missing account reference")
+ self.setConfig('activated', False)
+
+
+ def activate(self):
+ self._loadAccount()
+
+
+ def getURL(self, *args, **kwargs): #@TODO: Remove in 0.4.10
+ """ see HTTPRequest for argument list """
+ h = pyreq.getHTTPRequest(timeout=120)
+ try:
+ if not 'decode' in kwargs:
+ kwargs['decode'] = True
+ rep = h.load(*args, **kwargs)
+ finally:
+ h.close()
+
+ return rep
+
+
+ def getConfig(self, option, default=''):
+ """getConfig with default value - sublass may not implements all config options"""
+ try:
+ return self.getConf(option)
+
+ except KeyError:
+ return default
+
+
+ def pluginsCached(self):
+ if self.plugins:
+ return self.plugins
+
+ for _i in xrange(3):
+ try:
+ pluginset = self._pluginSet(self.getHosters() if self.plugintype == "hoster" else self.getCrypters())
+
+ except Exception, e:
+ self.logError(e, "Waiting 1 minute and retry")
+ sleep(60)
+
+ else:
+ break
+ else:
+ return list()
+
+ try:
+ configmode = self.getConfig("pluginmode", 'all')
+ if configmode in ("listed", "unlisted"):
+ pluginlist = self.getConfig("pluginlist", '').replace('|', ',').replace(';', ',').split(',')
+ configset = self._pluginSet(pluginlist)
+
+ if configmode == "listed":
+ pluginset &= configset
+ else:
+ pluginset -= configset
+
+ except Exception, e:
+ self.logError(e)
+
+ self.plugins = list(pluginset)
+
+ return self.plugins
+
+
+ def _pluginSet(self, plugins):
+ plugins = set((decode(x).strip().lower() for x in plugins if '.' in x))
+
+ for rf, rt in self.DOMAIN_REPLACEMENTS:
+ regex = re.compile(rf)
+ for p in filter(lambda x: regex.match(x), plugins):
+ plugins.remove(p)
+ plugins.add(re.sub(rf, rt, p))
+
+ plugins.discard('')
+
+ return plugins
+
+
+ def getHosters(self):
+ """Load list of supported hoster
+
+ :return: List of domain names
+ """
+ raise NotImplementedError
+
+
+ def getCrypters(self):
+ """Load list of supported crypters
+
+ :return: List of domain names
+ """
+ raise NotImplementedError
+
+
+ def periodical(self):
+ """reload plugin list periodically"""
+ self.logInfo(_("Reloading supported %s list") % self.plugintype)
+
+ old_supported = self.supported
+
+ self.supported = []
+ self.new_supported = []
+ self.plugins = []
+
+ self.overridePlugins()
+
+ old_supported = [plugin for plugin in old_supported if plugin not in self.supported]
+
+ if old_supported:
+ self.logDebug("Unload: %s" % ", ".join(old_supported))
+ for plugin in old_supported:
+ self.unloadPlugin(plugin)
+
+ if self.getConfig("reload", True):
+ self.interval = max(self.getConfig("reloadinterval", 12) * 60 * 60, self.MIN_INTERVAL)
+ else:
+ self.core.scheduler.removeJob(self.cb)
+ self.cb = None
+
+
+ def overridePlugins(self):
+ excludedList = []
+
+ if self.plugintype == "hoster":
+ pluginMap = dict((name.lower(), name) for name in self.core.pluginManager.hosterPlugins.iterkeys())
+ accountList = [account.type.lower() for account in self.core.api.getAccounts(False) if account.valid and account.premium]
+ else:
+ pluginMap = {}
+ accountList = [name[::-1].replace("Folder"[::-1], "", 1).lower()[::-1] for name in self.core.pluginManager.crypterPlugins.iterkeys()]
+
+ for plugin in self.pluginsCached():
+ name = remove_chars(plugin, "-.")
+
+ if name in accountList:
+ excludedList.append(plugin)
+ else:
+ if name in pluginMap:
+ self.supported.append(pluginMap[name])
+ else:
+ self.new_supported.append(plugin)
+
+ if not self.supported and not self.new_supported:
+ self.logError(_("No %s loaded") % self.plugintype)
+ return
+
+ # inject plugin plugin
+ self.logDebug("Overwritten %ss: %s" % (self.plugintype, ", ".join(sorted(self.supported))))
+
+ for plugin in self.supported:
+ hdict = self.core.pluginManager.plugins[self.plugintype][plugin]
+ hdict['new_module'] = self.pluginmodule
+ hdict['new_name'] = self.pluginname
+
+ if excludedList:
+ self.logInfo(_("%ss not overwritten: %s") % (self.plugintype.capitalize(), ", ".join(sorted(excludedList))))
+
+ if self.new_supported:
+ plugins = sorted(self.new_supported)
+
+ self.logDebug("New %ss: %s" % (self.plugintype, ", ".join(plugins)))
+
+ # create new regexp
+ regexp = r'.*(?P<DOMAIN>%s).*' % "|".join([x.replace(".", "\.") for x in plugins])
+ if hasattr(self.pluginclass, "__pattern__") and isinstance(self.pluginclass.__pattern__, basestring) and '://' in self.pluginclass.__pattern__:
+ regexp = r'%s|%s' % (self.pluginclass.__pattern__, regexp)
+
+ self.logDebug("Regexp: %s" % regexp)
+
+ hdict = self.core.pluginManager.plugins[self.plugintype][self.pluginname]
+ hdict['pattern'] = regexp
+ hdict['re'] = re.compile(regexp)
+
+
+ def unloadPlugin(self, plugin):
+ hdict = self.core.pluginManager.plugins[self.plugintype][plugin]
+ if "module" in hdict:
+ del hdict['module']
+
+ if "new_module" in hdict:
+ del hdict['new_module']
+ del hdict['new_name']
+
+
+ def deactivate(self):
+ """Remove override for all plugins. Scheduler job is removed by hookmanager"""
+ for plugin in self.supported:
+ self.unloadPlugin(plugin)
+
+ # reset pattern
+ hdict = self.core.pluginManager.plugins[self.plugintype][self.pluginname]
+
+ hdict['pattern'] = getattr(self.pluginclass, "__pattern__", r'^unmatchable$')
+ hdict['re'] = re.compile(hdict['pattern'])
+
+
+ def downloadFailed(self, pyfile):
+ """remove plugin override if download fails but not if file is offline/temp.offline"""
+ if pyfile.status != 8 or not self.getConfig("revertfailed", True):
+ return
+
+ hdict = self.core.pluginManager.plugins[self.plugintype][pyfile.pluginname]
+ if "new_name" in hdict and hdict['new_name'] == self.pluginname:
+ if pyfile.error == "MultiHook":
+ self.logDebug("Unload MultiHook", pyfile.pluginname, hdict)
+ self.unloadPlugin(pyfile.pluginname)
+ pyfile.setStatus("queued")
+ pyfile.sync()
+ else:
+ retries = max(self.getConfig("retry", 10), 0)
+ wait_time = max(self.getConfig("retryinterval", 1), 0)
+
+ if 0 < retries > pyfile.plugin.retries:
+ self.logInfo(_("Retrying: %s") % pyfile.name)
+ pyfile.setCustomStatus("MultiHook", "queued")
+ pyfile.sync()
+
+ pyfile.plugin.retries += 1
+ pyfile.plugin.setWait(wait_time)
+ pyfile.plugin.wait()
diff --git a/pyload/plugin/internal/MultiHoster.py b/pyload/plugin/internal/MultiHoster.py
new file mode 100644
index 000000000..ed425ffaa
--- /dev/null
+++ b/pyload/plugin/internal/MultiHoster.py
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from pyload.plugin.internal.SimpleHoster import SimpleHoster, replace_patterns, set_cookies
+
+
+class MultiHoster(SimpleHoster):
+ __name__ = "MultiHoster"
+ __type__ = "hoster"
+ __version__ = "0.37"
+
+ __pattern__ = r'^unmatchable$'
+
+ __description__ = """Multi hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ LOGIN_ACCOUNT = True
+
+
+ def setup(self):
+ self.chunkLimit = 1
+ self.multiDL = bool(self.account)
+ self.resumeDownload = self.premium
+
+
+ def prepare(self):
+ self.info = {}
+ self.html = ""
+ self.link = "" #@TODO: Move to hoster class in 0.4.10
+ self.directDL = False #@TODO: Move to hoster class in 0.4.10
+
+ if self.LOGIN_ACCOUNT and not self.account:
+ self.fail(_("Required account not found"))
+
+ self.req.setOption("timeout", 120)
+
+ if isinstance(self.COOKIES, list):
+ set_cookies(self.req.cj, self.COOKIES)
+
+ if self.DIRECT_LINK is None:
+ self.directDL = self.__pattern__ != r'^unmatchable$' and re.match(self.__pattern__, self.pyfile.url)
+ else:
+ self.directDL = self.DIRECT_LINK
+
+ self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS)
+
+
+ def process(self, pyfile):
+ self.prepare()
+
+ if self.directDL:
+ self.checkInfo()
+ self.logDebug("Looking for direct download link...")
+ self.handleDirect(pyfile)
+
+ if not self.link and not self.lastDownload:
+ self.preload()
+
+ self.checkErrors()
+ self.checkStatus(getinfo=False)
+
+ if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()):
+ self.logDebug("Handled as premium download")
+ self.handlePremium(pyfile)
+
+ elif not self.LOGIN_ACCOUNT or (not self.CHECK_TRAFFIC or self.checkTrafficLeft()):
+ self.logDebug("Handled as free download")
+ self.handleFree(pyfile)
+
+ self.downloadLink(self.link, True)
+ self.checkFile()
+
+
+ def handlePremium(self, pyfile):
+ return self.handleFree(pyfile)
+
+
+ def handleFree(self, pyfile):
+ if self.premium:
+ raise NotImplementedError
+ else:
+ self.fail(_("Required premium account not found"))
diff --git a/pyload/plugin/internal/SimpleCrypter.py b/pyload/plugin/internal/SimpleCrypter.py
new file mode 100644
index 000000000..e4b8874f3
--- /dev/null
+++ b/pyload/plugin/internal/SimpleCrypter.py
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urlparse import urljoin, urlparse
+
+from pyload.plugin.Crypter import Crypter
+from pyload.plugin.internal.SimpleHoster import SimpleHoster, replace_patterns, set_cookies
+from pyload.utils import fixup
+
+
+class SimpleCrypter(Crypter, SimpleHoster):
+ __name__ = "SimpleCrypter"
+ __type__ = "crypter"
+ __version__ = "0.43"
+
+ __pattern__ = r'^unmatchable$'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True), #: Overrides core.config['general']['folder_per_package']
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Simple decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("stickell", "l.stickell@yahoo.it"),
+ ("zoidberg", "zoidberg@mujmail.cz"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ """
+ Following patterns should be defined by each crypter:
+
+ LINK_PATTERN: Download link or regex to catch links in group(1)
+ example: LINK_PATTERN = r'<div class="link"><a href="(.+?)"'
+
+ NAME_PATTERN: (optional) folder name or page title
+ example: NAME_PATTERN = r'<title>Files of: (?P<N>[^<]+) folder</title>'
+
+ OFFLINE_PATTERN: (optional) Checks if the page is unreachable
+ example: OFFLINE_PATTERN = r'File (deleted|not found)'
+
+ TEMP_OFFLINE_PATTERN: (optional) Checks if the page is temporarily unreachable
+ example: TEMP_OFFLINE_PATTERN = r'Server maintainance'
+
+
+ You can override the getLinks method if you need a more sophisticated way to extract the links.
+
+
+ If the links are splitted on multiple pages you can define the PAGES_PATTERN regex:
+
+ PAGES_PATTERN: (optional) group(1) should be the number of overall pages containing the links
+ example: PAGES_PATTERN = r'Pages: (\d+)'
+
+ and its loadPage method:
+
+
+ def loadPage(self, page_n):
+ return the html of the page number page_n
+ """
+
+ LINK_PATTERN = None
+
+ NAME_REPLACEMENTS = [("&#?\w+;", fixup)]
+ URL_REPLACEMENTS = []
+
+ TEXT_ENCODING = False #: Set to True or encoding name if encoding in http header is not correct
+ COOKIES = True #: or False or list of tuples [(domain, name, value)]
+
+ LOGIN_ACCOUNT = False
+ LOGIN_PREMIUM = False
+
+
+ def prepare(self):
+ self.pyfile.error = "" #@TODO: Remove in 0.4.10
+
+ self.info = {}
+ self.html = ""
+ self.links = [] #@TODO: Move to hoster class in 0.4.10
+
+ if self.LOGIN_PREMIUM and not self.premium:
+ self.fail(_("Required premium account not found"))
+
+ if self.LOGIN_ACCOUNT and not self.account:
+ self.fail(_("Required account not found"))
+
+ self.req.setOption("timeout", 120)
+
+ if isinstance(self.COOKIES, list):
+ set_cookies(self.req.cj, self.COOKIES)
+
+ self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS)
+
+
+ def decrypt(self, pyfile):
+ self.prepare()
+
+ self.preload()
+ self.checkInfo()
+
+ self.links = self.getLinks()
+
+ if hasattr(self, 'PAGES_PATTERN') and hasattr(self, 'loadPage'):
+ self.handlePages(pyfile)
+
+ self.logDebug("Package has %d links" % len(self.links))
+
+ if self.links:
+ self.packages = [(self.info['name'], self.links, self.info['folder'])]
+
+ elif not self.urls and not self.packages: #@TODO: Remove in 0.4.10
+ self.fail(_("No link grabbed"))
+
+
+ def checkNameSize(self, getinfo=True):
+ if not self.info or getinfo:
+ self.logDebug("File info (BEFORE): %s" % self.info)
+ self.info.update(self.getInfo(self.pyfile.url, self.html))
+ self.logDebug("File info (AFTER): %s" % self.info)
+
+ try:
+ url = self.info['url'].strip()
+ name = self.info['name'].strip()
+ if name and name != url:
+ self.pyfile.name = name
+
+ except Exception:
+ pass
+
+ try:
+ folder = self.info['folder'] = self.pyfile.name
+
+ except Exception:
+ pass
+
+ self.logDebug("File name: %s" % self.pyfile.name,
+ "File folder: %s" % self.pyfile.name)
+
+
+ def getLinks(self):
+ """
+ Returns the links extracted from self.html
+ You should override this only if it's impossible to extract links using only the LINK_PATTERN.
+ """
+ url_p = urlparse(self.pyfile.url)
+ baseurl = "%s://%s" % (url_p.scheme, url_p.netloc)
+
+ return [urljoin(baseurl, link) if not urlparse(link).scheme else link \
+ for link in re.findall(self.LINK_PATTERN, self.html)]
+
+
+ def handlePages(self, pyfile):
+ try:
+ pages = int(re.search(self.PAGES_PATTERN, self.html).group(1))
+ except Exception:
+ pages = 1
+
+ for p in xrange(2, pages + 1):
+ self.html = self.loadPage(p)
+ self.links += self.getLinks()
diff --git a/pyload/plugin/internal/SimpleDereferer.py b/pyload/plugin/internal/SimpleDereferer.py
new file mode 100644
index 000000000..6d323b4b0
--- /dev/null
+++ b/pyload/plugin/internal/SimpleDereferer.py
@@ -0,0 +1,98 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from urllib import unquote
+
+from pyload.plugin.Crypter import Crypter
+from pyload.plugin.internal.SimpleHoster import fileUrl, set_cookies
+
+
+class SimpleDereferer(Crypter):
+ __name__ = "SimpleDereferer"
+ __type__ = "crypter"
+ __version__ = "0.07"
+
+ __pattern__ = r'^unmatchable$'
+ __config__ = [("use_subfolder", "bool", "Save package to subfolder", True),
+ ("subfolder_per_package", "bool", "Create a subfolder for each package", True)]
+
+ __description__ = """Simple dereferer plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ """
+ Following patterns should be defined by each crypter:
+
+ LINK_PATTERN: Regex to catch the redirect url in group(1)
+ example: LINK_PATTERN = r'<div class="link"><a href="(.+?)"'
+
+ OFFLINE_PATTERN: (optional) Checks if the page is unreachable
+ example: OFFLINE_PATTERN = r'File (deleted|not found)'
+
+ TEMP_OFFLINE_PATTERN: (optional) Checks if the page is temporarily unreachable
+ example: TEMP_OFFLINE_PATTERN = r'Server maintainance'
+
+
+ You can override the getLinks method if you need a more sophisticated way to extract the redirect url.
+ """
+
+ LINK_PATTERN = None
+
+ TEXT_ENCODING = False
+ COOKIES = True
+
+
+ def decrypt(self, pyfile):
+ link = fileUrl(self, pyfile.url)
+
+ if not link:
+ try:
+ link = unquote(re.match(self.__pattern__, pyfile.url).group('LINK'))
+
+ except Exception:
+ self.prepare()
+ self.preload()
+ self.checkStatus()
+
+ link = self.getLink()
+
+ if link.strip():
+ self.urls = [link.strip()] #@TODO: Remove `.strip()` in 0.4.10
+
+ elif not self.urls and not self.packages: #@TODO: Remove in 0.4.10
+ self.fail(_("No link grabbed"))
+
+
+ def prepare(self):
+ self.info = {}
+ self.html = ""
+
+ self.req.setOption("timeout", 120)
+
+ if isinstance(self.COOKIES, list):
+ set_cookies(self.req.cj, self.COOKIES)
+
+
+ def preload(self):
+ self.html = self.load(self.pyfile.url, cookies=bool(self.COOKIES), decode=not self.TEXT_ENCODING)
+
+ if isinstance(self.TEXT_ENCODING, basestring):
+ self.html = unicode(self.html, self.TEXT_ENCODING)
+
+
+ def checkStatus(self):
+ if hasattr(self, "OFFLINE_PATTERN") and re.search(self.OFFLINE_PATTERN, self.html):
+ self.offline()
+
+ elif hasattr(self, "TEMP_OFFLINE_PATTERN") and re.search(self.TEMP_OFFLINE_PATTERN, self.html):
+ self.tempOffline()
+
+
+ def getLink(self):
+ try:
+ return re.search(self.LINK_PATTERN, self.html).group(1)
+
+ except Exception:
+ pass
diff --git a/pyload/plugin/internal/SimpleHoster.py b/pyload/plugin/internal/SimpleHoster.py
new file mode 100644
index 000000000..ac7f5aa4d
--- /dev/null
+++ b/pyload/plugin/internal/SimpleHoster.py
@@ -0,0 +1,701 @@
+# -*- coding: utf-8 -*-
+
+import mimetypes
+import os
+import re
+
+from datetime import datetime, timedelta
+from inspect import isclass
+from time import time
+from urllib import unquote
+from urlparse import urljoin, urlparse
+
+from pyload.datatype.File import statusMap as _statusMap
+from pyload.network.CookieJar import CookieJar
+from pyload.network.HTTPRequest import BadHeader
+from pyload.network.RequestFactory import getURL
+from pyload.plugin.Hoster import Hoster
+from pyload.plugin.Plugin import Fail
+from pyload.utils import fixup, fs_encode, parseFileSize
+
+
+#@TODO: Adapt and move to PyFile in 0.4.10
+statusMap = dict((v, k) for k, v in _statusMap.iteritems())
+
+
+#@TODO: Remove in 0.4.10 and redirect to self.error instead
+def _error(self, reason, type):
+ if not reason and not type:
+ type = "unknown"
+
+ msg = _("%s error") % type.strip().capitalize() if type else _("Error")
+ msg += ": %s" % reason.strip() if reason else ""
+ msg += _(" | Plugin may be out of date")
+
+ raise Fail(msg)
+
+
+#@TODO: Remove in 0.4.10
+def _wait(self, seconds, reconnect):
+ if seconds:
+ self.setWait(int(seconds) + 1)
+
+ if reconnect is not None:
+ self.wantReconnect = reconnect
+
+ super(SimpleHoster, self).wait()
+
+
+def replace_patterns(string, ruleslist):
+ for r in ruleslist:
+ rf, rt = r
+ string = re.sub(rf, rt, string)
+ return string
+
+
+def set_cookies(cj, cookies):
+ for cookie in cookies:
+ if isinstance(cookie, tuple) and len(cookie) == 3:
+ domain, name, value = cookie
+ cj.setCookie(domain, name, value)
+
+
+def parseHtmlTagAttrValue(attr_name, tag):
+ m = re.search(r"%s\s*=\s*([\"']?)((?<=\")[^\"]+|(?<=')[^']+|[^>\s\"'][^>\s]*)\1" % attr_name, tag, re.I)
+ return m.group(2) if m else None
+
+
+def parseHtmlForm(attr_str, html, input_names={}):
+ for form in re.finditer(r"(?P<TAG><form[^>]*%s[^>]*>)(?P<CONTENT>.*?)</?(form|body|html)[^>]*>" % attr_str,
+ html, re.S | re.I):
+ inputs = {}
+ action = parseHtmlTagAttrValue("action", form.group('TAG'))
+
+ for inputtag in re.finditer(r'(<(input|textarea)[^>]*>)([^<]*(?=</\2)|)', form.group('CONTENT'), re.S | re.I):
+ name = parseHtmlTagAttrValue("name", inputtag.group(1))
+ if name:
+ value = parseHtmlTagAttrValue("value", inputtag.group(1))
+ if not value:
+ inputs[name] = inputtag.group(3) or ''
+ else:
+ inputs[name] = value
+
+ if input_names:
+ # check input attributes
+ for key, val in input_names.iteritems():
+ if key in inputs:
+ if isinstance(val, basestring) and inputs[key] == val:
+ continue
+ elif isinstance(val, tuple) and inputs[key] in val:
+ continue
+ elif hasattr(val, "search") and re.match(val, inputs[key]):
+ continue
+ break #: attibute value does not match
+ else:
+ break #: attibute name does not match
+ else:
+ return action, inputs #: passed attribute check
+ else:
+ # no attribute check
+ return action, inputs
+
+ return {}, None #: no matching form found
+
+
+#: Deprecated
+def parseFileInfo(plugin, url="", html=""):
+ if hasattr(plugin, "getInfo"):
+ info = plugin.getInfo(url, html)
+ res = info['name'], info['size'], info['status'], info['url']
+ else:
+ url = unquote(url)
+ url_p = urlparse(url)
+ res = ((url_p.path.split('/')[-1]
+ or url_p.query.split('=', 1)[::-1][0].split('&', 1)[0]
+ or url_p.netloc.split('.', 1)[0]),
+ 0,
+ 3 if url else 8,
+ url)
+
+ return res
+
+
+#@TODO: Remove in 0.4.10
+#@NOTE: Every plugin must have own parseInfos classmethod to work with 0.4.10
+# def create_getInfo(plugin):
+
+ # def generator(list):
+ # for x in list:
+ # yield x
+
+ # if hasattr(plugin, "parseInfos"):
+ # fn = lambda urls: generator((info['name'], info['size'], info['status'], info['url']) for info in plugin.parseInfos(urls))
+ # else:
+ # fn = lambda urls: generator(parseFileInfo(url) for url in urls)
+
+ # return fn
+
+
+def timestamp():
+ return int(time() * 1000)
+
+
+#@TODO: Move to hoster class in 0.4.10
+def fileUrl(self, url, follow_location=None):
+ link = ""
+ redirect = 1
+
+ if type(follow_location) is int:
+ redirect = max(follow_location, 1)
+ else:
+ redirect = 5
+
+ for i in xrange(redirect):
+ try:
+ self.logDebug("Redirect #%d to: %s" % (i, url))
+ header = self.load(url, ref=True, cookies=True, just_header=True, decode=True)
+
+ except Exception: #: Bad bad bad...
+ req = pyreq.getHTTPRequest()
+ res = req.load(url, cookies=True, just_header=True, decode=True)
+
+ req.close()
+
+ header = {"code": req.code}
+ for line in res.splitlines():
+ line = line.strip()
+ if not line or ":" not in line:
+ continue
+
+ key, none, value = line.partition(":")
+ key = key.lower().strip()
+ value = value.strip()
+
+ if key in header:
+ if type(header[key]) == list:
+ header[key].append(value)
+ else:
+ header[key] = [header[key], value]
+ else:
+ header[key] = value
+
+ if 'content-disposition' in header:
+ link = url
+
+ elif 'location' in header and header['location'].strip():
+ location = header['location']
+
+ if not urlparse(location).scheme:
+ url_p = urlparse(url)
+ baseurl = "%s://%s" % (url_p.scheme, url_p.netloc)
+ location = urljoin(baseurl, location)
+
+ if 'code' in header and header['code'] == 302:
+ link = location
+
+ if follow_location:
+ url = location
+ continue
+
+ else:
+ extension = os.path.splitext(urlparse(url).path.split('/')[-1])[-1]
+
+ if 'content-type' in header and header['content-type'].strip():
+ mimetype = header['content-type'].split(';')[0].strip()
+
+ elif extension:
+ mimetype = mimetypes.guess_type(extension, False)[0] or "application/octet-stream"
+
+ else:
+ mimetype = ""
+
+ if mimetype and (link or 'html' not in mimetype):
+ link = url
+ else:
+ link = ""
+
+ break
+
+ else:
+ try:
+ self.logError(_("Too many redirects"))
+ except Exception:
+ pass
+
+ return link
+
+
+def secondsToMidnight(gmt=0):
+ now = datetime.utcnow() + timedelta(hours=gmt)
+
+ if now.hour is 0 and now.minute < 10:
+ midnight = now
+ else:
+ midnight = now + timedelta(days=1)
+
+ td = midnight.replace(hour=0, minute=10, second=0, microsecond=0) - now
+
+ if hasattr(td, 'total_seconds'):
+ res = td.total_seconds()
+ else: #@NOTE: work-around for python 2.5 and 2.6 missing timedelta.total_seconds
+ res = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
+
+ return int(res)
+
+
+class SimpleHoster(Hoster):
+ __name__ = "SimpleHoster"
+ __type__ = "hoster"
+ __version__ = "1.15"
+
+ __pattern__ = r'^unmatchable$'
+
+ __description__ = """Simple hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
+ ("stickell", "l.stickell@yahoo.it"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ """
+ Info patterns should be defined by each hoster:
+
+ INFO_PATTERN: (optional) Name and Size of the file
+ example: INFO_PATTERN = r'(?P<N>file_name) (?P<S>file_size) (?P<U>size_unit)'
+ or
+ NAME_PATTERN: (optional) Name that will be set for the file
+ example: NAME_PATTERN = r'(?P<N>file_name)'
+ SIZE_PATTERN: (optional) Size that will be checked for the file
+ example: SIZE_PATTERN = r'(?P<S>file_size) (?P<U>size_unit)'
+
+ HASHSUM_PATTERN: (optional) Hash code and type of the file
+ example: HASHSUM_PATTERN = r'(?P<H>hash_code) (?P<T>MD5)'
+
+ OFFLINE_PATTERN: (optional) Check if the page is unreachable
+ example: OFFLINE_PATTERN = r'File (deleted|not found)'
+
+ TEMP_OFFLINE_PATTERN: (optional) Check if the page is temporarily unreachable
+ example: TEMP_OFFLINE_PATTERN = r'Server (maintenance|maintainance)'
+
+
+ Error handling patterns are all optional:
+
+ WAIT_PATTERN: (optional) Detect waiting time
+ example: WAIT_PATTERN = r''
+
+ PREMIUM_ONLY_PATTERN: (optional) Check if the file can be downloaded only with a premium account
+ example: PREMIUM_ONLY_PATTERN = r'Premium account required'
+
+ ERROR_PATTERN: (optional) Detect any error preventing download
+ example: ERROR_PATTERN = r''
+
+
+ Instead overriding handleFree and handlePremium methods you can define the following patterns for direct download:
+
+ LINK_FREE_PATTERN: (optional) group(1) should be the direct link for free download
+ example: LINK_FREE_PATTERN = r'<div class="link"><a href="(.+?)"'
+
+ LINK_PREMIUM_PATTERN: (optional) group(1) should be the direct link for premium download
+ example: LINK_PREMIUM_PATTERN = r'<div class="link"><a href="(.+?)"'
+ """
+
+ NAME_REPLACEMENTS = [("&#?\w+;", fixup)]
+ SIZE_REPLACEMENTS = []
+ URL_REPLACEMENTS = []
+
+ TEXT_ENCODING = False #: Set to True or encoding name if encoding value in http header is not correct
+ COOKIES = True #: or False or list of tuples [(domain, name, value)]
+ CHECK_TRAFFIC = False #: Set to True to force checking traffic left for premium account
+ DIRECT_LINK = None #: Set to True to looking for direct link (as defined in handleDirect method), set to None to do it if self.account is True else False
+ MULTI_HOSTER = False #: Set to True to leech other hoster link (as defined in handleMulti method)
+ LOGIN_ACCOUNT = False #: Set to True to require account login
+ DISPOSITION = True #: Work-around to `filename*=UTF-8` bug; remove in 0.4.10
+
+ directLink = fileUrl #@TODO: Remove in 0.4.10
+
+
+ @classmethod
+ def parseInfos(cls, urls): #@TODO: Built-in in 0.4.10 core, then remove from plugins
+ for url in urls:
+ url = replace_patterns(url, cls.URL_REPLACEMENTS)
+ yield cls.getInfo(url)
+
+
+ @classmethod
+ def apiInfo(cls, url="", get={}, post={}):
+ url = unquote(url)
+ url_p = urlparse(url)
+ return {'name' : (url_p.path.split('/')[-1]
+ or url_p.query.split('=', 1)[::-1][0].split('&', 1)[0]
+ or url_p.netloc.split('.', 1)[0]),
+ 'size' : 0,
+ 'status': 3 if url else 8,
+ 'url' : url}
+
+
+ @classmethod
+ def getInfo(cls, url="", html=""):
+ info = cls.apiInfo(url)
+ online = False if info['status'] != 2 else True
+
+ try:
+ info['pattern'] = re.match(cls.__pattern__, url).groupdict() #: pattern groups will be saved here
+
+ except Exception:
+ info['pattern'] = {}
+
+ if not html and not online:
+ if not url:
+ info['error'] = "missing url"
+ info['status'] = 1
+
+ elif info['status'] is 3 and not fileUrl(None, url):
+ try:
+ html = getURL(url, cookies=cls.COOKIES, decode=not cls.TEXT_ENCODING)
+
+ if isinstance(cls.TEXT_ENCODING, basestring):
+ html = unicode(html, cls.TEXT_ENCODING)
+
+ except BadHeader, e:
+ info['error'] = "%d: %s" % (e.code, e.content)
+
+ if e.code is 404:
+ info['status'] = 1
+
+ elif e.code is 503:
+ info['status'] = 6
+
+ if html:
+ if hasattr(cls, "OFFLINE_PATTERN") and re.search(cls.OFFLINE_PATTERN, html):
+ info['status'] = 1
+
+ elif hasattr(cls, "TEMP_OFFLINE_PATTERN") and re.search(cls.TEMP_OFFLINE_PATTERN, html):
+ info['status'] = 6
+
+ else:
+ for pattern in ("INFO_PATTERN", "NAME_PATTERN", "SIZE_PATTERN", "HASHSUM_PATTERN"):
+ try:
+ attr = getattr(cls, pattern)
+ pdict = re.search(attr, html).groupdict()
+
+ if all(True for k in pdict if k not in info['pattern']):
+ info['pattern'].update(pdict)
+
+ except AttributeError:
+ continue
+
+ else:
+ online = True
+
+ if online:
+ info['status'] = 2
+
+ if 'N' in info['pattern']:
+ info['name'] = replace_patterns(unquote(info['pattern']['N'].strip()),
+ cls.NAME_REPLACEMENTS)
+
+ if 'S' in info['pattern']:
+ size = replace_patterns(info['pattern']['S'] + info['pattern']['U'] if 'U' in info['pattern'] else info['pattern']['S'],
+ cls.SIZE_REPLACEMENTS)
+ info['size'] = parseFileSize(size)
+
+ elif isinstance(info['size'], basestring):
+ unit = info['units'] if 'units' in info else None
+ info['size'] = parseFileSize(info['size'], unit)
+
+ if 'H' in info['pattern']:
+ hashtype = info['pattern']['T'] if 'T' in info['pattern'] else "hash"
+ info[hashtype] = info['pattern']['H']
+
+ if not info['pattern']:
+ info.pop('pattern', None)
+
+ return info
+
+
+ def setup(self):
+ self.resumeDownload = self.multiDL = self.premium
+
+
+ def prepare(self):
+ self.pyfile.error = "" #@TODO: Remove in 0.4.10
+
+ self.info = {}
+ self.html = ""
+ self.link = "" #@TODO: Move to hoster class in 0.4.10
+ self.directDL = False #@TODO: Move to hoster class in 0.4.10
+ self.multihost = False #@TODO: Move to hoster class in 0.4.10
+
+ if self.LOGIN_ACCOUNT and not self.account:
+ self.fail(_("Required account not found"))
+
+ self.req.setOption("timeout", 120)
+
+ if isinstance(self.COOKIES, list):
+ set_cookies(self.req.cj, self.COOKIES)
+
+ if (self.MULTI_HOSTER
+ and (self.__pattern__ != self.core.pluginManager.hosterPlugins[self.__name__]['pattern']
+ or re.match(self.__pattern__, self.pyfile.url) is None)):
+ self.multihost = True
+ return
+
+ if self.DIRECT_LINK is None:
+ self.directDL = bool(self.account)
+ else:
+ self.directDL = self.DIRECT_LINK
+
+ self.pyfile.url = replace_patterns(self.pyfile.url, self.URL_REPLACEMENTS)
+
+
+ def preload(self):
+ self.html = self.load(self.pyfile.url, cookies=bool(self.COOKIES), decode=not self.TEXT_ENCODING)
+
+ if isinstance(self.TEXT_ENCODING, basestring):
+ self.html = unicode(self.html, self.TEXT_ENCODING)
+
+
+ def process(self, pyfile):
+ self.prepare()
+ self.checkInfo()
+
+ if self.directDL:
+ self.logDebug("Looking for direct download link...")
+ self.handleDirect(pyfile)
+
+ if self.multihost and not self.link and not self.lastDownload:
+ self.logDebug("Looking for leeched download link...")
+ self.handleMulti(pyfile)
+
+ if not self.link and not self.lastDownload:
+ self.MULTI_HOSTER = False
+ self.retry(1, reason="Multi hoster fails")
+
+ if not self.link and not self.lastDownload:
+ self.preload()
+ self.checkInfo()
+
+ if self.premium and (not self.CHECK_TRAFFIC or self.checkTrafficLeft()):
+ self.logDebug("Handled as premium download")
+ self.handlePremium(pyfile)
+
+ elif not self.LOGIN_ACCOUNT or (not self.CHECK_TRAFFIC or self.checkTrafficLeft()):
+ self.logDebug("Handled as free download")
+ self.handleFree(pyfile)
+
+ self.downloadLink(self.link, self.DISPOSITION) #: Remove `self.DISPOSITION` in 0.4.10
+ self.checkFile()
+
+
+ def downloadLink(self, link, disposition=True):
+ if link and isinstance(link, basestring):
+ self.correctCaptcha()
+
+ if not urlparse(link).scheme:
+ url_p = urlparse(self.pyfile.url)
+ baseurl = "%s://%s" % (url_p.scheme, url_p.netloc)
+ link = urljoin(baseurl, link)
+
+ self.download(link, ref=False, disposition=disposition)
+
+
+ def checkFile(self):
+ if self.cTask and not self.lastDownload:
+ self.invalidCaptcha()
+ self.retry(10, reason=_("Wrong captcha"))
+
+ elif not self.lastDownload or not os.path.exists(fs_encode(self.lastDownload)):
+ self.lastDownload = ""
+ self.error(self.pyfile.error or _("No file downloaded"))
+
+ else:
+ rules = {'empty file': re.compile(r'\A\Z'),
+ 'html file' : re.compile(r'\A\s*<!DOCTYPE html'),
+ 'html error': re.compile(r'\A\s*(<.+>)?\d{3}(\Z|\s+)')}
+
+ if hasattr(self, 'ERROR_PATTERN'):
+ rules['error'] = re.compile(self.ERROR_PATTERN)
+
+ check = self.checkDownload(rules)
+ if check: #@TODO: Move to hoster in 0.4.10
+ errmsg = check.strip().capitalize()
+ if self.lastCheck:
+ errmsg += " | " + self.lastCheck.group(0).strip()
+
+ self.lastDownload = ""
+ self.retry(10, 60, errmsg)
+
+
+ def checkErrors(self):
+ if not self.html:
+ self.logWarning(_("No html code to check"))
+ return
+
+ if hasattr(self, 'PREMIUM_ONLY_PATTERN') and not self.premium and re.search(self.PREMIUM_ONLY_PATTERN, self.html):
+ self.fail(_("Link require a premium account to be handled"))
+
+ elif hasattr(self, 'ERROR_PATTERN'):
+ m = re.search(self.ERROR_PATTERN, self.html)
+ if m:
+ errmsg = self.info['error'] = m.group(1)
+ self.error(errmsg)
+
+ elif hasattr(self, 'WAIT_PATTERN'):
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m:
+ wait_time = sum(int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1}[u.lower()] for v, u in
+ re.findall(r'(\d+)\s*(hr|hour|min|sec)', m.group(0), re.I))
+ self.wait(wait_time, wait_time > 300)
+ return
+
+ self.info.pop('error', None)
+
+
+ def checkStatus(self, getinfo=True):
+ if not self.info or getinfo:
+ self.logDebug("Update file info...")
+ self.logDebug("Previous file info: %s" % self.info)
+ self.info.update(self.getInfo(self.pyfile.url, self.html))
+ self.logDebug("Current file info: %s" % self.info)
+
+ try:
+ status = self.info['status']
+
+ if status is 1:
+ self.offline()
+
+ elif status is 6:
+ self.tempOffline()
+
+ elif status is 8:
+ self.fail()
+
+ finally:
+ self.logDebug("File status: %s" % statusMap[status])
+
+
+ def checkNameSize(self, getinfo=True):
+ if not self.info or getinfo:
+ self.logDebug("Update file info...")
+ self.logDebug("Previous file info: %s" % self.info)
+ self.info.update(self.getInfo(self.pyfile.url, self.html))
+ self.logDebug("Current file info: %s" % self.info)
+
+ try:
+ url = self.info['url'].strip()
+ name = self.info['name'].strip()
+ if name and name != url:
+ self.pyfile.name = name
+
+ except Exception:
+ pass
+
+ try:
+ size = self.info['size']
+ if size > 0:
+ self.pyfile.size = size
+
+ except Exception:
+ pass
+
+ self.logDebug("File name: %s" % self.pyfile.name,
+ "File size: %s byte" % self.pyfile.size if self.pyfile.size > 0 else "File size: Unknown")
+
+
+ def checkInfo(self):
+ self.checkNameSize()
+
+ if self.html:
+ self.checkErrors()
+ self.checkNameSize()
+
+ self.checkStatus(getinfo=False)
+
+
+ #: Deprecated
+ def getFileInfo(self):
+ self.info = {}
+ self.checkInfo()
+ return self.info
+
+
+ def handleDirect(self, pyfile):
+ link = self.directLink(pyfile.url, self.resumeDownload)
+
+ if link:
+ self.logInfo(_("Direct download link detected"))
+
+ self.link = link
+ else:
+ self.logDebug("Direct download link not found")
+
+
+ def handleMulti(self, pyfile): #: Multi-hoster handler
+ pass
+
+
+ def handleFree(self, pyfile):
+ if not hasattr(self, 'LINK_FREE_PATTERN'):
+ self.logError(_("Free download not implemented"))
+
+ m = re.search(self.LINK_FREE_PATTERN, self.html)
+ if m is None:
+ self.error(_("Free download link not found"))
+ else:
+ self.link = m.group(1)
+
+
+ def handlePremium(self, pyfile):
+ if not hasattr(self, 'LINK_PREMIUM_PATTERN'):
+ self.logError(_("Premium download not implemented"))
+ self.logDebug("Handled as free download")
+ self.handleFree(pyfile)
+
+ m = re.search(self.LINK_PREMIUM_PATTERN, self.html)
+ if m is None:
+ self.error(_("Premium download link not found"))
+ else:
+ self.link = m.group(1)
+
+
+ def longWait(self, wait_time=None, max_tries=3):
+ if wait_time and isinstance(wait_time, (int, long, float)):
+ time_str = "%dh %dm" % divmod(wait_time / 60, 60)
+ else:
+ wait_time = 900
+ time_str = _("(unknown time)")
+ max_tries = 100
+
+ self.logInfo(_("Download limit reached, reconnect or wait %s") % time_str)
+
+ self.wait(wait_time, True)
+ self.retry(max_tries=max_tries, reason=_("Download limit reached"))
+
+
+ def parseHtmlForm(self, attr_str="", input_names={}):
+ return parseHtmlForm(attr_str, self.html, input_names)
+
+
+ def checkTrafficLeft(self):
+ if not self.account:
+ return True
+
+ traffic = self.account.getAccountInfo(self.user, True)['trafficleft']
+
+ if traffic is None:
+ return False
+ elif traffic == -1:
+ return True
+ else:
+ size = self.pyfile.size / 1024
+ self.logInfo(_("Filesize: %i KiB, Traffic left for user %s: %i KiB") % (size, self.user, traffic))
+ return size <= traffic
+
+
+ #@TODO: Remove in 0.4.10
+ def wait(self, seconds=0, reconnect=None):
+ return _wait(self, seconds, reconnect)
+
+
+ def error(self, reason="", type="parse"):
+ return _error(self, reason, type)
diff --git a/pyload/plugin/internal/UpdateManager.py b/pyload/plugin/internal/UpdateManager.py
new file mode 100644
index 000000000..ff692b4ae
--- /dev/null
+++ b/pyload/plugin/internal/UpdateManager.py
@@ -0,0 +1,306 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import with_statement
+
+import re
+import sys
+
+from operator import itemgetter
+from os import path, remove, stat
+
+from pyload.network.RequestFactory import getURL
+from pyload.plugin.Addon import Expose, Addon, threaded
+from pyload.utils import safe_join
+
+
+class UpdateManager(Addon):
+ __name__ = "UpdateManager"
+ __type__ = "addon"
+ __version__ = "0.43"
+
+ __config__ = [("activated" , "bool" , "Activated" , True ),
+ ("mode" , "pyLoad + plugins;plugins only", "Check updates for" , "pyLoad + plugins"),
+ ("interval" , "int" , "Check interval in hours" , 8 ),
+ ("autorestart" , "bool" , "Automatically restart pyLoad when required" , True ),
+ ("reloadplugins", "bool" , "Monitor plugins for code changes in debug mode", True ),
+ ("nodebugupdate", "bool" , "Don't check for updates in debug mode" , False )]
+
+ __description__ = """Check for updates"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ # event_list = ["pluginConfigChanged"]
+
+ SERVER_URL = "http://updatemanager.pyload.org"
+ VERSION = re.compile(r'__version__.*=.*("|\')([\d.]+)')
+ MIN_INTERVAL = 3 * 60 * 60 #: 3h minimum check interval (value is in seconds)
+
+
+ def pluginConfigChanged(self, plugin, name, value):
+ if name == "interval":
+ interval = value * 60 * 60
+ if self.MIN_INTERVAL <= interval != self.interval:
+ self.core.scheduler.removeJob(self.cb)
+ self.interval = interval
+ self.initPeriodical()
+ else:
+ self.logDebug("Invalid interval value, kept current")
+
+ elif name == "reloadplugins":
+ if self.cb2:
+ self.core.scheduler.removeJob(self.cb2)
+ if value is True and self.core.debug:
+ self.periodical2()
+
+
+ def activate(self):
+ self.pluginConfigChanged(self.__name__, "interval", self.getConfig("interval"))
+ x = lambda: self.pluginConfigChanged(self.__name__, "reloadplugins", self.getConfig("reloadplugins"))
+ self.core.scheduler.addJob(10, x, threaded=False)
+
+
+ def deactivate(self):
+ self.pluginConfigChanged(self.__name__, "reloadplugins", False)
+
+
+ def setup(self):
+ self.cb2 = None
+ self.interval = 0
+ self.updating = False
+ self.info = {'pyload': False, 'version': None, 'plugins': False}
+ self.mtimes = {} #: store modification time for each plugin
+
+
+ def periodical2(self):
+ if not self.updating:
+ self.autoreloadPlugins()
+
+ self.cb2 = self.core.scheduler.addJob(4, self.periodical2, threaded=False)
+
+
+ @Expose
+ def autoreloadPlugins(self):
+ """ reload and reindex all modified plugins """
+ modules = filter(
+ lambda m: m and (m.__name__.startswith("pyload.plugin.") or
+ m.__name__.startswith("userplugins.")) and
+ m.__name__.count(".") >= 2, sys.modules.itervalues()
+ )
+
+ reloads = []
+
+ for m in modules:
+ root, type, name = m.__name__.rsplit(".", 2)
+ id = (type, name)
+ if type in self.core.pluginManager.plugins:
+ f = m.__file__.replace(".pyc", ".py")
+ if not path.isfile(f):
+ continue
+
+ mtime = stat(f).st_mtime
+
+ if id not in self.mtimes:
+ self.mtimes[id] = mtime
+ elif self.mtimes[id] < mtime:
+ reloads.append(id)
+ self.mtimes[id] = mtime
+
+ return True if self.core.pluginManager.reloadPlugins(reloads) else False
+
+
+ def periodical(self):
+ if self.info['pyload'] or self.getConfig("nodebugupdate") and self.core.debug:
+ return
+
+ self.updateThread()
+
+
+ def server_request(self):
+ try:
+ return getURL(self.SERVER_URL, get={'v': self.core.api.getServerVersion()}).splitlines()
+ except Exception:
+ self.logWarning(_("Unable to contact server to get updates"))
+
+
+ @threaded
+ def updateThread(self):
+ self.updating = True
+
+ status = self.update(onlyplugin=self.getConfig("mode") == "plugins only")
+
+ if status is 2 and self.getConfig("autorestart"):
+ self.core.api.restart()
+ else:
+ self.updating = False
+
+
+ @Expose
+ def updatePlugins(self):
+ """ simple wrapper for calling plugin update quickly """
+ return self.update(onlyplugin=True)
+
+
+ @Expose
+ def update(self, onlyplugin=False):
+ """ check for updates """
+ data = self.server_request()
+
+ if not data:
+ exitcode = 0
+
+ elif data[0] == "None":
+ self.logInfo(_("No new pyLoad version available"))
+ updates = data[1:]
+ exitcode = self._updatePlugins(updates)
+
+ elif onlyplugin:
+ exitcode = 0
+
+ else:
+ newversion = data[0]
+ self.logInfo(_("*** New pyLoad Version %s available ***") % newversion)
+ self.logInfo(_("*** Get it here: https://github.com/pyload/pyload/releases ***"))
+ exitcode = 3
+ self.info['pyload'] = True
+ self.info['version'] = newversion
+
+ return exitcode #: 0 = No plugins updated; 1 = Plugins updated; 2 = Plugins updated, but restart required; 3 = No plugins updated, new pyLoad version available
+
+
+ def _updatePlugins(self, updates):
+ """ check for plugin updates """
+
+ if self.info['plugins']:
+ return False #: plugins were already updated
+
+ exitcode = 0
+ updated = []
+
+ url = updates[0]
+ schema = updates[1].split('|')
+
+ if "BLACKLIST" in updates:
+ blacklist = updates[updates.index('BLACKLIST') + 1:]
+ updates = updates[2:updates.index('BLACKLIST')]
+ else:
+ blacklist = None
+ updates = updates[2:]
+
+ upgradable = [dict(zip(schema, x.split('|'))) for x in updates]
+ blacklisted = [(x.split('|')[0], x.split('|')[1].rsplit('.', 1)[0]) for x in blacklist] if blacklist else []
+
+ if blacklist:
+ # Protect UpdateManager from self-removing
+ try:
+ blacklisted.remove(("internal", "UpdateManager"))
+ except Exception:
+ pass
+
+ for t, n in blacklisted:
+ for idx, plugin in enumerate(upgradable):
+ if n == plugin['name'] and t == plugin['type']:
+ upgradable.pop(idx)
+ break
+
+ for t, n in self.removePlugins(sorted(blacklisted)):
+ self.logInfo(_("Removed blacklisted plugin [%(type)s] %(name)s") % {
+ 'type': t,
+ 'name': n,
+ })
+
+ for plugin in sorted(upgradable, key=itemgetter("type", "name")):
+ filename = plugin['name']
+ type = plugin['type']
+ version = plugin['version']
+
+ if filename.endswith(".pyc"):
+ name = filename[:filename.find("_")]
+ else:
+ name = filename.replace(".py", "")
+
+ plugins = getattr(self.core.pluginManager, "%sPlugins" % type)
+
+ oldver = float(plugins[name]['version']) if name in plugins else None
+ newver = float(version)
+
+ if not oldver:
+ msg = "New plugin: [%(type)s] %(name)s (v%(newver).2f)"
+ elif newver > oldver:
+ msg = "New version of plugin: [%(type)s] %(name)s (v%(oldver).2f -> v%(newver).2f)"
+ else:
+ continue
+
+ self.logInfo(_(msg) % {'type' : type,
+ 'name' : name,
+ 'oldver': oldver,
+ 'newver': newver})
+ try:
+ content = getURL(url % plugin)
+ m = self.VERSION.search(content)
+
+ if m and m.group(2) == version:
+ with open(safe_join("userplugins", prefix, filename), "wb") as f:
+ f.write(content)
+
+ updated.append((prefix, name))
+ else:
+ raise Exception, _("Version mismatch")
+
+ except Exception, e:
+ self.logError(_("Error updating plugin: %s") % filename, str(e))
+
+ if updated:
+ reloaded = self.core.pluginManager.reloadPlugins(updated)
+ if reloaded:
+ self.logInfo(_("Plugins updated and reloaded"))
+ exitcode = 1
+ else:
+ self.logInfo(_("*** Plugins have been updated, but need a pyLoad restart to be reloaded ***"))
+ self.info['plugins'] = True
+ exitcode = 2
+ else:
+ self.logInfo(_("No plugin updates available"))
+
+ return exitcode #: 0 = No plugins updated; 1 = Plugins updated; 2 = Plugins updated, but restart required
+
+
+ @Expose
+ def removePlugins(self, type_plugins):
+ """ delete plugins from disk """
+
+ if not type_plugins:
+ return
+
+ self.logDebug("Requested deletion of plugins: %s" % type_plugins)
+
+ removed = []
+
+ for type, name in type_plugins:
+ err = False
+ file = name + ".py"
+
+ for root in ("userplugins", path.join(pypath, "pyload", "plugins")):
+
+ filename = safe_join(root, type, file)
+ try:
+ remove(filename)
+ except Exception, e:
+ self.logDebug("Error deleting: %s" % path.basename(filename), e)
+ err = True
+
+ filename += "c"
+ if path.isfile(filename):
+ try:
+ if type == "addon":
+ self.manager.deactivateAddon(name)
+ remove(filename)
+ except Exception, e:
+ self.logDebug("Error deleting: %s" % path.basename(filename), e)
+ err = True
+
+ if not err:
+ id = (type, name)
+ removed.append(id)
+
+ return removed #: return a list of the plugins successfully removed
diff --git a/module/plugins/internal/XFSAccount.py b/pyload/plugin/internal/XFSAccount.py
index 2e6b7dc50..2e6b7dc50 100644
--- a/module/plugins/internal/XFSAccount.py
+++ b/pyload/plugin/internal/XFSAccount.py
diff --git a/pyload/plugin/internal/XFSCrypter.py b/pyload/plugin/internal/XFSCrypter.py
new file mode 100644
index 000000000..1a03b69d0
--- /dev/null
+++ b/pyload/plugin/internal/XFSCrypter.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+
+from pyload.plugin.internal.SimpleCrypter import SimpleCrypter
+
+
+class XFSCrypter(SimpleCrypter):
+ __name__ = "XFSCrypter"
+ __type__ = "crypter"
+ __version__ = "0.06"
+
+ __pattern__ = r'^unmatchable$'
+
+ __description__ = """XFileSharing decrypter plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ HOSTER_DOMAIN = None
+
+ URL_REPLACEMENTS = [(r'&?per_page=\d+', ""), (r'[?/&]+$', ""), (r'(.+/[^?]+)$', r'\1?'), (r'$', r'&per_page=10000')]
+
+ LINK_PATTERN = r'<(?:td|TD).*?>\s*<a href="(.+?)".*?>.+?(?:</a>)?\s*</(?:td|TD)>'
+ NAME_PATTERN = r'<[tT]itle>.*?\: (?P<N>.+) folder</[tT]itle>'
+
+ OFFLINE_PATTERN = r'>\s*\w+ (Not Found|file (was|has been) removed)'
+ TEMP_OFFLINE_PATTERN = r'>\s*\w+ server (is in )?(maintenance|maintainance)'
+
+
+ def prepare(self):
+ if not self.HOSTER_DOMAIN:
+ if self.account:
+ account = self.account
+ else:
+ account_name = (self.__name__ + ".py").replace("Folder.py", "").replace(".py", "")
+ account = self.pyfile.m.core.accountManager.getAccountPlugin(account_name)
+
+ if account and hasattr(account, "HOSTER_DOMAIN") and account.HOSTER_DOMAIN:
+ self.HOSTER_DOMAIN = account.HOSTER_DOMAIN
+ else:
+ self.fail(_("Missing HOSTER_DOMAIN"))
+
+ if isinstance(self.COOKIES, list):
+ self.COOKIES.insert((self.HOSTER_DOMAIN, "lang", "english"))
+
+ return super(XFSCrypter, self).prepare()
diff --git a/pyload/plugin/internal/XFSHoster.py b/pyload/plugin/internal/XFSHoster.py
new file mode 100644
index 000000000..b0a5aff0f
--- /dev/null
+++ b/pyload/plugin/internal/XFSHoster.py
@@ -0,0 +1,326 @@
+# -*- coding: utf-8 -*-
+
+import re
+
+from random import random
+from time import sleep
+from urlparse import urljoin, urlparse
+
+from pyload.plugin.internal.captcha import ReCaptcha, SolveMedia
+from pyload.plugin.internal.SimpleHoster import SimpleHoster, secondsToMidnight
+from pyload.utils import html_unescape
+
+
+class XFSHoster(SimpleHoster):
+ __name__ = "XFSHoster"
+ __type__ = "hoster"
+ __version__ = "0.44"
+
+ __pattern__ = r'^unmatchable$'
+
+ __description__ = """XFileSharing hoster plugin"""
+ __license__ = "GPLv3"
+ __authors__ = [("zoidberg", "zoidberg@mujmail.cz"),
+ ("stickell", "l.stickell@yahoo.it"),
+ ("Walter Purcaro", "vuolter@gmail.com")]
+
+
+ HOSTER_DOMAIN = None
+
+ TEXT_ENCODING = False
+ DIRECT_LINK = None
+ MULTI_HOSTER = True #@NOTE: Should be default to False for safe, but I'm lazy...
+
+ NAME_PATTERN = r'(Filename[ ]*:[ ]*</b>(</td><td nowrap>)?|name="fname"[ ]+value="|<[\w^_]+ class="(file)?name">)\s*(?P<N>.+?)(\s*<|")'
+ SIZE_PATTERN = r'(Size[ ]*:[ ]*</b>(</td><td>)?|File:.*>|</font>\s*\(|<[\w^_]+ class="size">)\s*(?P<S>[\d.,]+)\s*(?P<U>[\w^_]+)'
+
+ OFFLINE_PATTERN = r'>\s*\w+ (Not Found|file (was|has been) removed)'
+ TEMP_OFFLINE_PATTERN = r'>\s*\w+ server (is in )?(maintenance|maintainance)'
+
+ WAIT_PATTERN = r'<span id="countdown_str">.*?>(\d+)</span>|id="countdown" value=".*?(\d+).*?"'
+ PREMIUM_ONLY_PATTERN = r'>This file is available for Premium Users only'
+ ERROR_PATTERN = r'(?:class=["\']err["\'].*?>|<[Cc]enter><b>|>Error</td>|>\(ERROR:)(?:\s*<.+?>\s*)*(.+?)(?:["\']|<|\))'
+
+ LINK_LEECH_PATTERN = r'<h2>Download Link</h2>\s*<textarea[^>]*>([^<]+)'
+ LINK_PATTERN = None #: final download url pattern
+
+ CAPTCHA_PATTERN = r'(https?://[^"\']+?/captchas?/[^"\']+)'
+ CAPTCHA_BLOCK_PATTERN = r'>Enter code.*?<div.*?>(.+?)</div>'
+ RECAPTCHA_PATTERN = None
+ SOLVEMEDIA_PATTERN = None
+
+ FORM_PATTERN = None
+ FORM_INPUTS_MAP = None #: dict passed as input_names to parseHtmlForm
+
+
+ def setup(self):
+ self.chunkLimit = -1 if self.premium else 1
+ self.resumeDownload = self.multiDL = self.premium
+
+
+ def prepare(self):
+ """ Initialize important variables """
+ if not self.HOSTER_DOMAIN:
+ if self.account:
+ account = self.account
+ else:
+ account = self.pyfile.m.core.accountManager.getAccountPlugin(self.__name__)
+
+ if account and hasattr(account, "HOSTER_DOMAIN") and account.HOSTER_DOMAIN:
+ self.HOSTER_DOMAIN = account.HOSTER_DOMAIN
+ else:
+ self.fail(_("Missing HOSTER_DOMAIN"))
+
+ if isinstance(self.COOKIES, list):
+ self.COOKIES.insert((self.HOSTER_DOMAIN, "lang", "english"))
+
+ if not self.LINK_PATTERN:
+ pattern = r'(https?://(?:www\.)?([^/]*?%s|\d+\.\d+\.\d+\.\d+)(\:\d+)?(/d/|(/files)?/\d+/\w+/).+?)["\'<]'
+ self.LINK_PATTERN = pattern % self.HOSTER_DOMAIN.replace('.', '\.')
+
+ self.captcha = None
+ self.errmsg = None
+
+ super(XFSHoster, self).prepare()
+
+ if self.DIRECT_LINK is None:
+ self.directDL = self.premium
+
+
+ def handleFree(self, pyfile):
+ for i in xrange(1, 6):
+ self.logDebug("Getting download link: #%d" % i)
+
+ self.checkErrors()
+
+ m = re.search(self.LINK_PATTERN, self.html, re.S)
+ if m:
+ break
+
+ data = self.getPostParameters()
+
+ self.html = self.load(self.pyfile.url, post=data, ref=True, decode=True, follow_location=False)
+
+ m = re.search(r'Location\s*:\s*(.+)', self.req.http.header, re.I)
+ if m and not "op=" in m.group(1):
+ break
+
+ m = re.search(self.LINK_PATTERN, self.html, re.S)
+ if m:
+ break
+ else:
+ self.logError(data['op'] if 'op' in data else _("UNKNOWN"))
+ return ""
+
+ self.link = m.group(1).strip() #@TODO: Remove .strip() in 0.4.10
+
+
+ def handlePremium(self, pyfile):
+ return self.handleFree(pyfile)
+
+
+ def handleMulti(self, pyfile):
+ if not self.account:
+ self.fail(_("Only registered or premium users can use url leech feature"))
+
+ #only tested with easybytez.com
+ self.html = self.load("http://www.%s/" % self.HOSTER_DOMAIN)
+
+ action, inputs = self.parseHtmlForm()
+
+ upload_id = "%012d" % int(random() * 10 ** 12)
+ action += upload_id + "&js_on=1&utype=prem&upload_type=url"
+
+ inputs['tos'] = '1'
+ inputs['url_mass'] = pyfile.url
+ inputs['up1oad_type'] = 'url'
+
+ self.logDebug(action, inputs)
+
+ self.req.setOption("timeout", 600) #: wait for file to upload to easybytez.com
+
+ self.html = self.load(action, post=inputs)
+
+ self.checkErrors()
+
+ action, inputs = self.parseHtmlForm('F1')
+ if not inputs:
+ if self.errmsg:
+ self.retry(reason=self.errmsg)
+ else:
+ self.error(_("TEXTAREA F1 not found"))
+
+ self.logDebug(inputs)
+
+ stmsg = inputs['st']
+
+ if stmsg == 'OK':
+ self.html = self.load(action, post=inputs)
+
+ elif 'Can not leech file' in stmsg:
+ self.retry(20, 3 * 60, _("Can not leech file"))
+
+ elif 'today' in stmsg:
+ self.retry(wait_time=secondsToMidnight(gmt=2), reason=_("You've used all Leech traffic today"))
+
+ else:
+ self.fail(stmsg)
+
+ #get easybytez.com link for uploaded file
+ m = re.search(self.LINK_LEECH_PATTERN, self.html)
+ if m is None:
+ self.error(_("LINK_LEECH_PATTERN not found"))
+
+ header = self.load(m.group(1), just_header=True, decode=True)
+
+ if 'location' in header: #: Direct download link
+ self.link = header['location']
+
+
+ def checkErrors(self):
+ m = re.search(self.ERROR_PATTERN, self.html)
+ if m is None:
+ self.errmsg = None
+ else:
+ self.errmsg = m.group(1).strip()
+
+ self.logWarning(re.sub(r"<.*?>", " ", self.errmsg))
+
+ if 'wait' in self.errmsg:
+ wait_time = sum(int(v) * {"hr": 3600, "hour": 3600, "min": 60, "sec": 1}[u.lower()] for v, u in
+ re.findall(r'(\d+)\s*(hr|hour|min|sec)', self.errmsg, re.I))
+ self.wait(wait_time, True)
+
+ elif 'country' in self.errmsg:
+ self.fail(_("Downloads are disabled for your country"))
+
+ elif 'captcha' in self.errmsg:
+ self.invalidCaptcha()
+
+ elif 'premium' in self.errmsg and 'require' in self.errmsg:
+ self.fail(_("File can be downloaded by premium users only"))
+
+ elif 'limit' in self.errmsg:
+ if 'days' in self.errmsg:
+ delay = secondsToMidnight(gmt=2)
+ retries = 3
+ else:
+ delay = 1 * 60 * 60
+ retries = 24
+
+ self.wantReconnect = True
+ self.retry(retries, delay, _("Download limit exceeded"))
+
+ elif 'countdown' in self.errmsg or 'Expired' in self.errmsg:
+ self.retry(reason=_("Link expired"))
+
+ elif 'maintenance' in self.errmsg or 'maintainance' in self.errmsg:
+ self.tempOffline()
+
+ elif 'up to' in self.errmsg:
+ self.fail(_("File too large for free download"))
+
+ else:
+ self.wantReconnect = True
+ self.retry(wait_time=60, reason=self.errmsg)
+
+ if self.errmsg:
+ self.info['error'] = self.errmsg
+ else:
+ self.info.pop('error', None)
+
+
+ def getPostParameters(self):
+ if self.FORM_PATTERN or self.FORM_INPUTS_MAP:
+ action, inputs = self.parseHtmlForm(self.FORM_PATTERN or "", self.FORM_INPUTS_MAP or {})
+ else:
+ action, inputs = self.parseHtmlForm(input_names={'op': re.compile(r'^download')})
+
+ if not inputs:
+ action, inputs = self.parseHtmlForm('F1')
+ if not inputs:
+ if self.errmsg:
+ self.retry(reason=self.errmsg)
+ else:
+ self.error(_("TEXTAREA F1 not found"))
+
+ self.logDebug(inputs)
+
+ if 'op' in inputs:
+ if "password" in inputs:
+ password = self.getPassword()
+ if password:
+ inputs['password'] = password
+ else:
+ self.fail(_("Missing password"))
+
+ if not self.premium:
+ m = re.search(self.WAIT_PATTERN, self.html)
+ if m:
+ wait_time = int(m.group(1))
+ self.setWait(wait_time, False)
+
+ self.captcha = self.handleCaptcha(inputs)
+
+ self.wait()
+ else:
+ inputs['referer'] = self.pyfile.url
+
+ if self.premium:
+ inputs['method_premium'] = "Premium Download"
+ inputs.pop('method_free', None)
+ else:
+ inputs['method_free'] = "Free Download"
+ inputs.pop('method_premium', None)
+
+ return inputs
+
+
+ def handleCaptcha(self, inputs):
+ m = re.search(self.CAPTCHA_PATTERN, self.html)
+ if m:
+ captcha_url = m.group(1)
+ inputs['code'] = self.decryptCaptcha(captcha_url)
+ return 1
+
+ m = re.search(self.CAPTCHA_BLOCK_PATTERN, self.html, re.S)
+ if m:
+ captcha_div = m.group(1)
+ numerals = re.findall(r'<span.*?padding-left\s*:\s*(\d+).*?>(\d)</span>', html_unescape(captcha_div))
+
+ self.logDebug(captcha_div)
+
+ inputs['code'] = "".join(a[1] for a in sorted(numerals, key=lambda num: int(num[0])))
+
+ self.logDebug("Captcha code: %s" % inputs['code'], numerals)
+ return 2
+
+ recaptcha = ReCaptcha(self)
+ try:
+ captcha_key = re.search(self.RECAPTCHA_PATTERN, self.html).group(1)
+
+ except Exception:
+ captcha_key = recaptcha.detect_key()
+
+ else:
+ self.logDebug("ReCaptcha key: %s" % captcha_key)
+
+ if captcha_key:
+ inputs['recaptcha_response_field'], inputs['recaptcha_challenge_field'] = recaptcha.challenge(captcha_key)
+ return 3
+
+ solvemedia = SolveMedia(self)
+ try:
+ captcha_key = re.search(self.SOLVEMEDIA_PATTERN, self.html).group(1)
+
+ except Exception:
+ captcha_key = solvemedia.detect_key()
+
+ else:
+ self.logDebug("SolveMedia key: %s" % captcha_key)
+
+ if captcha_key:
+ inputs['adcopy_response'], inputs['adcopy_challenge'] = solvemedia.challenge(captcha_key)
+ return 4
+
+ return 0
diff --git a/module/plugins/ocr/__init__.py b/pyload/plugin/internal/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/plugins/ocr/__init__.py
+++ b/pyload/plugin/internal/__init__.py
diff --git a/module/plugins/ocr/GigasizeCom.py b/pyload/plugin/ocr/GigasizeCom.py
index 6982e6ca9..6982e6ca9 100644
--- a/module/plugins/ocr/GigasizeCom.py
+++ b/pyload/plugin/ocr/GigasizeCom.py
diff --git a/module/plugins/ocr/LinksaveIn.py b/pyload/plugin/ocr/LinksaveIn.py
index 7ced74f4b..7ced74f4b 100644
--- a/module/plugins/ocr/LinksaveIn.py
+++ b/pyload/plugin/ocr/LinksaveIn.py
diff --git a/module/plugins/ocr/NetloadIn.py b/pyload/plugin/ocr/NetloadIn.py
index 8939b5318..8939b5318 100644
--- a/module/plugins/ocr/NetloadIn.py
+++ b/pyload/plugin/ocr/NetloadIn.py
diff --git a/module/plugins/ocr/ShareonlineBiz.py b/pyload/plugin/ocr/ShareonlineBiz.py
index bbc3d1762..bbc3d1762 100644
--- a/module/plugins/ocr/ShareonlineBiz.py
+++ b/pyload/plugin/ocr/ShareonlineBiz.py
diff --git a/module/remote/socketbackend/__init__.py b/pyload/plugin/ocr/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/remote/socketbackend/__init__.py
+++ b/pyload/plugin/ocr/__init__.py
diff --git a/module/remote/ClickAndLoadBackend.py b/pyload/remote/ClickAndLoadBackend.py
index a73ea7f24..a73ea7f24 100644
--- a/module/remote/ClickAndLoadBackend.py
+++ b/pyload/remote/ClickAndLoadBackend.py
diff --git a/module/remote/SocketBackend.py b/pyload/remote/SocketBackend.py
index a1c885347..a1c885347 100644
--- a/module/remote/SocketBackend.py
+++ b/pyload/remote/SocketBackend.py
diff --git a/module/remote/ThriftBackend.py b/pyload/remote/ThriftBackend.py
index 16917cfc9..16917cfc9 100644
--- a/module/remote/ThriftBackend.py
+++ b/pyload/remote/ThriftBackend.py
diff --git a/module/remote/__init__.py b/pyload/remote/__init__.py
index 60dfa77c7..60dfa77c7 100644
--- a/module/remote/__init__.py
+++ b/pyload/remote/__init__.py
diff --git a/module/remote/thriftbackend/__init__.py b/pyload/remote/socketbackend/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/remote/thriftbackend/__init__.py
+++ b/pyload/remote/socketbackend/__init__.py
diff --git a/module/remote/socketbackend/create_ttypes.py b/pyload/remote/socketbackend/create_ttypes.py
index 5bfbcafa0..5bfbcafa0 100644
--- a/module/remote/socketbackend/create_ttypes.py
+++ b/pyload/remote/socketbackend/create_ttypes.py
diff --git a/module/remote/thriftbackend/Processor.py b/pyload/remote/thriftbackend/Processor.py
index 683697d1c..683697d1c 100644
--- a/module/remote/thriftbackend/Processor.py
+++ b/pyload/remote/thriftbackend/Processor.py
diff --git a/module/remote/thriftbackend/Protocol.py b/pyload/remote/thriftbackend/Protocol.py
index 417b45834..417b45834 100644
--- a/module/remote/thriftbackend/Protocol.py
+++ b/pyload/remote/thriftbackend/Protocol.py
diff --git a/module/remote/thriftbackend/Socket.py b/pyload/remote/thriftbackend/Socket.py
index f6edc8408..f6edc8408 100644
--- a/module/remote/thriftbackend/Socket.py
+++ b/pyload/remote/thriftbackend/Socket.py
diff --git a/module/remote/thriftbackend/ThriftClient.py b/pyload/remote/thriftbackend/ThriftClient.py
index 7c2a1cb01..7c2a1cb01 100644
--- a/module/remote/thriftbackend/ThriftClient.py
+++ b/pyload/remote/thriftbackend/ThriftClient.py
diff --git a/module/remote/thriftbackend/ThriftTest.py b/pyload/remote/thriftbackend/ThriftTest.py
index c9c0d3cf3..c9c0d3cf3 100644
--- a/module/remote/thriftbackend/ThriftTest.py
+++ b/pyload/remote/thriftbackend/ThriftTest.py
diff --git a/module/remote/thriftbackend/Transport.py b/pyload/remote/thriftbackend/Transport.py
index 7db4ba9d7..7db4ba9d7 100644
--- a/module/remote/thriftbackend/Transport.py
+++ b/pyload/remote/thriftbackend/Transport.py
diff --git a/module/remote/thriftbackend/thriftgen/__init__.py b/pyload/remote/thriftbackend/__init__.py
index 40a96afc6..40a96afc6 100644
--- a/module/remote/thriftbackend/thriftgen/__init__.py
+++ b/pyload/remote/thriftbackend/__init__.py
diff --git a/module/remote/thriftbackend/pyload.thrift b/pyload/remote/thriftbackend/pyload.thrift
index 3aef7af00..3aef7af00 100644
--- a/module/remote/thriftbackend/pyload.thrift
+++ b/pyload/remote/thriftbackend/pyload.thrift
diff --git a/pyload/remote/thriftbackend/thriftgen/__init__.py b/pyload/remote/thriftbackend/thriftgen/__init__.py
new file mode 100644
index 000000000..40a96afc6
--- /dev/null
+++ b/pyload/remote/thriftbackend/thriftgen/__init__.py
@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-
diff --git a/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote b/pyload/remote/thriftbackend/thriftgen/pyload/Pyload-remote
index ddc1dd451..ddc1dd451 100644
--- a/module/remote/thriftbackend/thriftgen/pyload/Pyload-remote
+++ b/pyload/remote/thriftbackend/thriftgen/pyload/Pyload-remote
diff --git a/module/remote/thriftbackend/thriftgen/pyload/Pyload.py b/pyload/remote/thriftbackend/thriftgen/pyload/Pyload.py
index e8d2cf9af..e8d2cf9af 100644
--- a/module/remote/thriftbackend/thriftgen/pyload/Pyload.py
+++ b/pyload/remote/thriftbackend/thriftgen/pyload/Pyload.py
diff --git a/module/remote/thriftbackend/thriftgen/pyload/__init__.py b/pyload/remote/thriftbackend/thriftgen/pyload/__init__.py
index 9a0fb88bf..9a0fb88bf 100644
--- a/module/remote/thriftbackend/thriftgen/pyload/__init__.py
+++ b/pyload/remote/thriftbackend/thriftgen/pyload/__init__.py
diff --git a/module/remote/thriftbackend/thriftgen/pyload/constants.py b/pyload/remote/thriftbackend/thriftgen/pyload/constants.py
index 3bdd64cc1..3bdd64cc1 100644
--- a/module/remote/thriftbackend/thriftgen/pyload/constants.py
+++ b/pyload/remote/thriftbackend/thriftgen/pyload/constants.py
diff --git a/module/remote/thriftbackend/thriftgen/pyload/ttypes.py b/pyload/remote/thriftbackend/thriftgen/pyload/ttypes.py
index 67d23161d..67d23161d 100644
--- a/module/remote/thriftbackend/thriftgen/pyload/ttypes.py
+++ b/pyload/remote/thriftbackend/thriftgen/pyload/ttypes.py
diff --git a/module/utils/__init__.py b/pyload/utils/__init__.py
index 330ee622c..330ee622c 100644
--- a/module/utils/__init__.py
+++ b/pyload/utils/__init__.py
diff --git a/module/utils/packagetools.py b/pyload/utils/packagetools.py
index 9dbde9b50..9dbde9b50 100644
--- a/module/utils/packagetools.py
+++ b/pyload/utils/packagetools.py
diff --git a/module/utils/printer.py b/pyload/utils/printer.py
index 5d333e238..5d333e238 100644
--- a/module/utils/printer.py
+++ b/pyload/utils/printer.py
diff --git a/module/utils/pylgettext.py b/pyload/utils/pylgettext.py
index cab631cf4..cab631cf4 100644
--- a/module/utils/pylgettext.py
+++ b/pyload/utils/pylgettext.py
diff --git a/module/webui/__init__.py b/pyload/webui/__init__.py
index 0d2f1ca36..0d2f1ca36 100644
--- a/module/webui/__init__.py
+++ b/pyload/webui/__init__.py
diff --git a/module/webui/app/__init__.py b/pyload/webui/app/__init__.py
index 39d0fadd5..39d0fadd5 100644
--- a/module/webui/app/__init__.py
+++ b/pyload/webui/app/__init__.py
diff --git a/module/webui/app/api.py b/pyload/webui/app/api.py
index 1ee4b1608..1ee4b1608 100644
--- a/module/webui/app/api.py
+++ b/pyload/webui/app/api.py
diff --git a/module/webui/app/cnl.py b/pyload/webui/app/cnl.py
index e00e47f66..e00e47f66 100644
--- a/module/webui/app/cnl.py
+++ b/pyload/webui/app/cnl.py
diff --git a/module/webui/app/json.py b/pyload/webui/app/json.py
index c347c25e3..c347c25e3 100644
--- a/module/webui/app/json.py
+++ b/pyload/webui/app/json.py
diff --git a/module/webui/app/pyload.py b/pyload/webui/app/pyload.py
index 2d1a8eb86..2d1a8eb86 100644
--- a/module/webui/app/pyload.py
+++ b/pyload/webui/app/pyload.py
diff --git a/module/webui/app/utils.py b/pyload/webui/app/utils.py
index fd0e14cfa..fd0e14cfa 100644
--- a/module/webui/app/utils.py
+++ b/pyload/webui/app/utils.py
diff --git a/module/webui/filters.py b/pyload/webui/filters.py
index 527b18446..527b18446 100644
--- a/module/webui/filters.py
+++ b/pyload/webui/filters.py
diff --git a/module/webui/middlewares.py b/pyload/webui/middlewares.py
index 5f56f81ee..5f56f81ee 100644
--- a/module/webui/middlewares.py
+++ b/pyload/webui/middlewares.py
diff --git a/module/webui/servers/lighttpd_default.conf b/pyload/webui/servers/lighttpd_default.conf
index aa199b3f3..aa199b3f3 100644
--- a/module/webui/servers/lighttpd_default.conf
+++ b/pyload/webui/servers/lighttpd_default.conf
diff --git a/module/webui/servers/nginx_default.conf b/pyload/webui/servers/nginx_default.conf
index c1cfcafca..c1cfcafca 100644
--- a/module/webui/servers/nginx_default.conf
+++ b/pyload/webui/servers/nginx_default.conf
diff --git a/module/webui/themes/Dark/css/MooDialog.css b/pyload/webui/themes/Dark/css/MooDialog.css
index 1714e170f..1714e170f 100644
--- a/module/webui/themes/Dark/css/MooDialog.css
+++ b/pyload/webui/themes/Dark/css/MooDialog.css
diff --git a/module/webui/themes/Dark/css/base.css b/pyload/webui/themes/Dark/css/base.css
index f0bae8f24..f0bae8f24 100644
--- a/module/webui/themes/Dark/css/base.css
+++ b/pyload/webui/themes/Dark/css/base.css
diff --git a/module/webui/themes/Dark/css/log.css b/pyload/webui/themes/Dark/css/log.css
index 3362e9381..3362e9381 100644
--- a/module/webui/themes/Dark/css/log.css
+++ b/pyload/webui/themes/Dark/css/log.css
diff --git a/module/webui/themes/Dark/css/pathchooser.css b/pyload/webui/themes/Dark/css/pathchooser.css
index 204812aa1..204812aa1 100644
--- a/module/webui/themes/Dark/css/pathchooser.css
+++ b/pyload/webui/themes/Dark/css/pathchooser.css
diff --git a/module/webui/themes/Dark/css/window.css b/pyload/webui/themes/Dark/css/window.css
index 1bcc58e6c..1bcc58e6c 100644
--- a/module/webui/themes/Dark/css/window.css
+++ b/pyload/webui/themes/Dark/css/window.css
diff --git a/module/webui/themes/Dark/img/MooDialog/dialog-close.png b/pyload/webui/themes/Dark/img/MooDialog/dialog-close.png
index 81ebb88b2..81ebb88b2 100644
--- a/module/webui/themes/Dark/img/MooDialog/dialog-close.png
+++ b/pyload/webui/themes/Dark/img/MooDialog/dialog-close.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/MooDialog/dialog-error.png b/pyload/webui/themes/Dark/img/MooDialog/dialog-error.png
index d70328403..d70328403 100644
--- a/module/webui/themes/Dark/img/MooDialog/dialog-error.png
+++ b/pyload/webui/themes/Dark/img/MooDialog/dialog-error.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/MooDialog/dialog-question.png b/pyload/webui/themes/Dark/img/MooDialog/dialog-question.png
index b0af3db5b..b0af3db5b 100644
--- a/module/webui/themes/Dark/img/MooDialog/dialog-question.png
+++ b/pyload/webui/themes/Dark/img/MooDialog/dialog-question.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/MooDialog/dialog-warning.png b/pyload/webui/themes/Dark/img/MooDialog/dialog-warning.png
index aad64d4be..aad64d4be 100644
--- a/module/webui/themes/Dark/img/MooDialog/dialog-warning.png
+++ b/pyload/webui/themes/Dark/img/MooDialog/dialog-warning.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/button.png b/pyload/webui/themes/Dark/img/button.png
index bb408a7d6..bb408a7d6 100644
--- a/module/webui/themes/Dark/img/button.png
+++ b/pyload/webui/themes/Dark/img/button.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/dark-bg.jpg b/pyload/webui/themes/Dark/img/dark-bg.jpg
index 637fa6b93..637fa6b93 100644
--- a/module/webui/themes/Dark/img/dark-bg.jpg
+++ b/pyload/webui/themes/Dark/img/dark-bg.jpg
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/add_folder.png b/pyload/webui/themes/Dark/img/default/add_folder.png
index 8acbc411b..8acbc411b 100644
--- a/module/webui/themes/Dark/img/default/add_folder.png
+++ b/pyload/webui/themes/Dark/img/default/add_folder.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/ajax-loader.gif b/pyload/webui/themes/Dark/img/default/ajax-loader.gif
index 2fd8e0737..2fd8e0737 100644
--- a/module/webui/themes/Dark/img/default/ajax-loader.gif
+++ b/pyload/webui/themes/Dark/img/default/ajax-loader.gif
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/arrow_refresh.png b/pyload/webui/themes/Dark/img/default/arrow_refresh.png
index 0de26566d..0de26566d 100644
--- a/module/webui/themes/Dark/img/default/arrow_refresh.png
+++ b/pyload/webui/themes/Dark/img/default/arrow_refresh.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/arrow_right.png b/pyload/webui/themes/Dark/img/default/arrow_right.png
index b1a181923..b1a181923 100644
--- a/module/webui/themes/Dark/img/default/arrow_right.png
+++ b/pyload/webui/themes/Dark/img/default/arrow_right.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/big_button.gif b/pyload/webui/themes/Dark/img/default/big_button.gif
index 7680490ea..7680490ea 100644
--- a/module/webui/themes/Dark/img/default/big_button.gif
+++ b/pyload/webui/themes/Dark/img/default/big_button.gif
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/big_button_over.gif b/pyload/webui/themes/Dark/img/default/big_button_over.gif
index 2e3ee10d2..2e3ee10d2 100644
--- a/module/webui/themes/Dark/img/default/big_button_over.gif
+++ b/pyload/webui/themes/Dark/img/default/big_button_over.gif
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/body.png b/pyload/webui/themes/Dark/img/default/body.png
index 7ff1043e0..7ff1043e0 100644
--- a/module/webui/themes/Dark/img/default/body.png
+++ b/pyload/webui/themes/Dark/img/default/body.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/closebtn.gif b/pyload/webui/themes/Dark/img/default/closebtn.gif
index 3e27e6030..3e27e6030 100644
--- a/module/webui/themes/Dark/img/default/closebtn.gif
+++ b/pyload/webui/themes/Dark/img/default/closebtn.gif
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/cog.png b/pyload/webui/themes/Dark/img/default/cog.png
index 67de2c6cc..67de2c6cc 100644
--- a/module/webui/themes/Dark/img/default/cog.png
+++ b/pyload/webui/themes/Dark/img/default/cog.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/control_add.png b/pyload/webui/themes/Dark/img/default/control_add.png
index d39886893..d39886893 100644
--- a/module/webui/themes/Dark/img/default/control_add.png
+++ b/pyload/webui/themes/Dark/img/default/control_add.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/control_add_blue.png b/pyload/webui/themes/Dark/img/default/control_add_blue.png
index d11b7f41d..d11b7f41d 100644
--- a/module/webui/themes/Dark/img/default/control_add_blue.png
+++ b/pyload/webui/themes/Dark/img/default/control_add_blue.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/control_cancel.png b/pyload/webui/themes/Dark/img/default/control_cancel.png
index 7b9bc3fba..7b9bc3fba 100644
--- a/module/webui/themes/Dark/img/default/control_cancel.png
+++ b/pyload/webui/themes/Dark/img/default/control_cancel.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/control_cancel_blue.png b/pyload/webui/themes/Dark/img/default/control_cancel_blue.png
index 0c5c96ce3..0c5c96ce3 100644
--- a/module/webui/themes/Dark/img/default/control_cancel_blue.png
+++ b/pyload/webui/themes/Dark/img/default/control_cancel_blue.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/control_pause.png b/pyload/webui/themes/Dark/img/default/control_pause.png
index 2d9ce9c4e..2d9ce9c4e 100644
--- a/module/webui/themes/Dark/img/default/control_pause.png
+++ b/pyload/webui/themes/Dark/img/default/control_pause.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/control_pause_blue.png b/pyload/webui/themes/Dark/img/default/control_pause_blue.png
index ec61099b0..ec61099b0 100644
--- a/module/webui/themes/Dark/img/default/control_pause_blue.png
+++ b/pyload/webui/themes/Dark/img/default/control_pause_blue.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/control_play.png b/pyload/webui/themes/Dark/img/default/control_play.png
index 0846555d0..0846555d0 100644
--- a/module/webui/themes/Dark/img/default/control_play.png
+++ b/pyload/webui/themes/Dark/img/default/control_play.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/control_play_blue.png b/pyload/webui/themes/Dark/img/default/control_play_blue.png
index f8c8ec683..f8c8ec683 100644
--- a/module/webui/themes/Dark/img/default/control_play_blue.png
+++ b/pyload/webui/themes/Dark/img/default/control_play_blue.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/control_stop.png b/pyload/webui/themes/Dark/img/default/control_stop.png
index 893bb60e5..893bb60e5 100644
--- a/module/webui/themes/Dark/img/default/control_stop.png
+++ b/pyload/webui/themes/Dark/img/default/control_stop.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/control_stop_blue.png b/pyload/webui/themes/Dark/img/default/control_stop_blue.png
index e6f75d232..e6f75d232 100644
--- a/module/webui/themes/Dark/img/default/control_stop_blue.png
+++ b/pyload/webui/themes/Dark/img/default/control_stop_blue.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/delete.png b/pyload/webui/themes/Dark/img/default/delete.png
index 08f249365..08f249365 100644
--- a/module/webui/themes/Dark/img/default/delete.png
+++ b/pyload/webui/themes/Dark/img/default/delete.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/drag_corner.gif b/pyload/webui/themes/Dark/img/default/drag_corner.gif
index befb1adf1..befb1adf1 100644
--- a/module/webui/themes/Dark/img/default/drag_corner.gif
+++ b/pyload/webui/themes/Dark/img/default/drag_corner.gif
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/error.png b/pyload/webui/themes/Dark/img/default/error.png
index c37bd062e..c37bd062e 100644
--- a/module/webui/themes/Dark/img/default/error.png
+++ b/pyload/webui/themes/Dark/img/default/error.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/folder.png b/pyload/webui/themes/Dark/img/default/folder.png
index 784e8fa48..784e8fa48 100644
--- a/module/webui/themes/Dark/img/default/folder.png
+++ b/pyload/webui/themes/Dark/img/default/folder.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/full.png b/pyload/webui/themes/Dark/img/default/full.png
index fea52af76..fea52af76 100644
--- a/module/webui/themes/Dark/img/default/full.png
+++ b/pyload/webui/themes/Dark/img/default/full.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/head-login.png b/pyload/webui/themes/Dark/img/default/head-login.png
index b59b7cbbf..b59b7cbbf 100644
--- a/module/webui/themes/Dark/img/default/head-login.png
+++ b/pyload/webui/themes/Dark/img/default/head-login.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/head-menu-collector.png b/pyload/webui/themes/Dark/img/default/head-menu-collector.png
index 861be40bc..861be40bc 100644
--- a/module/webui/themes/Dark/img/default/head-menu-collector.png
+++ b/pyload/webui/themes/Dark/img/default/head-menu-collector.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/head-menu-config.png b/pyload/webui/themes/Dark/img/default/head-menu-config.png
index bbf43d4f3..bbf43d4f3 100644
--- a/module/webui/themes/Dark/img/default/head-menu-config.png
+++ b/pyload/webui/themes/Dark/img/default/head-menu-config.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/head-menu-development.png b/pyload/webui/themes/Dark/img/default/head-menu-development.png
index fad150fe1..fad150fe1 100644
--- a/module/webui/themes/Dark/img/default/head-menu-development.png
+++ b/pyload/webui/themes/Dark/img/default/head-menu-development.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/head-menu-download.png b/pyload/webui/themes/Dark/img/default/head-menu-download.png
index 98c5da9db..98c5da9db 100644
--- a/module/webui/themes/Dark/img/default/head-menu-download.png
+++ b/pyload/webui/themes/Dark/img/default/head-menu-download.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/head-menu-home.png b/pyload/webui/themes/Dark/img/default/head-menu-home.png
index 9d62109aa..9d62109aa 100644
--- a/module/webui/themes/Dark/img/default/head-menu-home.png
+++ b/pyload/webui/themes/Dark/img/default/head-menu-home.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/head-menu-index.png b/pyload/webui/themes/Dark/img/default/head-menu-index.png
index 44d631064..44d631064 100644
--- a/module/webui/themes/Dark/img/default/head-menu-index.png
+++ b/pyload/webui/themes/Dark/img/default/head-menu-index.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/head-menu-news.png b/pyload/webui/themes/Dark/img/default/head-menu-news.png
index 43950ebc9..43950ebc9 100644
--- a/module/webui/themes/Dark/img/default/head-menu-news.png
+++ b/pyload/webui/themes/Dark/img/default/head-menu-news.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/head-menu-queue.png b/pyload/webui/themes/Dark/img/default/head-menu-queue.png
index be98793ce..be98793ce 100644
--- a/module/webui/themes/Dark/img/default/head-menu-queue.png
+++ b/pyload/webui/themes/Dark/img/default/head-menu-queue.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/head-menu-recent.png b/pyload/webui/themes/Dark/img/default/head-menu-recent.png
index fc9b0497f..fc9b0497f 100644
--- a/module/webui/themes/Dark/img/default/head-menu-recent.png
+++ b/pyload/webui/themes/Dark/img/default/head-menu-recent.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/head-menu-wiki.png b/pyload/webui/themes/Dark/img/default/head-menu-wiki.png
index 07cf0102d..07cf0102d 100644
--- a/module/webui/themes/Dark/img/default/head-menu-wiki.png
+++ b/pyload/webui/themes/Dark/img/default/head-menu-wiki.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/head-search-noshadow.png b/pyload/webui/themes/Dark/img/default/head-search-noshadow.png
index aafdae015..aafdae015 100644
--- a/module/webui/themes/Dark/img/default/head-search-noshadow.png
+++ b/pyload/webui/themes/Dark/img/default/head-search-noshadow.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/head_bg1.png b/pyload/webui/themes/Dark/img/default/head_bg1.png
index f2848c3cc..f2848c3cc 100644
--- a/module/webui/themes/Dark/img/default/head_bg1.png
+++ b/pyload/webui/themes/Dark/img/default/head_bg1.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/images.png b/pyload/webui/themes/Dark/img/default/images.png
index 184860d1e..184860d1e 100644
--- a/module/webui/themes/Dark/img/default/images.png
+++ b/pyload/webui/themes/Dark/img/default/images.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/notice.png b/pyload/webui/themes/Dark/img/default/notice.png
index 12cd1aef9..12cd1aef9 100644
--- a/module/webui/themes/Dark/img/default/notice.png
+++ b/pyload/webui/themes/Dark/img/default/notice.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/package_go.png b/pyload/webui/themes/Dark/img/default/package_go.png
index aace63ad6..aace63ad6 100644
--- a/module/webui/themes/Dark/img/default/package_go.png
+++ b/pyload/webui/themes/Dark/img/default/package_go.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/page-tools-backlinks.png b/pyload/webui/themes/Dark/img/default/page-tools-backlinks.png
index 3eb6a9ce3..3eb6a9ce3 100644
--- a/module/webui/themes/Dark/img/default/page-tools-backlinks.png
+++ b/pyload/webui/themes/Dark/img/default/page-tools-backlinks.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/page-tools-edit.png b/pyload/webui/themes/Dark/img/default/page-tools-edit.png
index 188e1c12b..188e1c12b 100644
--- a/module/webui/themes/Dark/img/default/page-tools-edit.png
+++ b/pyload/webui/themes/Dark/img/default/page-tools-edit.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/page-tools-revisions.png b/pyload/webui/themes/Dark/img/default/page-tools-revisions.png
index 5c3b8587f..5c3b8587f 100644
--- a/module/webui/themes/Dark/img/default/page-tools-revisions.png
+++ b/pyload/webui/themes/Dark/img/default/page-tools-revisions.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/parseUri.png b/pyload/webui/themes/Dark/img/default/parseUri.png
index 937bded9d..937bded9d 100644
--- a/module/webui/themes/Dark/img/default/parseUri.png
+++ b/pyload/webui/themes/Dark/img/default/parseUri.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/pencil.png b/pyload/webui/themes/Dark/img/default/pencil.png
index 0bfecd50e..0bfecd50e 100644
--- a/module/webui/themes/Dark/img/default/pencil.png
+++ b/pyload/webui/themes/Dark/img/default/pencil.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/reconnect.png b/pyload/webui/themes/Dark/img/default/reconnect.png
index 49b269145..49b269145 100644
--- a/module/webui/themes/Dark/img/default/reconnect.png
+++ b/pyload/webui/themes/Dark/img/default/reconnect.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/status_None.png b/pyload/webui/themes/Dark/img/default/status_None.png
index 293b13f77..293b13f77 100644
--- a/module/webui/themes/Dark/img/default/status_None.png
+++ b/pyload/webui/themes/Dark/img/default/status_None.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/status_downloading.png b/pyload/webui/themes/Dark/img/default/status_downloading.png
index fb4ebc850..fb4ebc850 100644
--- a/module/webui/themes/Dark/img/default/status_downloading.png
+++ b/pyload/webui/themes/Dark/img/default/status_downloading.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/status_failed.png b/pyload/webui/themes/Dark/img/default/status_failed.png
index c37bd062e..c37bd062e 100644
--- a/module/webui/themes/Dark/img/default/status_failed.png
+++ b/pyload/webui/themes/Dark/img/default/status_failed.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/status_finished.png b/pyload/webui/themes/Dark/img/default/status_finished.png
index 89c8129a4..89c8129a4 100644
--- a/module/webui/themes/Dark/img/default/status_finished.png
+++ b/pyload/webui/themes/Dark/img/default/status_finished.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/status_offline.png b/pyload/webui/themes/Dark/img/default/status_offline.png
index 0cfd58596..0cfd58596 100644
--- a/module/webui/themes/Dark/img/default/status_offline.png
+++ b/pyload/webui/themes/Dark/img/default/status_offline.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/status_proc.png b/pyload/webui/themes/Dark/img/default/status_proc.png
index 67de2c6cc..67de2c6cc 100644
--- a/module/webui/themes/Dark/img/default/status_proc.png
+++ b/pyload/webui/themes/Dark/img/default/status_proc.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/status_queue.png b/pyload/webui/themes/Dark/img/default/status_queue.png
index 293b13f77..293b13f77 100644
--- a/module/webui/themes/Dark/img/default/status_queue.png
+++ b/pyload/webui/themes/Dark/img/default/status_queue.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/status_waiting.png b/pyload/webui/themes/Dark/img/default/status_waiting.png
index 2842cc338..2842cc338 100644
--- a/module/webui/themes/Dark/img/default/status_waiting.png
+++ b/pyload/webui/themes/Dark/img/default/status_waiting.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/success.png b/pyload/webui/themes/Dark/img/default/success.png
index 89c8129a4..89c8129a4 100644
--- a/module/webui/themes/Dark/img/default/success.png
+++ b/pyload/webui/themes/Dark/img/default/success.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/tabs-border-bottom.png b/pyload/webui/themes/Dark/img/default/tabs-border-bottom.png
index 02440f428..02440f428 100644
--- a/module/webui/themes/Dark/img/default/tabs-border-bottom.png
+++ b/pyload/webui/themes/Dark/img/default/tabs-border-bottom.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/user-actions-logout.png b/pyload/webui/themes/Dark/img/default/user-actions-logout.png
index 0010931e2..0010931e2 100644
--- a/module/webui/themes/Dark/img/default/user-actions-logout.png
+++ b/pyload/webui/themes/Dark/img/default/user-actions-logout.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/user-actions-profile.png b/pyload/webui/themes/Dark/img/default/user-actions-profile.png
index 46573fff6..46573fff6 100644
--- a/module/webui/themes/Dark/img/default/user-actions-profile.png
+++ b/pyload/webui/themes/Dark/img/default/user-actions-profile.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/default/user-info.png b/pyload/webui/themes/Dark/img/default/user-info.png
index 6e643100f..6e643100f 100644
--- a/module/webui/themes/Dark/img/default/user-info.png
+++ b/pyload/webui/themes/Dark/img/default/user-info.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/pyload-logo.png b/pyload/webui/themes/Dark/img/pyload-logo.png
index e878afee5..e878afee5 100644
--- a/module/webui/themes/Dark/img/pyload-logo.png
+++ b/pyload/webui/themes/Dark/img/pyload-logo.png
Binary files differ
diff --git a/module/webui/themes/Dark/img/tab-background.png b/pyload/webui/themes/Dark/img/tab-background.png
index ee96b8407..ee96b8407 100644
--- a/module/webui/themes/Dark/img/tab-background.png
+++ b/pyload/webui/themes/Dark/img/tab-background.png
Binary files differ
diff --git a/module/webui/themes/Dark/js/render/admin.coffee b/pyload/webui/themes/Dark/js/render/admin.coffee
index 5afbcbb66..5afbcbb66 100644
--- a/module/webui/themes/Dark/js/render/admin.coffee
+++ b/pyload/webui/themes/Dark/js/render/admin.coffee
diff --git a/module/webui/themes/Dark/js/render/admin.min.js b/pyload/webui/themes/Dark/js/render/admin.min.js
index 94a5e494d..94a5e494d 100644
--- a/module/webui/themes/Dark/js/render/admin.min.js
+++ b/pyload/webui/themes/Dark/js/render/admin.min.js
diff --git a/module/webui/themes/Dark/js/render/base.coffee b/pyload/webui/themes/Dark/js/render/base.coffee
index 07b8bfb6f..07b8bfb6f 100644
--- a/module/webui/themes/Dark/js/render/base.coffee
+++ b/pyload/webui/themes/Dark/js/render/base.coffee
diff --git a/module/webui/themes/Dark/js/render/base.min.js b/pyload/webui/themes/Dark/js/render/base.min.js
index 1ba1d73f9..1ba1d73f9 100644
--- a/module/webui/themes/Dark/js/render/base.min.js
+++ b/pyload/webui/themes/Dark/js/render/base.min.js
diff --git a/module/webui/themes/Dark/js/render/package.js b/pyload/webui/themes/Dark/js/render/package.js
index 659a8e6fc..659a8e6fc 100644
--- a/module/webui/themes/Dark/js/render/package.js
+++ b/pyload/webui/themes/Dark/js/render/package.js
diff --git a/module/webui/themes/Dark/js/render/settings.coffee b/pyload/webui/themes/Dark/js/render/settings.coffee
index d522741b9..d522741b9 100644
--- a/module/webui/themes/Dark/js/render/settings.coffee
+++ b/pyload/webui/themes/Dark/js/render/settings.coffee
diff --git a/module/webui/themes/Dark/js/render/settings.min.js b/pyload/webui/themes/Dark/js/render/settings.min.js
index 41d1cb25a..41d1cb25a 100644
--- a/module/webui/themes/Dark/js/render/settings.min.js
+++ b/pyload/webui/themes/Dark/js/render/settings.min.js
diff --git a/module/webui/themes/Dark/js/static/MooDialog.js b/pyload/webui/themes/Dark/js/static/MooDialog.js
index 45a52496f..45a52496f 100644
--- a/module/webui/themes/Dark/js/static/MooDialog.js
+++ b/pyload/webui/themes/Dark/js/static/MooDialog.js
diff --git a/module/webui/themes/Dark/js/static/MooDialog.min.js b/pyload/webui/themes/Dark/js/static/MooDialog.min.js
index 90b3ae100..90b3ae100 100644
--- a/module/webui/themes/Dark/js/static/MooDialog.min.js
+++ b/pyload/webui/themes/Dark/js/static/MooDialog.min.js
diff --git a/module/webui/themes/Dark/js/static/MooDropMenu.js b/pyload/webui/themes/Dark/js/static/MooDropMenu.js
index ac0fa1874..ac0fa1874 100644
--- a/module/webui/themes/Dark/js/static/MooDropMenu.js
+++ b/pyload/webui/themes/Dark/js/static/MooDropMenu.js
diff --git a/module/webui/themes/Dark/js/static/MooDropMenu.min.js b/pyload/webui/themes/Dark/js/static/MooDropMenu.min.js
index 552ae247a..552ae247a 100644
--- a/module/webui/themes/Dark/js/static/MooDropMenu.min.js
+++ b/pyload/webui/themes/Dark/js/static/MooDropMenu.min.js
diff --git a/module/webui/themes/Dark/js/static/mootools-core.js b/pyload/webui/themes/Dark/js/static/mootools-core.js
index db83850fd..db83850fd 100644
--- a/module/webui/themes/Dark/js/static/mootools-core.js
+++ b/pyload/webui/themes/Dark/js/static/mootools-core.js
diff --git a/module/webui/themes/Dark/js/static/mootools-core.min.js b/pyload/webui/themes/Dark/js/static/mootools-core.min.js
index 354f94196..354f94196 100644
--- a/module/webui/themes/Dark/js/static/mootools-core.min.js
+++ b/pyload/webui/themes/Dark/js/static/mootools-core.min.js
diff --git a/module/webui/themes/Dark/js/static/mootools-more.js b/pyload/webui/themes/Dark/js/static/mootools-more.js
index c7f4a1a0e..c7f4a1a0e 100644
--- a/module/webui/themes/Dark/js/static/mootools-more.js
+++ b/pyload/webui/themes/Dark/js/static/mootools-more.js
diff --git a/module/webui/themes/Dark/js/static/mootools-more.min.js b/pyload/webui/themes/Dark/js/static/mootools-more.min.js
index ce03a60fd..ce03a60fd 100644
--- a/module/webui/themes/Dark/js/static/mootools-more.min.js
+++ b/pyload/webui/themes/Dark/js/static/mootools-more.min.js
diff --git a/module/webui/themes/Dark/js/static/purr.js b/pyload/webui/themes/Dark/js/static/purr.js
index 9cbc503d9..9cbc503d9 100644
--- a/module/webui/themes/Dark/js/static/purr.js
+++ b/pyload/webui/themes/Dark/js/static/purr.js
diff --git a/module/webui/themes/Dark/js/static/purr.min.js b/pyload/webui/themes/Dark/js/static/purr.min.js
index bf70e357d..bf70e357d 100644
--- a/module/webui/themes/Dark/js/static/purr.min.js
+++ b/pyload/webui/themes/Dark/js/static/purr.min.js
diff --git a/module/webui/themes/Dark/js/static/tinytab.js b/pyload/webui/themes/Dark/js/static/tinytab.js
index de50279fc..de50279fc 100644
--- a/module/webui/themes/Dark/js/static/tinytab.js
+++ b/pyload/webui/themes/Dark/js/static/tinytab.js
diff --git a/module/webui/themes/Dark/js/static/tinytab.min.js b/pyload/webui/themes/Dark/js/static/tinytab.min.js
index 2f4fa0436..2f4fa0436 100644
--- a/module/webui/themes/Dark/js/static/tinytab.min.js
+++ b/pyload/webui/themes/Dark/js/static/tinytab.min.js
diff --git a/module/webui/themes/Dark/tml/admin.html b/pyload/webui/themes/Dark/tml/admin.html
index 3a88ffc7a..3a88ffc7a 100644
--- a/module/webui/themes/Dark/tml/admin.html
+++ b/pyload/webui/themes/Dark/tml/admin.html
diff --git a/module/webui/themes/Dark/tml/base.html b/pyload/webui/themes/Dark/tml/base.html
index bebb0600d..bebb0600d 100644
--- a/module/webui/themes/Dark/tml/base.html
+++ b/pyload/webui/themes/Dark/tml/base.html
diff --git a/module/webui/themes/Dark/tml/captcha.html b/pyload/webui/themes/Dark/tml/captcha.html
index 731d97d11..731d97d11 100644
--- a/module/webui/themes/Dark/tml/captcha.html
+++ b/pyload/webui/themes/Dark/tml/captcha.html
diff --git a/module/webui/themes/Dark/tml/downloads.html b/pyload/webui/themes/Dark/tml/downloads.html
index c6ff7a243..c6ff7a243 100644
--- a/module/webui/themes/Dark/tml/downloads.html
+++ b/pyload/webui/themes/Dark/tml/downloads.html
diff --git a/module/webui/themes/Dark/tml/folder.html b/pyload/webui/themes/Dark/tml/folder.html
index b57338d5e..b57338d5e 100644
--- a/module/webui/themes/Dark/tml/folder.html
+++ b/pyload/webui/themes/Dark/tml/folder.html
diff --git a/module/webui/themes/Dark/tml/home.html b/pyload/webui/themes/Dark/tml/home.html
index 9131c640e..9131c640e 100644
--- a/module/webui/themes/Dark/tml/home.html
+++ b/pyload/webui/themes/Dark/tml/home.html
diff --git a/module/webui/themes/Dark/tml/info.html b/pyload/webui/themes/Dark/tml/info.html
index 1c0a35e9f..1c0a35e9f 100644
--- a/module/webui/themes/Dark/tml/info.html
+++ b/pyload/webui/themes/Dark/tml/info.html
diff --git a/module/webui/themes/Dark/tml/login.html b/pyload/webui/themes/Dark/tml/login.html
index dcb3a18b8..dcb3a18b8 100644
--- a/module/webui/themes/Dark/tml/login.html
+++ b/pyload/webui/themes/Dark/tml/login.html
diff --git a/module/webui/themes/Dark/tml/logout.html b/pyload/webui/themes/Dark/tml/logout.html
index 08adfcf6c..08adfcf6c 100644
--- a/module/webui/themes/Dark/tml/logout.html
+++ b/pyload/webui/themes/Dark/tml/logout.html
diff --git a/module/webui/themes/Dark/tml/logs.html b/pyload/webui/themes/Dark/tml/logs.html
index e7fead2df..e7fead2df 100644
--- a/module/webui/themes/Dark/tml/logs.html
+++ b/pyload/webui/themes/Dark/tml/logs.html
diff --git a/module/webui/themes/Dark/tml/pathchooser.html b/pyload/webui/themes/Dark/tml/pathchooser.html
index 288af8bfa..288af8bfa 100644
--- a/module/webui/themes/Dark/tml/pathchooser.html
+++ b/pyload/webui/themes/Dark/tml/pathchooser.html
diff --git a/module/webui/themes/Dark/tml/queue.html b/pyload/webui/themes/Dark/tml/queue.html
index 1a61e2638..1a61e2638 100644
--- a/module/webui/themes/Dark/tml/queue.html
+++ b/pyload/webui/themes/Dark/tml/queue.html
diff --git a/module/webui/themes/Dark/tml/settings.html b/pyload/webui/themes/Dark/tml/settings.html
index cf0fe1745..cf0fe1745 100644
--- a/module/webui/themes/Dark/tml/settings.html
+++ b/pyload/webui/themes/Dark/tml/settings.html
diff --git a/module/webui/themes/Dark/tml/settings_item.html b/pyload/webui/themes/Dark/tml/settings_item.html
index e417e564c..e417e564c 100644
--- a/module/webui/themes/Dark/tml/settings_item.html
+++ b/pyload/webui/themes/Dark/tml/settings_item.html
diff --git a/module/webui/themes/Dark/tml/window.html b/pyload/webui/themes/Dark/tml/window.html
index a518a7b95..a518a7b95 100644
--- a/module/webui/themes/Dark/tml/window.html
+++ b/pyload/webui/themes/Dark/tml/window.html
diff --git a/module/webui/themes/Default/css/MooDialog.css b/pyload/webui/themes/Default/css/MooDialog.css
index 1e2ae68aa..1e2ae68aa 100644
--- a/module/webui/themes/Default/css/MooDialog.css
+++ b/pyload/webui/themes/Default/css/MooDialog.css
diff --git a/module/webui/themes/Default/css/base.css b/pyload/webui/themes/Default/css/base.css
index f5078bfbb..f5078bfbb 100644
--- a/module/webui/themes/Default/css/base.css
+++ b/pyload/webui/themes/Default/css/base.css
diff --git a/module/webui/themes/Default/css/log.css b/pyload/webui/themes/Default/css/log.css
index 33e67397d..33e67397d 100644
--- a/module/webui/themes/Default/css/log.css
+++ b/pyload/webui/themes/Default/css/log.css
diff --git a/module/webui/themes/Default/css/pathchooser.css b/pyload/webui/themes/Default/css/pathchooser.css
index 204812aa1..204812aa1 100644
--- a/module/webui/themes/Default/css/pathchooser.css
+++ b/pyload/webui/themes/Default/css/pathchooser.css
diff --git a/module/webui/themes/Default/css/window.css b/pyload/webui/themes/Default/css/window.css
index b469b4259..b469b4259 100644
--- a/module/webui/themes/Default/css/window.css
+++ b/pyload/webui/themes/Default/css/window.css
diff --git a/module/webui/themes/Default/img/MooDialog/dialog-close.png b/pyload/webui/themes/Default/img/MooDialog/dialog-close.png
index 81ebb88b2..81ebb88b2 100644
--- a/module/webui/themes/Default/img/MooDialog/dialog-close.png
+++ b/pyload/webui/themes/Default/img/MooDialog/dialog-close.png
Binary files differ
diff --git a/module/webui/themes/Default/img/MooDialog/dialog-error.png b/pyload/webui/themes/Default/img/MooDialog/dialog-error.png
index d70328403..d70328403 100644
--- a/module/webui/themes/Default/img/MooDialog/dialog-error.png
+++ b/pyload/webui/themes/Default/img/MooDialog/dialog-error.png
Binary files differ
diff --git a/module/webui/themes/Default/img/MooDialog/dialog-question.png b/pyload/webui/themes/Default/img/MooDialog/dialog-question.png
index b0af3db5b..b0af3db5b 100644
--- a/module/webui/themes/Default/img/MooDialog/dialog-question.png
+++ b/pyload/webui/themes/Default/img/MooDialog/dialog-question.png
Binary files differ
diff --git a/module/webui/themes/Default/img/MooDialog/dialog-warning.png b/pyload/webui/themes/Default/img/MooDialog/dialog-warning.png
index aad64d4be..aad64d4be 100644
--- a/module/webui/themes/Default/img/MooDialog/dialog-warning.png
+++ b/pyload/webui/themes/Default/img/MooDialog/dialog-warning.png
Binary files differ
diff --git a/module/webui/themes/Default/img/add_folder.png b/pyload/webui/themes/Default/img/add_folder.png
index 8acbc411b..8acbc411b 100644
--- a/module/webui/themes/Default/img/add_folder.png
+++ b/pyload/webui/themes/Default/img/add_folder.png
Binary files differ
diff --git a/module/webui/themes/Default/img/ajax-loader.gif b/pyload/webui/themes/Default/img/ajax-loader.gif
index 2fd8e0737..2fd8e0737 100644
--- a/module/webui/themes/Default/img/ajax-loader.gif
+++ b/pyload/webui/themes/Default/img/ajax-loader.gif
Binary files differ
diff --git a/module/webui/themes/Default/img/arrow_refresh.png b/pyload/webui/themes/Default/img/arrow_refresh.png
index 0de26566d..0de26566d 100644
--- a/module/webui/themes/Default/img/arrow_refresh.png
+++ b/pyload/webui/themes/Default/img/arrow_refresh.png
Binary files differ
diff --git a/module/webui/themes/Default/img/arrow_right.png b/pyload/webui/themes/Default/img/arrow_right.png
index b1a181923..b1a181923 100644
--- a/module/webui/themes/Default/img/arrow_right.png
+++ b/pyload/webui/themes/Default/img/arrow_right.png
Binary files differ
diff --git a/module/webui/themes/Default/img/big_button.gif b/pyload/webui/themes/Default/img/big_button.gif
index 7680490ea..7680490ea 100644
--- a/module/webui/themes/Default/img/big_button.gif
+++ b/pyload/webui/themes/Default/img/big_button.gif
Binary files differ
diff --git a/module/webui/themes/Default/img/big_button_over.gif b/pyload/webui/themes/Default/img/big_button_over.gif
index 2e3ee10d2..2e3ee10d2 100644
--- a/module/webui/themes/Default/img/big_button_over.gif
+++ b/pyload/webui/themes/Default/img/big_button_over.gif
Binary files differ
diff --git a/module/webui/themes/Default/img/body.png b/pyload/webui/themes/Default/img/body.png
index 7ff1043e0..7ff1043e0 100644
--- a/module/webui/themes/Default/img/body.png
+++ b/pyload/webui/themes/Default/img/body.png
Binary files differ
diff --git a/module/webui/themes/Default/img/button.png b/pyload/webui/themes/Default/img/button.png
index 890160614..890160614 100644
--- a/module/webui/themes/Default/img/button.png
+++ b/pyload/webui/themes/Default/img/button.png
Binary files differ
diff --git a/module/webui/themes/Default/img/closebtn.gif b/pyload/webui/themes/Default/img/closebtn.gif
index 3e27e6030..3e27e6030 100644
--- a/module/webui/themes/Default/img/closebtn.gif
+++ b/pyload/webui/themes/Default/img/closebtn.gif
Binary files differ
diff --git a/module/webui/themes/Default/img/cog.png b/pyload/webui/themes/Default/img/cog.png
index 67de2c6cc..67de2c6cc 100644
--- a/module/webui/themes/Default/img/cog.png
+++ b/pyload/webui/themes/Default/img/cog.png
Binary files differ
diff --git a/module/webui/themes/Default/img/control_add.png b/pyload/webui/themes/Default/img/control_add.png
index d39886893..d39886893 100644
--- a/module/webui/themes/Default/img/control_add.png
+++ b/pyload/webui/themes/Default/img/control_add.png
Binary files differ
diff --git a/module/webui/themes/Default/img/control_add_blue.png b/pyload/webui/themes/Default/img/control_add_blue.png
index d11b7f41d..d11b7f41d 100644
--- a/module/webui/themes/Default/img/control_add_blue.png
+++ b/pyload/webui/themes/Default/img/control_add_blue.png
Binary files differ
diff --git a/module/webui/themes/Default/img/control_cancel.png b/pyload/webui/themes/Default/img/control_cancel.png
index 7b9bc3fba..7b9bc3fba 100644
--- a/module/webui/themes/Default/img/control_cancel.png
+++ b/pyload/webui/themes/Default/img/control_cancel.png
Binary files differ
diff --git a/module/webui/themes/Default/img/control_cancel_blue.png b/pyload/webui/themes/Default/img/control_cancel_blue.png
index 0c5c96ce3..0c5c96ce3 100644
--- a/module/webui/themes/Default/img/control_cancel_blue.png
+++ b/pyload/webui/themes/Default/img/control_cancel_blue.png
Binary files differ
diff --git a/module/webui/themes/Default/img/control_pause.png b/pyload/webui/themes/Default/img/control_pause.png
index 2d9ce9c4e..2d9ce9c4e 100644
--- a/module/webui/themes/Default/img/control_pause.png
+++ b/pyload/webui/themes/Default/img/control_pause.png
Binary files differ
diff --git a/module/webui/themes/Default/img/control_pause_blue.png b/pyload/webui/themes/Default/img/control_pause_blue.png
index ec61099b0..ec61099b0 100644
--- a/module/webui/themes/Default/img/control_pause_blue.png
+++ b/pyload/webui/themes/Default/img/control_pause_blue.png
Binary files differ
diff --git a/module/webui/themes/Default/img/control_play.png b/pyload/webui/themes/Default/img/control_play.png
index 0846555d0..0846555d0 100644
--- a/module/webui/themes/Default/img/control_play.png
+++ b/pyload/webui/themes/Default/img/control_play.png
Binary files differ
diff --git a/module/webui/themes/Default/img/control_play_blue.png b/pyload/webui/themes/Default/img/control_play_blue.png
index f8c8ec683..f8c8ec683 100644
--- a/module/webui/themes/Default/img/control_play_blue.png
+++ b/pyload/webui/themes/Default/img/control_play_blue.png
Binary files differ
diff --git a/module/webui/themes/Default/img/control_stop.png b/pyload/webui/themes/Default/img/control_stop.png
index 893bb60e5..893bb60e5 100644
--- a/module/webui/themes/Default/img/control_stop.png
+++ b/pyload/webui/themes/Default/img/control_stop.png
Binary files differ
diff --git a/module/webui/themes/Default/img/control_stop_blue.png b/pyload/webui/themes/Default/img/control_stop_blue.png
index e6f75d232..e6f75d232 100644
--- a/module/webui/themes/Default/img/control_stop_blue.png
+++ b/pyload/webui/themes/Default/img/control_stop_blue.png
Binary files differ
diff --git a/module/webui/themes/Default/img/delete.png b/pyload/webui/themes/Default/img/delete.png
index 08f249365..08f249365 100644
--- a/module/webui/themes/Default/img/delete.png
+++ b/pyload/webui/themes/Default/img/delete.png
Binary files differ
diff --git a/module/webui/themes/Default/img/drag_corner.gif b/pyload/webui/themes/Default/img/drag_corner.gif
index befb1adf1..befb1adf1 100644
--- a/module/webui/themes/Default/img/drag_corner.gif
+++ b/pyload/webui/themes/Default/img/drag_corner.gif
Binary files differ
diff --git a/module/webui/themes/Default/img/error.png b/pyload/webui/themes/Default/img/error.png
index c37bd062e..c37bd062e 100644
--- a/module/webui/themes/Default/img/error.png
+++ b/pyload/webui/themes/Default/img/error.png
Binary files differ
diff --git a/module/webui/themes/Default/img/folder.png b/pyload/webui/themes/Default/img/folder.png
index 784e8fa48..784e8fa48 100644
--- a/module/webui/themes/Default/img/folder.png
+++ b/pyload/webui/themes/Default/img/folder.png
Binary files differ
diff --git a/module/webui/themes/Default/img/full.png b/pyload/webui/themes/Default/img/full.png
index fea52af76..fea52af76 100644
--- a/module/webui/themes/Default/img/full.png
+++ b/pyload/webui/themes/Default/img/full.png
Binary files differ
diff --git a/module/webui/themes/Default/img/head-login.png b/pyload/webui/themes/Default/img/head-login.png
index b59b7cbbf..b59b7cbbf 100644
--- a/module/webui/themes/Default/img/head-login.png
+++ b/pyload/webui/themes/Default/img/head-login.png
Binary files differ
diff --git a/module/webui/themes/Default/img/head-menu-collector.png b/pyload/webui/themes/Default/img/head-menu-collector.png
index 861be40bc..861be40bc 100644
--- a/module/webui/themes/Default/img/head-menu-collector.png
+++ b/pyload/webui/themes/Default/img/head-menu-collector.png
Binary files differ
diff --git a/module/webui/themes/Default/img/head-menu-config.png b/pyload/webui/themes/Default/img/head-menu-config.png
index bbf43d4f3..bbf43d4f3 100644
--- a/module/webui/themes/Default/img/head-menu-config.png
+++ b/pyload/webui/themes/Default/img/head-menu-config.png
Binary files differ
diff --git a/module/webui/themes/Default/img/head-menu-development.png b/pyload/webui/themes/Default/img/head-menu-development.png
index fad150fe1..fad150fe1 100644
--- a/module/webui/themes/Default/img/head-menu-development.png
+++ b/pyload/webui/themes/Default/img/head-menu-development.png
Binary files differ
diff --git a/module/webui/themes/Default/img/head-menu-download.png b/pyload/webui/themes/Default/img/head-menu-download.png
index 98c5da9db..98c5da9db 100644
--- a/module/webui/themes/Default/img/head-menu-download.png
+++ b/pyload/webui/themes/Default/img/head-menu-download.png
Binary files differ
diff --git a/module/webui/themes/Default/img/head-menu-home.png b/pyload/webui/themes/Default/img/head-menu-home.png
index 9d62109aa..9d62109aa 100644
--- a/module/webui/themes/Default/img/head-menu-home.png
+++ b/pyload/webui/themes/Default/img/head-menu-home.png
Binary files differ
diff --git a/module/webui/themes/Default/img/head-menu-index.png b/pyload/webui/themes/Default/img/head-menu-index.png
index 44d631064..44d631064 100644
--- a/module/webui/themes/Default/img/head-menu-index.png
+++ b/pyload/webui/themes/Default/img/head-menu-index.png
Binary files differ
diff --git a/module/webui/themes/Default/img/head-menu-news.png b/pyload/webui/themes/Default/img/head-menu-news.png
index 43950ebc9..43950ebc9 100644
--- a/module/webui/themes/Default/img/head-menu-news.png
+++ b/pyload/webui/themes/Default/img/head-menu-news.png
Binary files differ
diff --git a/module/webui/themes/Default/img/head-menu-queue.png b/pyload/webui/themes/Default/img/head-menu-queue.png
index be98793ce..be98793ce 100644
--- a/module/webui/themes/Default/img/head-menu-queue.png
+++ b/pyload/webui/themes/Default/img/head-menu-queue.png
Binary files differ
diff --git a/module/webui/themes/Default/img/head-menu-recent.png b/pyload/webui/themes/Default/img/head-menu-recent.png
index fc9b0497f..fc9b0497f 100644
--- a/module/webui/themes/Default/img/head-menu-recent.png
+++ b/pyload/webui/themes/Default/img/head-menu-recent.png
Binary files differ
diff --git a/module/webui/themes/Default/img/head-menu-wiki.png b/pyload/webui/themes/Default/img/head-menu-wiki.png
index 07cf0102d..07cf0102d 100644
--- a/module/webui/themes/Default/img/head-menu-wiki.png
+++ b/pyload/webui/themes/Default/img/head-menu-wiki.png
Binary files differ
diff --git a/module/webui/themes/Default/img/head-search-noshadow.png b/pyload/webui/themes/Default/img/head-search-noshadow.png
index aafdae015..aafdae015 100644
--- a/module/webui/themes/Default/img/head-search-noshadow.png
+++ b/pyload/webui/themes/Default/img/head-search-noshadow.png
Binary files differ
diff --git a/module/webui/themes/Default/img/head_bg1.png b/pyload/webui/themes/Default/img/head_bg1.png
index f2848c3cc..f2848c3cc 100644
--- a/module/webui/themes/Default/img/head_bg1.png
+++ b/pyload/webui/themes/Default/img/head_bg1.png
Binary files differ
diff --git a/module/webui/themes/Default/img/images.png b/pyload/webui/themes/Default/img/images.png
index 184860d1e..184860d1e 100644
--- a/module/webui/themes/Default/img/images.png
+++ b/pyload/webui/themes/Default/img/images.png
Binary files differ
diff --git a/module/webui/themes/Default/img/notice.png b/pyload/webui/themes/Default/img/notice.png
index 12cd1aef9..12cd1aef9 100644
--- a/module/webui/themes/Default/img/notice.png
+++ b/pyload/webui/themes/Default/img/notice.png
Binary files differ
diff --git a/module/webui/themes/Default/img/package_go.png b/pyload/webui/themes/Default/img/package_go.png
index aace63ad6..aace63ad6 100644
--- a/module/webui/themes/Default/img/package_go.png
+++ b/pyload/webui/themes/Default/img/package_go.png
Binary files differ
diff --git a/module/webui/themes/Default/img/page-tools-backlinks.png b/pyload/webui/themes/Default/img/page-tools-backlinks.png
index 3eb6a9ce3..3eb6a9ce3 100644
--- a/module/webui/themes/Default/img/page-tools-backlinks.png
+++ b/pyload/webui/themes/Default/img/page-tools-backlinks.png
Binary files differ
diff --git a/module/webui/themes/Default/img/page-tools-edit.png b/pyload/webui/themes/Default/img/page-tools-edit.png
index 188e1c12b..188e1c12b 100644
--- a/module/webui/themes/Default/img/page-tools-edit.png
+++ b/pyload/webui/themes/Default/img/page-tools-edit.png
Binary files differ
diff --git a/module/webui/themes/Default/img/page-tools-revisions.png b/pyload/webui/themes/Default/img/page-tools-revisions.png
index 5c3b8587f..5c3b8587f 100644
--- a/module/webui/themes/Default/img/page-tools-revisions.png
+++ b/pyload/webui/themes/Default/img/page-tools-revisions.png
Binary files differ
diff --git a/module/webui/themes/Default/img/parseUri.png b/pyload/webui/themes/Default/img/parseUri.png
index 937bded9d..937bded9d 100644
--- a/module/webui/themes/Default/img/parseUri.png
+++ b/pyload/webui/themes/Default/img/parseUri.png
Binary files differ
diff --git a/module/webui/themes/Default/img/pencil.png b/pyload/webui/themes/Default/img/pencil.png
index 0bfecd50e..0bfecd50e 100644
--- a/module/webui/themes/Default/img/pencil.png
+++ b/pyload/webui/themes/Default/img/pencil.png
Binary files differ
diff --git a/module/webui/themes/Default/img/pyload-logo.png b/pyload/webui/themes/Default/img/pyload-logo.png
index 2443cd8b1..2443cd8b1 100644
--- a/module/webui/themes/Default/img/pyload-logo.png
+++ b/pyload/webui/themes/Default/img/pyload-logo.png
Binary files differ
diff --git a/module/webui/themes/Default/img/reconnect.png b/pyload/webui/themes/Default/img/reconnect.png
index 49b269145..49b269145 100644
--- a/module/webui/themes/Default/img/reconnect.png
+++ b/pyload/webui/themes/Default/img/reconnect.png
Binary files differ
diff --git a/module/webui/themes/Default/img/status_None.png b/pyload/webui/themes/Default/img/status_None.png
index 293b13f77..293b13f77 100644
--- a/module/webui/themes/Default/img/status_None.png
+++ b/pyload/webui/themes/Default/img/status_None.png
Binary files differ
diff --git a/module/webui/themes/Default/img/status_downloading.png b/pyload/webui/themes/Default/img/status_downloading.png
index fb4ebc850..fb4ebc850 100644
--- a/module/webui/themes/Default/img/status_downloading.png
+++ b/pyload/webui/themes/Default/img/status_downloading.png
Binary files differ
diff --git a/module/webui/themes/Default/img/status_failed.png b/pyload/webui/themes/Default/img/status_failed.png
index c37bd062e..c37bd062e 100644
--- a/module/webui/themes/Default/img/status_failed.png
+++ b/pyload/webui/themes/Default/img/status_failed.png
Binary files differ
diff --git a/module/webui/themes/Default/img/status_finished.png b/pyload/webui/themes/Default/img/status_finished.png
index 89c8129a4..89c8129a4 100644
--- a/module/webui/themes/Default/img/status_finished.png
+++ b/pyload/webui/themes/Default/img/status_finished.png
Binary files differ
diff --git a/module/webui/themes/Default/img/status_offline.png b/pyload/webui/themes/Default/img/status_offline.png
index 0cfd58596..0cfd58596 100644
--- a/module/webui/themes/Default/img/status_offline.png
+++ b/pyload/webui/themes/Default/img/status_offline.png
Binary files differ
diff --git a/module/webui/themes/Default/img/status_proc.png b/pyload/webui/themes/Default/img/status_proc.png
index 67de2c6cc..67de2c6cc 100644
--- a/module/webui/themes/Default/img/status_proc.png
+++ b/pyload/webui/themes/Default/img/status_proc.png
Binary files differ
diff --git a/module/webui/themes/Default/img/status_queue.png b/pyload/webui/themes/Default/img/status_queue.png
index 293b13f77..293b13f77 100644
--- a/module/webui/themes/Default/img/status_queue.png
+++ b/pyload/webui/themes/Default/img/status_queue.png
Binary files differ
diff --git a/module/webui/themes/Default/img/status_waiting.png b/pyload/webui/themes/Default/img/status_waiting.png
index 2842cc338..2842cc338 100644
--- a/module/webui/themes/Default/img/status_waiting.png
+++ b/pyload/webui/themes/Default/img/status_waiting.png
Binary files differ
diff --git a/module/webui/themes/Default/img/success.png b/pyload/webui/themes/Default/img/success.png
index 89c8129a4..89c8129a4 100644
--- a/module/webui/themes/Default/img/success.png
+++ b/pyload/webui/themes/Default/img/success.png
Binary files differ
diff --git a/module/webui/themes/Default/img/tab-background.png b/pyload/webui/themes/Default/img/tab-background.png
index 29a5d1991..29a5d1991 100644
--- a/module/webui/themes/Default/img/tab-background.png
+++ b/pyload/webui/themes/Default/img/tab-background.png
Binary files differ
diff --git a/module/webui/themes/Default/img/tabs-border-bottom.png b/pyload/webui/themes/Default/img/tabs-border-bottom.png
index 02440f428..02440f428 100644
--- a/module/webui/themes/Default/img/tabs-border-bottom.png
+++ b/pyload/webui/themes/Default/img/tabs-border-bottom.png
Binary files differ
diff --git a/module/webui/themes/Default/img/user-actions-logout.png b/pyload/webui/themes/Default/img/user-actions-logout.png
index 0010931e2..0010931e2 100644
--- a/module/webui/themes/Default/img/user-actions-logout.png
+++ b/pyload/webui/themes/Default/img/user-actions-logout.png
Binary files differ
diff --git a/module/webui/themes/Default/img/user-actions-profile.png b/pyload/webui/themes/Default/img/user-actions-profile.png
index 46573fff6..46573fff6 100644
--- a/module/webui/themes/Default/img/user-actions-profile.png
+++ b/pyload/webui/themes/Default/img/user-actions-profile.png
Binary files differ
diff --git a/module/webui/themes/Default/img/user-info.png b/pyload/webui/themes/Default/img/user-info.png
index 6e643100f..6e643100f 100644
--- a/module/webui/themes/Default/img/user-info.png
+++ b/pyload/webui/themes/Default/img/user-info.png
Binary files differ
diff --git a/module/webui/themes/Default/js/render/admin.coffee b/pyload/webui/themes/Default/js/render/admin.coffee
index 5afbcbb66..5afbcbb66 100644
--- a/module/webui/themes/Default/js/render/admin.coffee
+++ b/pyload/webui/themes/Default/js/render/admin.coffee
diff --git a/module/webui/themes/Default/js/render/admin.min.js b/pyload/webui/themes/Default/js/render/admin.min.js
index 94a5e494d..94a5e494d 100644
--- a/module/webui/themes/Default/js/render/admin.min.js
+++ b/pyload/webui/themes/Default/js/render/admin.min.js
diff --git a/module/webui/themes/Default/js/render/base.coffee b/pyload/webui/themes/Default/js/render/base.coffee
index 07b8bfb6f..07b8bfb6f 100644
--- a/module/webui/themes/Default/js/render/base.coffee
+++ b/pyload/webui/themes/Default/js/render/base.coffee
diff --git a/module/webui/themes/Default/js/render/base.min.js b/pyload/webui/themes/Default/js/render/base.min.js
index 1ba1d73f9..1ba1d73f9 100644
--- a/module/webui/themes/Default/js/render/base.min.js
+++ b/pyload/webui/themes/Default/js/render/base.min.js
diff --git a/module/webui/themes/Default/js/render/package.js b/pyload/webui/themes/Default/js/render/package.js
index 659a8e6fc..659a8e6fc 100644
--- a/module/webui/themes/Default/js/render/package.js
+++ b/pyload/webui/themes/Default/js/render/package.js
diff --git a/module/webui/themes/Default/js/render/settings.coffee b/pyload/webui/themes/Default/js/render/settings.coffee
index d522741b9..d522741b9 100644
--- a/module/webui/themes/Default/js/render/settings.coffee
+++ b/pyload/webui/themes/Default/js/render/settings.coffee
diff --git a/module/webui/themes/Default/js/render/settings.min.js b/pyload/webui/themes/Default/js/render/settings.min.js
index 41d1cb25a..41d1cb25a 100644
--- a/module/webui/themes/Default/js/render/settings.min.js
+++ b/pyload/webui/themes/Default/js/render/settings.min.js
diff --git a/module/webui/themes/Default/js/static/MooDialog.js b/pyload/webui/themes/Default/js/static/MooDialog.js
index 45a52496f..45a52496f 100644
--- a/module/webui/themes/Default/js/static/MooDialog.js
+++ b/pyload/webui/themes/Default/js/static/MooDialog.js
diff --git a/module/webui/themes/Default/js/static/MooDialog.min.js b/pyload/webui/themes/Default/js/static/MooDialog.min.js
index 90b3ae100..90b3ae100 100644
--- a/module/webui/themes/Default/js/static/MooDialog.min.js
+++ b/pyload/webui/themes/Default/js/static/MooDialog.min.js
diff --git a/module/webui/themes/Default/js/static/MooDropMenu.js b/pyload/webui/themes/Default/js/static/MooDropMenu.js
index ac0fa1874..ac0fa1874 100644
--- a/module/webui/themes/Default/js/static/MooDropMenu.js
+++ b/pyload/webui/themes/Default/js/static/MooDropMenu.js
diff --git a/module/webui/themes/Default/js/static/MooDropMenu.min.js b/pyload/webui/themes/Default/js/static/MooDropMenu.min.js
index 552ae247a..552ae247a 100644
--- a/module/webui/themes/Default/js/static/MooDropMenu.min.js
+++ b/pyload/webui/themes/Default/js/static/MooDropMenu.min.js
diff --git a/module/webui/themes/Default/js/static/mootools-core.js b/pyload/webui/themes/Default/js/static/mootools-core.js
index db83850fd..db83850fd 100644
--- a/module/webui/themes/Default/js/static/mootools-core.js
+++ b/pyload/webui/themes/Default/js/static/mootools-core.js
diff --git a/module/webui/themes/Default/js/static/mootools-core.min.js b/pyload/webui/themes/Default/js/static/mootools-core.min.js
index 354f94196..354f94196 100644
--- a/module/webui/themes/Default/js/static/mootools-core.min.js
+++ b/pyload/webui/themes/Default/js/static/mootools-core.min.js
diff --git a/module/webui/themes/Default/js/static/mootools-more.js b/pyload/webui/themes/Default/js/static/mootools-more.js
index c7f4a1a0e..c7f4a1a0e 100644
--- a/module/webui/themes/Default/js/static/mootools-more.js
+++ b/pyload/webui/themes/Default/js/static/mootools-more.js
diff --git a/module/webui/themes/Default/js/static/mootools-more.min.js b/pyload/webui/themes/Default/js/static/mootools-more.min.js
index ce03a60fd..ce03a60fd 100644
--- a/module/webui/themes/Default/js/static/mootools-more.min.js
+++ b/pyload/webui/themes/Default/js/static/mootools-more.min.js
diff --git a/module/webui/themes/Default/js/static/purr.js b/pyload/webui/themes/Default/js/static/purr.js
index 9cbc503d9..9cbc503d9 100644
--- a/module/webui/themes/Default/js/static/purr.js
+++ b/pyload/webui/themes/Default/js/static/purr.js
diff --git a/module/webui/themes/Default/js/static/purr.min.js b/pyload/webui/themes/Default/js/static/purr.min.js
index bf70e357d..bf70e357d 100644
--- a/module/webui/themes/Default/js/static/purr.min.js
+++ b/pyload/webui/themes/Default/js/static/purr.min.js
diff --git a/module/webui/themes/Default/js/static/tinytab.js b/pyload/webui/themes/Default/js/static/tinytab.js
index de50279fc..de50279fc 100644
--- a/module/webui/themes/Default/js/static/tinytab.js
+++ b/pyload/webui/themes/Default/js/static/tinytab.js
diff --git a/module/webui/themes/Default/js/static/tinytab.min.js b/pyload/webui/themes/Default/js/static/tinytab.min.js
index 2f4fa0436..2f4fa0436 100644
--- a/module/webui/themes/Default/js/static/tinytab.min.js
+++ b/pyload/webui/themes/Default/js/static/tinytab.min.js
diff --git a/module/webui/themes/Default/tml/admin.html b/pyload/webui/themes/Default/tml/admin.html
index 0b7301fc8..0b7301fc8 100644
--- a/module/webui/themes/Default/tml/admin.html
+++ b/pyload/webui/themes/Default/tml/admin.html
diff --git a/module/webui/themes/Default/tml/base.html b/pyload/webui/themes/Default/tml/base.html
index aac70a394..aac70a394 100644
--- a/module/webui/themes/Default/tml/base.html
+++ b/pyload/webui/themes/Default/tml/base.html
diff --git a/module/webui/themes/Default/tml/captcha.html b/pyload/webui/themes/Default/tml/captcha.html
index 3bfa6cbcf..3bfa6cbcf 100644
--- a/module/webui/themes/Default/tml/captcha.html
+++ b/pyload/webui/themes/Default/tml/captcha.html
diff --git a/module/webui/themes/Default/tml/downloads.html b/pyload/webui/themes/Default/tml/downloads.html
index fe0f4f1bc..fe0f4f1bc 100644
--- a/module/webui/themes/Default/tml/downloads.html
+++ b/pyload/webui/themes/Default/tml/downloads.html
diff --git a/module/webui/themes/Default/tml/filemanager.html b/pyload/webui/themes/Default/tml/filemanager.html
index c2ac5df9d..c2ac5df9d 100644
--- a/module/webui/themes/Default/tml/filemanager.html
+++ b/pyload/webui/themes/Default/tml/filemanager.html
diff --git a/module/webui/themes/Default/tml/folder.html b/pyload/webui/themes/Default/tml/folder.html
index 54dd72bb9..54dd72bb9 100644
--- a/module/webui/themes/Default/tml/folder.html
+++ b/pyload/webui/themes/Default/tml/folder.html
diff --git a/module/webui/themes/Default/tml/home.html b/pyload/webui/themes/Default/tml/home.html
index 09daae596..09daae596 100644
--- a/module/webui/themes/Default/tml/home.html
+++ b/pyload/webui/themes/Default/tml/home.html
diff --git a/module/webui/themes/Default/tml/info.html b/pyload/webui/themes/Default/tml/info.html
index a5fc3c3f7..a5fc3c3f7 100644
--- a/module/webui/themes/Default/tml/info.html
+++ b/pyload/webui/themes/Default/tml/info.html
diff --git a/module/webui/themes/Default/tml/login.html b/pyload/webui/themes/Default/tml/login.html
index 538ce792d..538ce792d 100644
--- a/module/webui/themes/Default/tml/login.html
+++ b/pyload/webui/themes/Default/tml/login.html
diff --git a/module/webui/themes/Default/tml/logout.html b/pyload/webui/themes/Default/tml/logout.html
index 19d673e7c..19d673e7c 100644
--- a/module/webui/themes/Default/tml/logout.html
+++ b/pyload/webui/themes/Default/tml/logout.html
diff --git a/module/webui/themes/Default/tml/logs.html b/pyload/webui/themes/Default/tml/logs.html
index ccf992d04..ccf992d04 100644
--- a/module/webui/themes/Default/tml/logs.html
+++ b/pyload/webui/themes/Default/tml/logs.html
diff --git a/module/webui/themes/Default/tml/pathchooser.html b/pyload/webui/themes/Default/tml/pathchooser.html
index 5cf08a6e2..5cf08a6e2 100644
--- a/module/webui/themes/Default/tml/pathchooser.html
+++ b/pyload/webui/themes/Default/tml/pathchooser.html
diff --git a/module/webui/themes/Default/tml/queue.html b/pyload/webui/themes/Default/tml/queue.html
index 0fa9580e0..0fa9580e0 100644
--- a/module/webui/themes/Default/tml/queue.html
+++ b/pyload/webui/themes/Default/tml/queue.html
diff --git a/module/webui/themes/Default/tml/settings.html b/pyload/webui/themes/Default/tml/settings.html
index 9205f011b..9205f011b 100644
--- a/module/webui/themes/Default/tml/settings.html
+++ b/pyload/webui/themes/Default/tml/settings.html
diff --git a/module/webui/themes/Default/tml/settings_item.html b/pyload/webui/themes/Default/tml/settings_item.html
index 6642d34b4..6642d34b4 100644
--- a/module/webui/themes/Default/tml/settings_item.html
+++ b/pyload/webui/themes/Default/tml/settings_item.html
diff --git a/module/webui/themes/Default/tml/window.html b/pyload/webui/themes/Default/tml/window.html
index 800874af0..800874af0 100644
--- a/module/webui/themes/Default/tml/window.html
+++ b/pyload/webui/themes/Default/tml/window.html
diff --git a/module/webui/themes/Flat/css/MooDialog.css b/pyload/webui/themes/Flat/css/MooDialog.css
index 7d6e38ece..7d6e38ece 100644
--- a/module/webui/themes/Flat/css/MooDialog.css
+++ b/pyload/webui/themes/Flat/css/MooDialog.css
diff --git a/module/webui/themes/Flat/css/base.css b/pyload/webui/themes/Flat/css/base.css
index fd73d0a19..fd73d0a19 100644
--- a/module/webui/themes/Flat/css/base.css
+++ b/pyload/webui/themes/Flat/css/base.css
diff --git a/module/webui/themes/Flat/css/log.css b/pyload/webui/themes/Flat/css/log.css
index c2f21b506..c2f21b506 100644
--- a/module/webui/themes/Flat/css/log.css
+++ b/pyload/webui/themes/Flat/css/log.css
diff --git a/module/webui/themes/Flat/css/pathchooser.css b/pyload/webui/themes/Flat/css/pathchooser.css
index 204812aa1..204812aa1 100644
--- a/module/webui/themes/Flat/css/pathchooser.css
+++ b/pyload/webui/themes/Flat/css/pathchooser.css
diff --git a/module/webui/themes/Flat/css/window.css b/pyload/webui/themes/Flat/css/window.css
index 40c1aadca..40c1aadca 100644
--- a/module/webui/themes/Flat/css/window.css
+++ b/pyload/webui/themes/Flat/css/window.css
diff --git a/module/webui/themes/Flat/img/MooDialog/dialog-close.png b/pyload/webui/themes/Flat/img/MooDialog/dialog-close.png
index 81ebb88b2..81ebb88b2 100644
--- a/module/webui/themes/Flat/img/MooDialog/dialog-close.png
+++ b/pyload/webui/themes/Flat/img/MooDialog/dialog-close.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/MooDialog/dialog-error.png b/pyload/webui/themes/Flat/img/MooDialog/dialog-error.png
index d70328403..d70328403 100644
--- a/module/webui/themes/Flat/img/MooDialog/dialog-error.png
+++ b/pyload/webui/themes/Flat/img/MooDialog/dialog-error.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/MooDialog/dialog-question.png b/pyload/webui/themes/Flat/img/MooDialog/dialog-question.png
index b0af3db5b..b0af3db5b 100644
--- a/module/webui/themes/Flat/img/MooDialog/dialog-question.png
+++ b/pyload/webui/themes/Flat/img/MooDialog/dialog-question.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/MooDialog/dialog-warning.png b/pyload/webui/themes/Flat/img/MooDialog/dialog-warning.png
index aad64d4be..aad64d4be 100644
--- a/module/webui/themes/Flat/img/MooDialog/dialog-warning.png
+++ b/pyload/webui/themes/Flat/img/MooDialog/dialog-warning.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/arrow_refresh.png b/pyload/webui/themes/Flat/img/arrow_refresh.png
index b1b6fa4dc..b1b6fa4dc 100644
--- a/module/webui/themes/Flat/img/arrow_refresh.png
+++ b/pyload/webui/themes/Flat/img/arrow_refresh.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/arrow_right.png b/pyload/webui/themes/Flat/img/arrow_right.png
index 68f379fc7..68f379fc7 100644
--- a/module/webui/themes/Flat/img/arrow_right.png
+++ b/pyload/webui/themes/Flat/img/arrow_right.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/button.png b/pyload/webui/themes/Flat/img/button.png
index bb408a7d6..bb408a7d6 100644
--- a/module/webui/themes/Flat/img/button.png
+++ b/pyload/webui/themes/Flat/img/button.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/cog.png b/pyload/webui/themes/Flat/img/cog.png
index 833f779ac..833f779ac 100644
--- a/module/webui/themes/Flat/img/cog.png
+++ b/pyload/webui/themes/Flat/img/cog.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/control_add.png b/pyload/webui/themes/Flat/img/control_add.png
index e3f29fab2..e3f29fab2 100644
--- a/module/webui/themes/Flat/img/control_add.png
+++ b/pyload/webui/themes/Flat/img/control_add.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/control_add_blue.png b/pyload/webui/themes/Flat/img/control_add_blue.png
index e3f29fab2..e3f29fab2 100644
--- a/module/webui/themes/Flat/img/control_add_blue.png
+++ b/pyload/webui/themes/Flat/img/control_add_blue.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/control_cancel.png b/pyload/webui/themes/Flat/img/control_cancel.png
index 07c9cad30..07c9cad30 100644
--- a/module/webui/themes/Flat/img/control_cancel.png
+++ b/pyload/webui/themes/Flat/img/control_cancel.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/control_cancel_blue.png b/pyload/webui/themes/Flat/img/control_cancel_blue.png
index 07c9cad30..07c9cad30 100644
--- a/module/webui/themes/Flat/img/control_cancel_blue.png
+++ b/pyload/webui/themes/Flat/img/control_cancel_blue.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/control_pause.png b/pyload/webui/themes/Flat/img/control_pause.png
index 24e3705fa..24e3705fa 100644
--- a/module/webui/themes/Flat/img/control_pause.png
+++ b/pyload/webui/themes/Flat/img/control_pause.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/control_pause_blue.png b/pyload/webui/themes/Flat/img/control_pause_blue.png
index 24e3705fa..24e3705fa 100644
--- a/module/webui/themes/Flat/img/control_pause_blue.png
+++ b/pyload/webui/themes/Flat/img/control_pause_blue.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/control_play.png b/pyload/webui/themes/Flat/img/control_play.png
index 15ced1e21..15ced1e21 100644
--- a/module/webui/themes/Flat/img/control_play.png
+++ b/pyload/webui/themes/Flat/img/control_play.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/control_play_blue.png b/pyload/webui/themes/Flat/img/control_play_blue.png
index 15ced1e21..15ced1e21 100644
--- a/module/webui/themes/Flat/img/control_play_blue.png
+++ b/pyload/webui/themes/Flat/img/control_play_blue.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/control_stop.png b/pyload/webui/themes/Flat/img/control_stop.png
index 71215ef67..71215ef67 100644
--- a/module/webui/themes/Flat/img/control_stop.png
+++ b/pyload/webui/themes/Flat/img/control_stop.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/control_stop_blue.png b/pyload/webui/themes/Flat/img/control_stop_blue.png
index 71215ef67..71215ef67 100644
--- a/module/webui/themes/Flat/img/control_stop_blue.png
+++ b/pyload/webui/themes/Flat/img/control_stop_blue.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/add_folder.png b/pyload/webui/themes/Flat/img/default/add_folder.png
index 8acbc411b..8acbc411b 100644
--- a/module/webui/themes/Flat/img/default/add_folder.png
+++ b/pyload/webui/themes/Flat/img/default/add_folder.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/ajax-loader.gif b/pyload/webui/themes/Flat/img/default/ajax-loader.gif
index 2fd8e0737..2fd8e0737 100644
--- a/module/webui/themes/Flat/img/default/ajax-loader.gif
+++ b/pyload/webui/themes/Flat/img/default/ajax-loader.gif
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/big_button.gif b/pyload/webui/themes/Flat/img/default/big_button.gif
index 7680490ea..7680490ea 100644
--- a/module/webui/themes/Flat/img/default/big_button.gif
+++ b/pyload/webui/themes/Flat/img/default/big_button.gif
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/big_button_over.gif b/pyload/webui/themes/Flat/img/default/big_button_over.gif
index 2e3ee10d2..2e3ee10d2 100644
--- a/module/webui/themes/Flat/img/default/big_button_over.gif
+++ b/pyload/webui/themes/Flat/img/default/big_button_over.gif
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/body.png b/pyload/webui/themes/Flat/img/default/body.png
index 7ff1043e0..7ff1043e0 100644
--- a/module/webui/themes/Flat/img/default/body.png
+++ b/pyload/webui/themes/Flat/img/default/body.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/closebtn.gif b/pyload/webui/themes/Flat/img/default/closebtn.gif
index 3e27e6030..3e27e6030 100644
--- a/module/webui/themes/Flat/img/default/closebtn.gif
+++ b/pyload/webui/themes/Flat/img/default/closebtn.gif
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/drag_corner.gif b/pyload/webui/themes/Flat/img/default/drag_corner.gif
index befb1adf1..befb1adf1 100644
--- a/module/webui/themes/Flat/img/default/drag_corner.gif
+++ b/pyload/webui/themes/Flat/img/default/drag_corner.gif
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/full.png b/pyload/webui/themes/Flat/img/default/full.png
index fea52af76..fea52af76 100644
--- a/module/webui/themes/Flat/img/default/full.png
+++ b/pyload/webui/themes/Flat/img/default/full.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/head-menu-recent.png b/pyload/webui/themes/Flat/img/default/head-menu-recent.png
index fc9b0497f..fc9b0497f 100644
--- a/module/webui/themes/Flat/img/default/head-menu-recent.png
+++ b/pyload/webui/themes/Flat/img/default/head-menu-recent.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/head_bg1.png b/pyload/webui/themes/Flat/img/default/head_bg1.png
index f2848c3cc..f2848c3cc 100644
--- a/module/webui/themes/Flat/img/default/head_bg1.png
+++ b/pyload/webui/themes/Flat/img/default/head_bg1.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/images.png b/pyload/webui/themes/Flat/img/default/images.png
index 184860d1e..184860d1e 100644
--- a/module/webui/themes/Flat/img/default/images.png
+++ b/pyload/webui/themes/Flat/img/default/images.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/parseUri.png b/pyload/webui/themes/Flat/img/default/parseUri.png
index 937bded9d..937bded9d 100644
--- a/module/webui/themes/Flat/img/default/parseUri.png
+++ b/pyload/webui/themes/Flat/img/default/parseUri.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/pyload-logo.png b/pyload/webui/themes/Flat/img/default/pyload-logo.png
index 2443cd8b1..2443cd8b1 100644
--- a/module/webui/themes/Flat/img/default/pyload-logo.png
+++ b/pyload/webui/themes/Flat/img/default/pyload-logo.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/tab-background.png b/pyload/webui/themes/Flat/img/default/tab-background.png
index 29a5d1991..29a5d1991 100644
--- a/module/webui/themes/Flat/img/default/tab-background.png
+++ b/pyload/webui/themes/Flat/img/default/tab-background.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/default/tabs-border-bottom.png b/pyload/webui/themes/Flat/img/default/tabs-border-bottom.png
index 02440f428..02440f428 100644
--- a/module/webui/themes/Flat/img/default/tabs-border-bottom.png
+++ b/pyload/webui/themes/Flat/img/default/tabs-border-bottom.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/delete.png b/pyload/webui/themes/Flat/img/delete.png
index 4539cff12..4539cff12 100644
--- a/module/webui/themes/Flat/img/delete.png
+++ b/pyload/webui/themes/Flat/img/delete.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/error.png b/pyload/webui/themes/Flat/img/error.png
index 6c565c99c..6c565c99c 100644
--- a/module/webui/themes/Flat/img/error.png
+++ b/pyload/webui/themes/Flat/img/error.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/folder.png b/pyload/webui/themes/Flat/img/folder.png
index 0b067dd3c..0b067dd3c 100644
--- a/module/webui/themes/Flat/img/folder.png
+++ b/pyload/webui/themes/Flat/img/folder.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/head-login.png b/pyload/webui/themes/Flat/img/head-login.png
index 6b57515bc..6b57515bc 100644
--- a/module/webui/themes/Flat/img/head-login.png
+++ b/pyload/webui/themes/Flat/img/head-login.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/head-menu-collector.png b/pyload/webui/themes/Flat/img/head-menu-collector.png
index bbcbe6406..bbcbe6406 100644
--- a/module/webui/themes/Flat/img/head-menu-collector.png
+++ b/pyload/webui/themes/Flat/img/head-menu-collector.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/head-menu-config.png b/pyload/webui/themes/Flat/img/head-menu-config.png
index 93e8f83ac..93e8f83ac 100644
--- a/module/webui/themes/Flat/img/head-menu-config.png
+++ b/pyload/webui/themes/Flat/img/head-menu-config.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/head-menu-development.png b/pyload/webui/themes/Flat/img/head-menu-development.png
index 33d8b062f..33d8b062f 100644
--- a/module/webui/themes/Flat/img/head-menu-development.png
+++ b/pyload/webui/themes/Flat/img/head-menu-development.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/head-menu-download.png b/pyload/webui/themes/Flat/img/head-menu-download.png
index 3691deebc..3691deebc 100644
--- a/module/webui/themes/Flat/img/head-menu-download.png
+++ b/pyload/webui/themes/Flat/img/head-menu-download.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/head-menu-home.png b/pyload/webui/themes/Flat/img/head-menu-home.png
index b77bef5eb..b77bef5eb 100644
--- a/module/webui/themes/Flat/img/head-menu-home.png
+++ b/pyload/webui/themes/Flat/img/head-menu-home.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/head-menu-index.png b/pyload/webui/themes/Flat/img/head-menu-index.png
index 8bc6e9604..8bc6e9604 100644
--- a/module/webui/themes/Flat/img/head-menu-index.png
+++ b/pyload/webui/themes/Flat/img/head-menu-index.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/head-menu-news.png b/pyload/webui/themes/Flat/img/head-menu-news.png
index 44e79a9a9..44e79a9a9 100644
--- a/module/webui/themes/Flat/img/head-menu-news.png
+++ b/pyload/webui/themes/Flat/img/head-menu-news.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/head-menu-queue.png b/pyload/webui/themes/Flat/img/head-menu-queue.png
index e4fa41ad8..e4fa41ad8 100644
--- a/module/webui/themes/Flat/img/head-menu-queue.png
+++ b/pyload/webui/themes/Flat/img/head-menu-queue.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/head-menu-wiki.png b/pyload/webui/themes/Flat/img/head-menu-wiki.png
index 61b0e54ea..61b0e54ea 100644
--- a/module/webui/themes/Flat/img/head-menu-wiki.png
+++ b/pyload/webui/themes/Flat/img/head-menu-wiki.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/head-search-noshadow.png b/pyload/webui/themes/Flat/img/head-search-noshadow.png
index 16d39bd06..16d39bd06 100644
--- a/module/webui/themes/Flat/img/head-search-noshadow.png
+++ b/pyload/webui/themes/Flat/img/head-search-noshadow.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/notice.png b/pyload/webui/themes/Flat/img/notice.png
index a52b067cb..a52b067cb 100644
--- a/module/webui/themes/Flat/img/notice.png
+++ b/pyload/webui/themes/Flat/img/notice.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/package_go.png b/pyload/webui/themes/Flat/img/package_go.png
index 80b2c42ee..80b2c42ee 100644
--- a/module/webui/themes/Flat/img/package_go.png
+++ b/pyload/webui/themes/Flat/img/package_go.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/page-tools-backlinks.png b/pyload/webui/themes/Flat/img/page-tools-backlinks.png
index fb8f55b38..fb8f55b38 100644
--- a/module/webui/themes/Flat/img/page-tools-backlinks.png
+++ b/pyload/webui/themes/Flat/img/page-tools-backlinks.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/page-tools-edit.png b/pyload/webui/themes/Flat/img/page-tools-edit.png
index 67177cf89..67177cf89 100644
--- a/module/webui/themes/Flat/img/page-tools-edit.png
+++ b/pyload/webui/themes/Flat/img/page-tools-edit.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/page-tools-revisions.png b/pyload/webui/themes/Flat/img/page-tools-revisions.png
index 088fe0087..088fe0087 100644
--- a/module/webui/themes/Flat/img/page-tools-revisions.png
+++ b/pyload/webui/themes/Flat/img/page-tools-revisions.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/pencil.png b/pyload/webui/themes/Flat/img/pencil.png
index e39c93cd8..e39c93cd8 100644
--- a/module/webui/themes/Flat/img/pencil.png
+++ b/pyload/webui/themes/Flat/img/pencil.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/reconnect.png b/pyload/webui/themes/Flat/img/reconnect.png
index cd35c9325..cd35c9325 100644
--- a/module/webui/themes/Flat/img/reconnect.png
+++ b/pyload/webui/themes/Flat/img/reconnect.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/status_None.png b/pyload/webui/themes/Flat/img/status_None.png
index 1400d3eb3..1400d3eb3 100644
--- a/module/webui/themes/Flat/img/status_None.png
+++ b/pyload/webui/themes/Flat/img/status_None.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/status_downloading.png b/pyload/webui/themes/Flat/img/status_downloading.png
index db8ad8cd6..db8ad8cd6 100644
--- a/module/webui/themes/Flat/img/status_downloading.png
+++ b/pyload/webui/themes/Flat/img/status_downloading.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/status_failed.png b/pyload/webui/themes/Flat/img/status_failed.png
index 6c565c99c..6c565c99c 100644
--- a/module/webui/themes/Flat/img/status_failed.png
+++ b/pyload/webui/themes/Flat/img/status_failed.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/status_finished.png b/pyload/webui/themes/Flat/img/status_finished.png
index 2c4aca40d..2c4aca40d 100644
--- a/module/webui/themes/Flat/img/status_finished.png
+++ b/pyload/webui/themes/Flat/img/status_finished.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/status_offline.png b/pyload/webui/themes/Flat/img/status_offline.png
index 6c565c99c..6c565c99c 100644
--- a/module/webui/themes/Flat/img/status_offline.png
+++ b/pyload/webui/themes/Flat/img/status_offline.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/status_proc.png b/pyload/webui/themes/Flat/img/status_proc.png
index 833f779ac..833f779ac 100644
--- a/module/webui/themes/Flat/img/status_proc.png
+++ b/pyload/webui/themes/Flat/img/status_proc.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/status_queue.png b/pyload/webui/themes/Flat/img/status_queue.png
index 1400d3eb3..1400d3eb3 100644
--- a/module/webui/themes/Flat/img/status_queue.png
+++ b/pyload/webui/themes/Flat/img/status_queue.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/status_waiting.png b/pyload/webui/themes/Flat/img/status_waiting.png
index fd038175e..fd038175e 100644
--- a/module/webui/themes/Flat/img/status_waiting.png
+++ b/pyload/webui/themes/Flat/img/status_waiting.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/success.png b/pyload/webui/themes/Flat/img/success.png
index 2c4aca40d..2c4aca40d 100644
--- a/module/webui/themes/Flat/img/success.png
+++ b/pyload/webui/themes/Flat/img/success.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/user-actions-logout.png b/pyload/webui/themes/Flat/img/user-actions-logout.png
index d4ef360e8..d4ef360e8 100644
--- a/module/webui/themes/Flat/img/user-actions-logout.png
+++ b/pyload/webui/themes/Flat/img/user-actions-logout.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/user-actions-profile.png b/pyload/webui/themes/Flat/img/user-actions-profile.png
index 9ec410b13..9ec410b13 100644
--- a/module/webui/themes/Flat/img/user-actions-profile.png
+++ b/pyload/webui/themes/Flat/img/user-actions-profile.png
Binary files differ
diff --git a/module/webui/themes/Flat/img/user-info.png b/pyload/webui/themes/Flat/img/user-info.png
index 345ed52e4..345ed52e4 100644
--- a/module/webui/themes/Flat/img/user-info.png
+++ b/pyload/webui/themes/Flat/img/user-info.png
Binary files differ
diff --git a/module/webui/themes/Flat/js/render/admin.coffee b/pyload/webui/themes/Flat/js/render/admin.coffee
index 5afbcbb66..5afbcbb66 100644
--- a/module/webui/themes/Flat/js/render/admin.coffee
+++ b/pyload/webui/themes/Flat/js/render/admin.coffee
diff --git a/module/webui/themes/Flat/js/render/admin.min.js b/pyload/webui/themes/Flat/js/render/admin.min.js
index 94a5e494d..94a5e494d 100644
--- a/module/webui/themes/Flat/js/render/admin.min.js
+++ b/pyload/webui/themes/Flat/js/render/admin.min.js
diff --git a/module/webui/themes/Flat/js/render/base.coffee b/pyload/webui/themes/Flat/js/render/base.coffee
index 07b8bfb6f..07b8bfb6f 100644
--- a/module/webui/themes/Flat/js/render/base.coffee
+++ b/pyload/webui/themes/Flat/js/render/base.coffee
diff --git a/module/webui/themes/Flat/js/render/base.min.js b/pyload/webui/themes/Flat/js/render/base.min.js
index 1ba1d73f9..1ba1d73f9 100644
--- a/module/webui/themes/Flat/js/render/base.min.js
+++ b/pyload/webui/themes/Flat/js/render/base.min.js
diff --git a/module/webui/themes/Flat/js/render/filemanager.js b/pyload/webui/themes/Flat/js/render/filemanager.js
index ab9b8b492..ab9b8b492 100644
--- a/module/webui/themes/Flat/js/render/filemanager.js
+++ b/pyload/webui/themes/Flat/js/render/filemanager.js
diff --git a/module/webui/themes/Flat/js/render/package.js b/pyload/webui/themes/Flat/js/render/package.js
index 659a8e6fc..659a8e6fc 100644
--- a/module/webui/themes/Flat/js/render/package.js
+++ b/pyload/webui/themes/Flat/js/render/package.js
diff --git a/module/webui/themes/Flat/js/render/settings.coffee b/pyload/webui/themes/Flat/js/render/settings.coffee
index d522741b9..d522741b9 100644
--- a/module/webui/themes/Flat/js/render/settings.coffee
+++ b/pyload/webui/themes/Flat/js/render/settings.coffee
diff --git a/module/webui/themes/Flat/js/render/settings.min.js b/pyload/webui/themes/Flat/js/render/settings.min.js
index 41d1cb25a..41d1cb25a 100644
--- a/module/webui/themes/Flat/js/render/settings.min.js
+++ b/pyload/webui/themes/Flat/js/render/settings.min.js
diff --git a/module/webui/themes/Flat/js/static/MooDialog.js b/pyload/webui/themes/Flat/js/static/MooDialog.js
index 45a52496f..45a52496f 100644
--- a/module/webui/themes/Flat/js/static/MooDialog.js
+++ b/pyload/webui/themes/Flat/js/static/MooDialog.js
diff --git a/module/webui/themes/Flat/js/static/MooDialog.min.js b/pyload/webui/themes/Flat/js/static/MooDialog.min.js
index 90b3ae100..90b3ae100 100644
--- a/module/webui/themes/Flat/js/static/MooDialog.min.js
+++ b/pyload/webui/themes/Flat/js/static/MooDialog.min.js
diff --git a/module/webui/themes/Flat/js/static/MooDropMenu.js b/pyload/webui/themes/Flat/js/static/MooDropMenu.js
index ac0fa1874..ac0fa1874 100644
--- a/module/webui/themes/Flat/js/static/MooDropMenu.js
+++ b/pyload/webui/themes/Flat/js/static/MooDropMenu.js
diff --git a/module/webui/themes/Flat/js/static/MooDropMenu.min.js b/pyload/webui/themes/Flat/js/static/MooDropMenu.min.js
index 552ae247a..552ae247a 100644
--- a/module/webui/themes/Flat/js/static/MooDropMenu.min.js
+++ b/pyload/webui/themes/Flat/js/static/MooDropMenu.min.js
diff --git a/module/webui/themes/Flat/js/static/mootools-core.js b/pyload/webui/themes/Flat/js/static/mootools-core.js
index db83850fd..db83850fd 100644
--- a/module/webui/themes/Flat/js/static/mootools-core.js
+++ b/pyload/webui/themes/Flat/js/static/mootools-core.js
diff --git a/module/webui/themes/Flat/js/static/mootools-core.min.js b/pyload/webui/themes/Flat/js/static/mootools-core.min.js
index 354f94196..354f94196 100644
--- a/module/webui/themes/Flat/js/static/mootools-core.min.js
+++ b/pyload/webui/themes/Flat/js/static/mootools-core.min.js
diff --git a/module/webui/themes/Flat/js/static/mootools-more.js b/pyload/webui/themes/Flat/js/static/mootools-more.js
index c7f4a1a0e..c7f4a1a0e 100644
--- a/module/webui/themes/Flat/js/static/mootools-more.js
+++ b/pyload/webui/themes/Flat/js/static/mootools-more.js
diff --git a/module/webui/themes/Flat/js/static/mootools-more.min.js b/pyload/webui/themes/Flat/js/static/mootools-more.min.js
index ce03a60fd..ce03a60fd 100644
--- a/module/webui/themes/Flat/js/static/mootools-more.min.js
+++ b/pyload/webui/themes/Flat/js/static/mootools-more.min.js
diff --git a/module/webui/themes/Flat/js/static/purr.js b/pyload/webui/themes/Flat/js/static/purr.js
index 9cbc503d9..9cbc503d9 100644
--- a/module/webui/themes/Flat/js/static/purr.js
+++ b/pyload/webui/themes/Flat/js/static/purr.js
diff --git a/module/webui/themes/Flat/js/static/purr.min.js b/pyload/webui/themes/Flat/js/static/purr.min.js
index bf70e357d..bf70e357d 100644
--- a/module/webui/themes/Flat/js/static/purr.min.js
+++ b/pyload/webui/themes/Flat/js/static/purr.min.js
diff --git a/module/webui/themes/Flat/js/static/tinytab.js b/pyload/webui/themes/Flat/js/static/tinytab.js
index de50279fc..de50279fc 100644
--- a/module/webui/themes/Flat/js/static/tinytab.js
+++ b/pyload/webui/themes/Flat/js/static/tinytab.js
diff --git a/module/webui/themes/Flat/js/static/tinytab.min.js b/pyload/webui/themes/Flat/js/static/tinytab.min.js
index 2f4fa0436..2f4fa0436 100644
--- a/module/webui/themes/Flat/js/static/tinytab.min.js
+++ b/pyload/webui/themes/Flat/js/static/tinytab.min.js
diff --git a/module/webui/themes/Flat/tml/admin.html b/pyload/webui/themes/Flat/tml/admin.html
index eb87666ff..eb87666ff 100644
--- a/module/webui/themes/Flat/tml/admin.html
+++ b/pyload/webui/themes/Flat/tml/admin.html
diff --git a/module/webui/themes/Flat/tml/base.html b/pyload/webui/themes/Flat/tml/base.html
index 4473ee5e2..4473ee5e2 100644
--- a/module/webui/themes/Flat/tml/base.html
+++ b/pyload/webui/themes/Flat/tml/base.html
diff --git a/module/webui/themes/Flat/tml/captcha.html b/pyload/webui/themes/Flat/tml/captcha.html
index 731d97d11..731d97d11 100644
--- a/module/webui/themes/Flat/tml/captcha.html
+++ b/pyload/webui/themes/Flat/tml/captcha.html
diff --git a/module/webui/themes/Flat/tml/downloads.html b/pyload/webui/themes/Flat/tml/downloads.html
index 4b9ae7baf..4b9ae7baf 100644
--- a/module/webui/themes/Flat/tml/downloads.html
+++ b/pyload/webui/themes/Flat/tml/downloads.html
diff --git a/module/webui/themes/Flat/tml/filemanager.html b/pyload/webui/themes/Flat/tml/filemanager.html
index 4dbbd288c..4dbbd288c 100644
--- a/module/webui/themes/Flat/tml/filemanager.html
+++ b/pyload/webui/themes/Flat/tml/filemanager.html
diff --git a/module/webui/themes/Flat/tml/folder.html b/pyload/webui/themes/Flat/tml/folder.html
index a0d1dcec9..a0d1dcec9 100644
--- a/module/webui/themes/Flat/tml/folder.html
+++ b/pyload/webui/themes/Flat/tml/folder.html
diff --git a/module/webui/themes/Flat/tml/home.html b/pyload/webui/themes/Flat/tml/home.html
index ec7f4aae2..ec7f4aae2 100644
--- a/module/webui/themes/Flat/tml/home.html
+++ b/pyload/webui/themes/Flat/tml/home.html
diff --git a/module/webui/themes/Flat/tml/info.html b/pyload/webui/themes/Flat/tml/info.html
index a650afc5a..a650afc5a 100644
--- a/module/webui/themes/Flat/tml/info.html
+++ b/pyload/webui/themes/Flat/tml/info.html
diff --git a/module/webui/themes/Flat/tml/login.html b/pyload/webui/themes/Flat/tml/login.html
index 64ed28426..64ed28426 100644
--- a/module/webui/themes/Flat/tml/login.html
+++ b/pyload/webui/themes/Flat/tml/login.html
diff --git a/module/webui/themes/Flat/tml/logout.html b/pyload/webui/themes/Flat/tml/logout.html
index f91b16914..f91b16914 100644
--- a/module/webui/themes/Flat/tml/logout.html
+++ b/pyload/webui/themes/Flat/tml/logout.html
diff --git a/module/webui/themes/Flat/tml/logs.html b/pyload/webui/themes/Flat/tml/logs.html
index eada9ad3f..eada9ad3f 100644
--- a/module/webui/themes/Flat/tml/logs.html
+++ b/pyload/webui/themes/Flat/tml/logs.html
diff --git a/module/webui/themes/Flat/tml/pathchooser.html b/pyload/webui/themes/Flat/tml/pathchooser.html
index 5ad1fd6d7..5ad1fd6d7 100644
--- a/module/webui/themes/Flat/tml/pathchooser.html
+++ b/pyload/webui/themes/Flat/tml/pathchooser.html
diff --git a/module/webui/themes/Flat/tml/queue.html b/pyload/webui/themes/Flat/tml/queue.html
index 80e6c864c..80e6c864c 100644
--- a/module/webui/themes/Flat/tml/queue.html
+++ b/pyload/webui/themes/Flat/tml/queue.html
diff --git a/module/webui/themes/Flat/tml/settings.html b/pyload/webui/themes/Flat/tml/settings.html
index 8a8e54b0f..8a8e54b0f 100644
--- a/module/webui/themes/Flat/tml/settings.html
+++ b/pyload/webui/themes/Flat/tml/settings.html
diff --git a/module/webui/themes/Flat/tml/settings_item.html b/pyload/webui/themes/Flat/tml/settings_item.html
index 813383343..813383343 100644
--- a/module/webui/themes/Flat/tml/settings_item.html
+++ b/pyload/webui/themes/Flat/tml/settings_item.html
diff --git a/module/webui/themes/Flat/tml/window.html b/pyload/webui/themes/Flat/tml/window.html
index ea5d65e46..ea5d65e46 100644
--- a/module/webui/themes/Flat/tml/window.html
+++ b/pyload/webui/themes/Flat/tml/window.html