diff options
| author | 2015-02-16 21:59:10 +0100 | |
|---|---|---|
| committer | 2015-02-16 21:59:10 +0100 | |
| commit | 8e7d14bae4d3c836f029a1235eb227380acc3f75 (patch) | |
| tree | ebd0679642cccb994e70a89a106b394189cb28bc | |
| parent | Merge branch 'stable' into 0.4.10 (diff) | |
| download | pyload-8e7d14bae4d3c836f029a1235eb227380acc3f75.tar.xz | |
Fix plugins to work on 0.4.10
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | module/database/File.py | 875 | ||||
| -rw-r--r-- | module/plugins/Addon.py | 185 | ||||
| -rw-r--r-- | module/plugins/Captcha.py | 51 | ||||
| -rw-r--r-- | module/plugins/OCR.py | 318 | ||||
| -rw-r--r-- | module/plugins/accounts/BackinNet.py | 16 | ||||
| -rw-r--r-- | module/plugins/accounts/CloudzillaTo.py | 37 | ||||
| -rw-r--r-- | module/plugins/accounts/DropboxCom.py | 38 | ||||
| -rw-r--r-- | module/plugins/accounts/ExashareCom.py | 16 | ||||
| -rw-r--r-- | module/plugins/accounts/JunkyvideoCom.py | 16 | ||||
| -rw-r--r-- | module/plugins/accounts/MultihostersCom.py | 16 | ||||
| -rw-r--r-- | module/plugins/accounts/NoPremiumPl.py | 81 | ||||
| -rw-r--r-- | module/plugins/accounts/PutdriveCom.py | 16 | ||||
| -rw-r--r-- | module/plugins/accounts/RapideoPl.py | 80 | ||||
| -rw-r--r-- | module/plugins/accounts/RapiduNet.py | 66 | ||||
| -rw-r--r-- | module/plugins/accounts/SmoozedCom.py | 62 | ||||
| -rw-r--r-- | module/plugins/accounts/UploadableCh.py | 34 | ||||
| -rw-r--r-- | module/plugins/accounts/WebshareCz.py | 68 | ||||
| -rw-r--r-- | module/plugins/addon/ClickAndLoad.py | 74 | ||||
| -rw-r--r-- | module/plugins/addon/ExtractArchive.py | 509 | ||||
| -rw-r--r-- | module/plugins/addon/MergeFiles.py | 85 | ||||
| -rw-r--r-- | module/plugins/addon/SkipRev.py | 98 | ||||
| -rw-r--r-- | module/plugins/addon/UnSkipOnFail.py | 95 | ||||
| -rw-r--r-- | module/plugins/addon/UpdateManager.py | 306 | ||||
| -rw-r--r-- | module/plugins/captcha/AdYouLike.py | 107 | ||||
| -rw-r--r-- | module/plugins/captcha/AdsCaptcha.py | 77 | ||||
| -rw-r--r-- | module/plugins/captcha/ReCaptcha.py | 73 | ||||
| -rw-r--r-- | module/plugins/captcha/SolveMedia.py | 50 | ||||
| -rw-r--r-- | module/plugins/container/CCF.py | 49 | ||||
| -rw-r--r-- | module/plugins/container/DLC.py | 72 | ||||
| -rw-r--r-- | module/plugins/container/LinkList.py | 69 | ||||
| -rw-r--r-- | module/plugins/container/RSDF.py | 52 | ||||
| -rw-r--r-- | module/plugins/crypter/BitshareCom.py | 24 | ||||
| -rw-r--r-- | module/plugins/crypter/C1NeonCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/CloudzillaToFolder.py | 39 | ||||
| -rw-r--r-- | module/plugins/crypter/CrockoCom.py | 23 | ||||
| -rw-r--r-- | module/plugins/crypter/CryptItCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/DataHu.py | 43 | ||||
| -rw-r--r-- | module/plugins/crypter/DdlstorageCom.py | 20 | ||||
| -rw-r--r-- | module/plugins/crypter/DepositfilesCom.py | 23 | ||||
| -rw-r--r-- | module/plugins/crypter/Dereferer.py | 17 | ||||
| -rw-r--r-- | module/plugins/crypter/DevhostStFolder.py | 57 | ||||
| -rw-r--r-- | module/plugins/crypter/DlProtectCom.py | 68 | ||||
| -rw-r--r-- | module/plugins/crypter/DontKnowMe.py | 17 | ||||
| -rw-r--r-- | module/plugins/crypter/DuploadOrg.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/EasybytezCom.py | 23 | ||||
| -rw-r--r-- | module/plugins/crypter/FilebeerInfo.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/FilecloudIo.py | 24 | ||||
| -rw-r--r-- | module/plugins/crypter/FilecryptCc.py | 182 | ||||
| -rw-r--r-- | module/plugins/crypter/FilefactoryCom.py | 31 | ||||
| -rw-r--r-- | module/plugins/crypter/FilerNet.py | 27 | ||||
| -rw-r--r-- | module/plugins/crypter/FilesonicCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/crypter/FilestubeCom.py | 24 | ||||
| -rw-r--r-- | module/plugins/crypter/FiletramCom.py | 25 | ||||
| -rw-r--r-- | module/plugins/crypter/FiredriveCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/FreakhareCom.py | 41 | ||||
| -rw-r--r-- | module/plugins/crypter/FreetexthostCom.py | 30 | ||||
| -rw-r--r-- | module/plugins/crypter/FshareVn.py | 23 | ||||
| -rw-r--r-- | module/plugins/crypter/Go4UpCom.py | 49 | ||||
| -rw-r--r-- | module/plugins/crypter/HotfileCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/ILoadTo.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/ImgurComAlbum.py | 30 | ||||
| -rw-r--r-- | module/plugins/crypter/LinkSaveIn.py | 22 | ||||
| -rw-r--r-- | module/plugins/crypter/LofCc.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/MBLinkInfo.py | 20 | ||||
| -rw-r--r-- | module/plugins/crypter/MegaCoNzFolder.py | 32 | ||||
| -rw-r--r-- | module/plugins/crypter/MegaRapidCz.py | 23 | ||||
| -rw-r--r-- | module/plugins/crypter/MegauploadCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/crypter/Movie2KTo.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/MultiUpOrg.py | 41 | ||||
| -rw-r--r-- | module/plugins/crypter/MultiuploadCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/crypter/NetfolderIn.py | 73 | ||||
| -rw-r--r-- | module/plugins/crypter/NosvideoCom.py | 24 | ||||
| -rw-r--r-- | module/plugins/crypter/OronCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/PastebinCom.py | 24 | ||||
| -rw-r--r-- | module/plugins/crypter/RSLayerCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/RelinkUs.py | 293 | ||||
| -rw-r--r-- | module/plugins/crypter/SecuredIn.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/SharingmatrixCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/crypter/SpeedLoadOrg.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/StealthTo.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/TnyCz.py | 30 | ||||
| -rw-r--r-- | module/plugins/crypter/TrailerzoneInfo.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/TurbobitNet.py | 47 | ||||
| -rw-r--r-- | module/plugins/crypter/TusfilesNet.py | 46 | ||||
| -rw-r--r-- | module/plugins/crypter/UploadableCh.py | 27 | ||||
| -rw-r--r-- | module/plugins/crypter/UploadedTo.py | 37 | ||||
| -rw-r--r-- | module/plugins/crypter/WiiReloadedOrg.py | 19 | ||||
| -rw-r--r-- | module/plugins/crypter/WuploadCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/crypter/XFileSharingPro.py | 55 | ||||
| -rw-r--r-- | module/plugins/hooks/AlldebridCom.py | 29 | ||||
| -rw-r--r-- | module/plugins/hooks/AndroidPhoneNotify.py | 80 | ||||
| -rw-r--r-- | module/plugins/hooks/BypassCaptcha.py | 135 | ||||
| -rw-r--r-- | module/plugins/hooks/Captcha9Kw.py | 251 | ||||
| -rw-r--r-- | module/plugins/hooks/CaptchaBrotherhood.py | 167 | ||||
| -rw-r--r-- | module/plugins/hooks/ClickAndLoad.py | 124 | ||||
| -rw-r--r-- | module/plugins/hooks/DeathByCaptcha.py | 214 | ||||
| -rw-r--r-- | module/plugins/hooks/DebridItaliaCom.py | 28 | ||||
| -rw-r--r-- | module/plugins/hooks/EasybytezCom.py | 32 | ||||
| -rw-r--r-- | module/plugins/hooks/ExpertDecoders.py | 96 | ||||
| -rw-r--r-- | module/plugins/hooks/FastixRu.py | 31 | ||||
| -rw-r--r-- | module/plugins/hooks/FreeWayMe.py | 27 | ||||
| -rw-r--r-- | module/plugins/hooks/ImageTyperz.py | 153 | ||||
| -rw-r--r-- | module/plugins/hooks/JustPremium.py | 46 | ||||
| -rw-r--r-- | module/plugins/hooks/LinkdecrypterCom.py | 25 | ||||
| -rw-r--r-- | module/plugins/hooks/LinksnappyCom.py | 29 | ||||
| -rw-r--r-- | module/plugins/hooks/MegaDebridEu.py | 35 | ||||
| -rw-r--r-- | module/plugins/hooks/MultihostersCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hooks/MultishareCz.py | 31 | ||||
| -rw-r--r-- | module/plugins/hooks/MyfastfileCom.py | 30 | ||||
| -rw-r--r-- | module/plugins/hooks/NoPremiumPl.py | 31 | ||||
| -rw-r--r-- | module/plugins/hooks/OverLoadMe.py | 31 | ||||
| -rw-r--r-- | module/plugins/hooks/PremiumTo.py | 29 | ||||
| -rw-r--r-- | module/plugins/hooks/PremiumizeMe.py | 40 | ||||
| -rw-r--r-- | module/plugins/hooks/PutdriveCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hooks/RPNetBiz.py | 38 | ||||
| -rw-r--r-- | module/plugins/hooks/RapideoPl.py | 31 | ||||
| -rw-r--r-- | module/plugins/hooks/RealdebridCom.py | 29 | ||||
| -rw-r--r-- | module/plugins/hooks/RehostTo.py | 29 | ||||
| -rw-r--r-- | module/plugins/hooks/SimplyPremiumCom.py | 31 | ||||
| -rw-r--r-- | module/plugins/hooks/SimplydebridCom.py | 26 | ||||
| -rw-r--r-- | module/plugins/hooks/SmoozedCom.py | 26 | ||||
| -rw-r--r-- | module/plugins/hooks/UnrestrictLi.py | 30 | ||||
| -rw-r--r-- | module/plugins/hooks/WindowsPhoneNotify.py | 96 | ||||
| -rw-r--r-- | module/plugins/hooks/XFileSharingPro.py | 110 | ||||
| -rw-r--r-- | module/plugins/hooks/ZeveraCom.py | 27 | ||||
| -rw-r--r-- | module/plugins/hoster/AlldebridCom.py | 78 | ||||
| -rw-r--r-- | module/plugins/hoster/AndroidfilehostCom.py | 63 | ||||
| -rw-r--r-- | module/plugins/hoster/BasketbuildCom.py | 61 | ||||
| -rw-r--r-- | module/plugins/hoster/BayfilesCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/BezvadataCz.py | 94 | ||||
| -rw-r--r-- | module/plugins/hoster/BillionuploadsCom.py | 22 | ||||
| -rw-r--r-- | module/plugins/hoster/BitshareCom.py | 158 | ||||
| -rw-r--r-- | module/plugins/hoster/BoltsharingCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/CatShareNet.py | 62 | ||||
| -rw-r--r-- | module/plugins/hoster/CloudzerNet.py | 20 | ||||
| -rw-r--r-- | module/plugins/hoster/CloudzillaTo.py | 61 | ||||
| -rw-r--r-- | module/plugins/hoster/CramitIn.py | 23 | ||||
| -rw-r--r-- | module/plugins/hoster/CrockoCom.py | 66 | ||||
| -rw-r--r-- | module/plugins/hoster/CyberlockerCh.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/CzshareCom.py | 161 | ||||
| -rw-r--r-- | module/plugins/hoster/DataHu.py | 34 | ||||
| -rw-r--r-- | module/plugins/hoster/DataportCz.py | 57 | ||||
| -rw-r--r-- | module/plugins/hoster/DateiTo.py | 82 | ||||
| -rw-r--r-- | module/plugins/hoster/DdlstorageCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/hoster/DebridItaliaCom.py | 43 | ||||
| -rw-r--r-- | module/plugins/hoster/DepositfilesCom.py | 115 | ||||
| -rw-r--r-- | module/plugins/hoster/DevhostSt.py | 36 | ||||
| -rw-r--r-- | module/plugins/hoster/DlFreeFr.py | 140 | ||||
| -rw-r--r-- | module/plugins/hoster/DodanePl.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/DuploadOrg.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/EasybytezCom.py | 24 | ||||
| -rw-r--r-- | module/plugins/hoster/EdiskCz.py | 56 | ||||
| -rw-r--r-- | module/plugins/hoster/EgoFilesCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/EnteruploadCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/EpicShareNet.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/EuroshareEu.py | 67 | ||||
| -rw-r--r-- | module/plugins/hoster/ExashareCom.py | 38 | ||||
| -rw-r--r-- | module/plugins/hoster/ExtabitCom.py | 78 | ||||
| -rw-r--r-- | module/plugins/hoster/FastixRu.py | 66 | ||||
| -rw-r--r-- | module/plugins/hoster/FastshareCz.py | 79 | ||||
| -rw-r--r-- | module/plugins/hoster/FileApeCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/FileSharkPl.py | 133 | ||||
| -rw-r--r-- | module/plugins/hoster/FileStoreTo.py | 37 | ||||
| -rw-r--r-- | module/plugins/hoster/FilebeerInfo.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/FilecloudIo.py | 126 | ||||
| -rw-r--r-- | module/plugins/hoster/FileomCom.py | 33 | ||||
| -rw-r--r-- | module/plugins/hoster/FilepostCom.py | 133 | ||||
| -rw-r--r-- | module/plugins/hoster/FilepupNet.py | 47 | ||||
| -rw-r--r-- | module/plugins/hoster/FilerNet.py | 74 | ||||
| -rw-r--r-- | module/plugins/hoster/FilerioCom.py | 23 | ||||
| -rw-r--r-- | module/plugins/hoster/FileserveCom.py | 216 | ||||
| -rw-r--r-- | module/plugins/hoster/FileshareInUa.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/FilesonicCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/hoster/FilezyNet.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/FiredriveCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/FourSharedCom.py | 62 | ||||
| -rw-r--r-- | module/plugins/hoster/FreakshareCom.py | 180 | ||||
| -rw-r--r-- | module/plugins/hoster/FreeWayMe.py | 53 | ||||
| -rw-r--r-- | module/plugins/hoster/FreevideoCz.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/GigapetaCom.py | 64 | ||||
| -rw-r--r-- | module/plugins/hoster/GooIm.py | 37 | ||||
| -rw-r--r-- | module/plugins/hoster/GoogledriveCom.py | 65 | ||||
| -rw-r--r-- | module/plugins/hoster/HellshareCz.py | 35 | ||||
| -rw-r--r-- | module/plugins/hoster/HellspyCz.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/HotfileCom.py | 21 | ||||
| -rw-r--r-- | module/plugins/hoster/HugefilesNet.py | 25 | ||||
| -rw-r--r-- | module/plugins/hoster/HundredEightyUploadCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/hoster/IFileWs.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/IcyFilesCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/IfileIt.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/IfolderRu.py | 76 | ||||
| -rw-r--r-- | module/plugins/hoster/JumbofilesCom.py | 36 | ||||
| -rw-r--r-- | module/plugins/hoster/JunocloudMe.py | 24 | ||||
| -rw-r--r-- | module/plugins/hoster/Keep2ShareCc.py | 112 | ||||
| -rw-r--r-- | module/plugins/hoster/KickloadCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/KingfilesNet.py | 78 | ||||
| -rw-r--r-- | module/plugins/hoster/LemUploadsCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/LetitbitNet.py | 155 | ||||
| -rw-r--r-- | module/plugins/hoster/LinksnappyCom.py | 58 | ||||
| -rw-r--r-- | module/plugins/hoster/LoadTo.py | 68 | ||||
| -rw-r--r-- | module/plugins/hoster/LomafileCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/hoster/LuckyShareNet.py | 74 | ||||
| -rw-r--r-- | module/plugins/hoster/MegaCoNz.py | 217 | ||||
| -rw-r--r-- | module/plugins/hoster/MegaDebridEu.py | 89 | ||||
| -rw-r--r-- | module/plugins/hoster/MegaFilesSe.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/MegaRapidCz.py | 65 | ||||
| -rw-r--r-- | module/plugins/hoster/MegareleaseOrg.py | 19 | ||||
| -rw-r--r-- | module/plugins/hoster/MegasharesCom.py | 113 | ||||
| -rw-r--r-- | module/plugins/hoster/MegauploadCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/MegavideoCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/hoster/MovReelCom.py | 21 | ||||
| -rw-r--r-- | module/plugins/hoster/MultihostersCom.py | 15 | ||||
| -rw-r--r-- | module/plugins/hoster/MultishareCz.py | 54 | ||||
| -rw-r--r-- | module/plugins/hoster/MyfastfileCom.py | 39 | ||||
| -rw-r--r-- | module/plugins/hoster/MystoreTo.py | 45 | ||||
| -rw-r--r-- | module/plugins/hoster/NahrajCz.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/NarodRu.py | 66 | ||||
| -rw-r--r-- | module/plugins/hoster/NitroflareCom.py | 107 | ||||
| -rw-r--r-- | module/plugins/hoster/NoPremiumPl.py | 103 | ||||
| -rw-r--r-- | module/plugins/hoster/NosuploadCom.py | 42 | ||||
| -rw-r--r-- | module/plugins/hoster/NovafileCom.py | 29 | ||||
| -rw-r--r-- | module/plugins/hoster/NowDownloadSx.py | 64 | ||||
| -rw-r--r-- | module/plugins/hoster/NowVideoSx.py | 44 | ||||
| -rw-r--r-- | module/plugins/hoster/OneFichierCom.py | 61 | ||||
| -rw-r--r-- | module/plugins/hoster/OronCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/hoster/OverLoadMe.py | 76 | ||||
| -rw-r--r-- | module/plugins/hoster/PandaplaNet.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/PotloadCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/PremiumTo.py | 55 | ||||
| -rw-r--r-- | module/plugins/hoster/PremiumizeMe.py | 60 | ||||
| -rw-r--r-- | module/plugins/hoster/PromptfileCom.py | 45 | ||||
| -rw-r--r-- | module/plugins/hoster/PrzeklejPl.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/PutdriveCom.py | 15 | ||||
| -rw-r--r-- | module/plugins/hoster/QuickshareCz.py | 89 | ||||
| -rw-r--r-- | module/plugins/hoster/RPNetBiz.py | 80 | ||||
| -rw-r--r-- | module/plugins/hoster/RapideoPl.py | 103 | ||||
| -rw-r--r-- | module/plugins/hoster/RapidfileshareNet.py | 25 | ||||
| -rw-r--r-- | module/plugins/hoster/RapidgatorNet.py | 172 | ||||
| -rw-r--r-- | module/plugins/hoster/RapiduNet.py | 86 | ||||
| -rw-r--r-- | module/plugins/hoster/RarefileNet.py | 23 | ||||
| -rw-r--r-- | module/plugins/hoster/RealdebridCom.py | 79 | ||||
| -rw-r--r-- | module/plugins/hoster/RehostTo.py | 28 | ||||
| -rw-r--r-- | module/plugins/hoster/RemixshareCom.py | 60 | ||||
| -rw-r--r-- | module/plugins/hoster/RgHostNet.py | 26 | ||||
| -rw-r--r-- | module/plugins/hoster/SafesharingEu.py | 21 | ||||
| -rw-r--r-- | module/plugins/hoster/SecureUploadEu.py | 21 | ||||
| -rw-r--r-- | module/plugins/hoster/SendspaceCom.py | 61 | ||||
| -rw-r--r-- | module/plugins/hoster/Share4WebCom.py | 22 | ||||
| -rw-r--r-- | module/plugins/hoster/Share76Com.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/ShareFilesCo.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/SharebeesCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/ShareonlineBiz.py | 187 | ||||
| -rw-r--r-- | module/plugins/hoster/SharingmatrixCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/hoster/ShragleCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/hoster/SimplyPremiumCom.py | 81 | ||||
| -rw-r--r-- | module/plugins/hoster/SimplydebridCom.py | 48 | ||||
| -rw-r--r-- | module/plugins/hoster/SmoozedCom.py | 63 | ||||
| -rw-r--r-- | module/plugins/hoster/SockshareCom.py | 20 | ||||
| -rw-r--r-- | module/plugins/hoster/SpeedLoadOrg.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/SpeedfileCz.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/SpeedyshareCom.py | 44 | ||||
| -rw-r--r-- | module/plugins/hoster/StorageTo.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/StreamcloudEu.py | 31 | ||||
| -rw-r--r-- | module/plugins/hoster/TurbobitNet.py | 167 | ||||
| -rw-r--r-- | module/plugins/hoster/TurbouploadCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/TusfilesNet.py | 40 | ||||
| -rw-r--r-- | module/plugins/hoster/TwoSharedCom.py | 32 | ||||
| -rw-r--r-- | module/plugins/hoster/UlozTo.py | 158 | ||||
| -rw-r--r-- | module/plugins/hoster/UloziskoSk.py | 71 | ||||
| -rw-r--r-- | module/plugins/hoster/UnibytesCom.py | 73 | ||||
| -rw-r--r-- | module/plugins/hoster/UnrestrictLi.py | 85 | ||||
| -rw-r--r-- | module/plugins/hoster/UpleaCom.py | 59 | ||||
| -rw-r--r-- | module/plugins/hoster/UploadStationCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/hoster/UploadableCh.py | 79 | ||||
| -rw-r--r-- | module/plugins/hoster/UploadboxCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/UploadedTo.py | 120 | ||||
| -rw-r--r-- | module/plugins/hoster/UploadhereCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/UploadheroCom.py | 76 | ||||
| -rw-r--r-- | module/plugins/hoster/UploadingCom.py | 99 | ||||
| -rw-r--r-- | module/plugins/hoster/UploadkingCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/UpstoreNet.py | 72 | ||||
| -rw-r--r-- | module/plugins/hoster/UptoboxCom.py | 32 | ||||
| -rw-r--r-- | module/plugins/hoster/VeohCom.py | 54 | ||||
| -rw-r--r-- | module/plugins/hoster/VidPlayNet.py | 24 | ||||
| -rw-r--r-- | module/plugins/hoster/VimeoCom.py | 74 | ||||
| -rw-r--r-- | module/plugins/hoster/Vipleech4UCom.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/WarserverCz.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/WebshareCz.py | 63 | ||||
| -rw-r--r-- | module/plugins/hoster/WrzucTo.py | 52 | ||||
| -rw-r--r-- | module/plugins/hoster/WuploadCom.py | 19 | ||||
| -rw-r--r-- | module/plugins/hoster/X7To.py | 18 | ||||
| -rw-r--r-- | module/plugins/hoster/XFileSharingPro.py | 62 | ||||
| -rw-r--r-- | module/plugins/hoster/XdadevelopersCom.py | 38 | ||||
| -rw-r--r-- | module/plugins/hoster/YibaishiwuCom.py | 59 | ||||
| -rw-r--r-- | module/plugins/hoster/ZShareNet.py | 19 | ||||
| -rw-r--r-- | module/plugins/hoster/ZeveraCom.py | 34 | ||||
| -rw-r--r-- | module/plugins/hoster/ZippyshareCom.py | 65 | ||||
| -rw-r--r-- | module/plugins/internal/BasePlugin.py | 95 | ||||
| -rw-r--r-- | module/plugins/internal/CaptchaService.py | 522 | ||||
| -rw-r--r-- | module/plugins/internal/DeadCrypter.py | 31 | ||||
| -rw-r--r-- | module/plugins/internal/DeadHoster.py | 31 | ||||
| -rw-r--r-- | module/plugins/internal/Extractor.py | 139 | ||||
| -rw-r--r-- | module/plugins/internal/MultiHook.py | 308 | ||||
| -rw-r--r-- | module/plugins/internal/MultiHoster.py | 85 | ||||
| -rw-r--r-- | module/plugins/internal/SevenZip.py | 155 | ||||
| -rw-r--r-- | module/plugins/internal/SimpleCrypter.py | 157 | ||||
| -rw-r--r-- | module/plugins/internal/SimpleDereferer.py | 98 | ||||
| -rw-r--r-- | module/plugins/internal/SimpleHoster.py | 701 | ||||
| -rw-r--r-- | module/plugins/internal/UnRar.py | 248 | ||||
| -rw-r--r-- | module/plugins/internal/UnZip.py | 68 | ||||
| -rw-r--r-- | module/plugins/internal/UpdateManager.py | 300 | ||||
| -rw-r--r-- | module/plugins/internal/XFSCrypter.py | 45 | ||||
| -rw-r--r-- | module/plugins/internal/XFSHoster.py | 326 | ||||
| -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.py | 875 | ||||
| -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.py | 182 | ||||
| -rw-r--r-- | pyload/plugin/Captcha.py | 34 | ||||
| -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.py | 140 | ||||
| -rw-r--r-- | pyload/plugin/Hook.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/Hoster.py (renamed from module/plugins/Hoster.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/OCR.py | 319 | ||||
| -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.py | 16 | ||||
| -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.py | 37 | ||||
| -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.py | 35 | ||||
| -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.py | 16 | ||||
| -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.py | 16 | ||||
| -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.py | 16 | ||||
| -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.py | 82 | ||||
| -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.py | 16 | ||||
| -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.py | 81 | ||||
| -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.py | 66 | ||||
| -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.py | 62 | ||||
| -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.py | 34 | ||||
| -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.py | 68 | ||||
| -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.py | 75 | ||||
| -rw-r--r-- | pyload/plugin/addon/Checksum.py (renamed from module/plugins/addon/Checksum.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/addon/ClickAndLoad.py | 119 | ||||
| -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.py | 504 | ||||
| -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.py | 46 | ||||
| -rw-r--r-- | pyload/plugin/addon/MergeFiles.py | 85 | ||||
| -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.py | 93 | ||||
| -rw-r--r-- | pyload/plugin/addon/UnSkipOnFail.py | 90 | ||||
| -rw-r--r-- | pyload/plugin/addon/UpdateManager.py | 306 | ||||
| -rw-r--r-- | pyload/plugin/addon/WindowsPhoneNotify.py | 91 | ||||
| -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.py | 108 | ||||
| -rw-r--r-- | pyload/plugin/captcha/AdsCaptcha.py | 79 | ||||
| -rw-r--r-- | pyload/plugin/captcha/ReCaptcha.py | 208 | ||||
| -rw-r--r-- | pyload/plugin/captcha/SolveMedia.py | 113 | ||||
| -rw-r--r-- | pyload/plugin/captcha/__init__.py (renamed from module/plugins/captcha/__init__.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/container/CCF.py | 49 | ||||
| -rw-r--r-- | pyload/plugin/container/DLC.py | 72 | ||||
| -rw-r--r-- | pyload/plugin/container/RSDF.py | 52 | ||||
| -rw-r--r-- | pyload/plugin/container/TXT.py | 69 | ||||
| -rw-r--r-- | pyload/plugin/container/__init__.py (renamed from module/plugins/container/__init__.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/crypter/BitshareCom.py | 21 | ||||
| -rw-r--r-- | pyload/plugin/crypter/C1NeonCom.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/ChipDe.py (renamed from module/plugins/crypter/ChipDe.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/crypter/CloudzillaTo.py | 36 | ||||
| -rw-r--r-- | pyload/plugin/crypter/CrockoCom.py | 20 | ||||
| -rw-r--r-- | pyload/plugin/crypter/CryptItCom.py | 16 | ||||
| -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.py | 40 | ||||
| -rw-r--r-- | pyload/plugin/crypter/DdlstorageCom.py | 17 | ||||
| -rw-r--r-- | pyload/plugin/crypter/DepositfilesCom.py | 20 | ||||
| -rw-r--r-- | pyload/plugin/crypter/Dereferer.py | 17 | ||||
| -rw-r--r-- | pyload/plugin/crypter/DevhostSt.py | 54 | ||||
| -rw-r--r-- | pyload/plugin/crypter/DlProtectCom.py | 65 | ||||
| -rw-r--r-- | pyload/plugin/crypter/DontKnowMe.py | 17 | ||||
| -rw-r--r-- | pyload/plugin/crypter/DuckCryptInfo.py (renamed from module/plugins/crypter/DuckCryptInfo.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/crypter/DuploadOrg.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/EasybytezCom.py | 20 | ||||
| -rw-r--r-- | pyload/plugin/crypter/EmbeduploadCom.py (renamed from module/plugins/crypter/EmbeduploadCom.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FilebeerInfo.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FilecloudIo.py | 21 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FilecryptCc.py | 182 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FilefactoryCom.py | 28 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FilerNet.py | 24 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FileserveCom.py (renamed from module/plugins/crypter/FileserveCom.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FilesonicCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FilestubeCom.py | 21 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FiletramCom.py | 22 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FiredriveCom.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FourChanOrg.py (renamed from module/plugins/crypter/FourChanOrg.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FreakhareCom.py | 38 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FreetexthostCom.py | 27 | ||||
| -rw-r--r-- | pyload/plugin/crypter/FshareVn.py | 20 | ||||
| -rw-r--r-- | pyload/plugin/crypter/Go4UpCom.py | 46 | ||||
| -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.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/ILoadTo.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/ImgurComAlbum.py | 27 | ||||
| -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.py | 22 | ||||
| -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.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/MBLinkInfo.py | 17 | ||||
| -rw-r--r-- | pyload/plugin/crypter/MediafireCom.py (renamed from module/plugins/crypter/MediafireCom.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/crypter/MegaCoNz.py | 32 | ||||
| -rw-r--r-- | pyload/plugin/crypter/MegaRapidCz.py | 20 | ||||
| -rw-r--r-- | pyload/plugin/crypter/MegauploadCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/crypter/Movie2KTo.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/MultiUpOrg.py | 38 | ||||
| -rw-r--r-- | pyload/plugin/crypter/MultiloadCz.py (renamed from module/plugins/crypter/MultiloadCz.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/crypter/MultiuploadCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/crypter/NCryptIn.py (renamed from module/plugins/crypter/NCryptIn.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/crypter/NetfolderIn.py | 70 | ||||
| -rw-r--r-- | pyload/plugin/crypter/NosvideoCom.py | 21 | ||||
| -rw-r--r-- | pyload/plugin/crypter/OneKhDe.py (renamed from module/plugins/crypter/OneKhDe.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/crypter/OronCom.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/PastebinCom.py | 21 | ||||
| -rw-r--r-- | pyload/plugin/crypter/QuickshareCz.py (renamed from module/plugins/crypter/QuickshareCz.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/crypter/RSLayerCom.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/RelinkUs.py | 293 | ||||
| -rw-r--r-- | pyload/plugin/crypter/SafelinkingNet.py (renamed from module/plugins/crypter/SafelinkingNet.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/crypter/SecuredIn.py | 16 | ||||
| -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.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/crypter/SpeedLoadOrg.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/StealthTo.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/TnyCz.py | 27 | ||||
| -rw-r--r-- | pyload/plugin/crypter/TrailerzoneInfo.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/TurbobitNet.py | 44 | ||||
| -rw-r--r-- | pyload/plugin/crypter/TusfilesNet.py | 43 | ||||
| -rw-r--r-- | pyload/plugin/crypter/UlozTo.py (renamed from module/plugins/crypter/UlozTo.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/crypter/UploadableCh.py | 24 | ||||
| -rw-r--r-- | pyload/plugin/crypter/UploadedTo.py | 34 | ||||
| -rw-r--r-- | pyload/plugin/crypter/WiiReloadedOrg.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/crypter/WuploadCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/crypter/XFileSharingPro.py | 52 | ||||
| -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.py | 155 | ||||
| -rw-r--r-- | pyload/plugin/extractor/UnRar.py | 248 | ||||
| -rw-r--r-- | pyload/plugin/extractor/UnZip.py | 68 | ||||
| -rw-r--r-- | pyload/plugin/extractor/__init__.py (renamed from module/plugins/hooks/__init__.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hook/AlldebridCom.py | 29 | ||||
| -rw-r--r-- | pyload/plugin/hook/BypassCaptcha.py | 135 | ||||
| -rw-r--r-- | pyload/plugin/hook/Captcha9Kw.py | 251 | ||||
| -rw-r--r-- | pyload/plugin/hook/CaptchaBrotherhood.py | 167 | ||||
| -rw-r--r-- | pyload/plugin/hook/DeathByCaptcha.py | 214 | ||||
| -rw-r--r-- | pyload/plugin/hook/DebridItaliaCom.py | 28 | ||||
| -rw-r--r-- | pyload/plugin/hook/EasybytezCom.py | 32 | ||||
| -rw-r--r-- | pyload/plugin/hook/ExpertDecoders.py | 96 | ||||
| -rw-r--r-- | pyload/plugin/hook/FastixRu.py | 31 | ||||
| -rw-r--r-- | pyload/plugin/hook/FreeWayMe.py | 27 | ||||
| -rw-r--r-- | pyload/plugin/hook/ImageTyperz.py | 153 | ||||
| -rw-r--r-- | pyload/plugin/hook/LinkdecrypterCom.py | 25 | ||||
| -rw-r--r-- | pyload/plugin/hook/LinksnappyCom.py | 29 | ||||
| -rw-r--r-- | pyload/plugin/hook/MegaDebridEu.py | 35 | ||||
| -rw-r--r-- | pyload/plugin/hook/MultihostersCom.py | 18 | ||||
| -rw-r--r-- | pyload/plugin/hook/MultishareCz.py | 31 | ||||
| -rw-r--r-- | pyload/plugin/hook/MyfastfileCom.py | 30 | ||||
| -rw-r--r-- | pyload/plugin/hook/NoPremiumPl.py | 31 | ||||
| -rw-r--r-- | pyload/plugin/hook/OverLoadMe.py | 31 | ||||
| -rw-r--r-- | pyload/plugin/hook/PremiumTo.py | 29 | ||||
| -rw-r--r-- | pyload/plugin/hook/PremiumizeMe.py | 40 | ||||
| -rw-r--r-- | pyload/plugin/hook/PutdriveCom.py | 18 | ||||
| -rw-r--r-- | pyload/plugin/hook/RPNetBiz.py | 38 | ||||
| -rw-r--r-- | pyload/plugin/hook/RapideoPl.py | 31 | ||||
| -rw-r--r-- | pyload/plugin/hook/RealdebridCom.py | 29 | ||||
| -rw-r--r-- | pyload/plugin/hook/RehostTo.py | 29 | ||||
| -rw-r--r-- | pyload/plugin/hook/SimplyPremiumCom.py | 31 | ||||
| -rw-r--r-- | pyload/plugin/hook/SimplydebridCom.py | 26 | ||||
| -rw-r--r-- | pyload/plugin/hook/SmoozedCom.py | 26 | ||||
| -rw-r--r-- | pyload/plugin/hook/UnrestrictLi.py | 30 | ||||
| -rw-r--r-- | pyload/plugin/hook/XFileSharingPro.py | 110 | ||||
| -rw-r--r-- | pyload/plugin/hook/ZeveraCom.py | 27 | ||||
| -rw-r--r-- | pyload/plugin/hook/__init__.py (renamed from module/plugins/hoster/__init__.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/AlldebridCom.py | 75 | ||||
| -rw-r--r-- | pyload/plugin/hoster/AndroidfilehostCom.py | 60 | ||||
| -rw-r--r-- | pyload/plugin/hoster/BasketbuildCom.py | 58 | ||||
| -rw-r--r-- | pyload/plugin/hoster/BayfilesCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/BezvadataCz.py | 91 | ||||
| -rw-r--r-- | pyload/plugin/hoster/BillionuploadsCom.py | 19 | ||||
| -rw-r--r-- | pyload/plugin/hoster/BitshareCom.py | 155 | ||||
| -rw-r--r-- | pyload/plugin/hoster/BoltsharingCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/CatShareNet.py | 59 | ||||
| -rw-r--r-- | pyload/plugin/hoster/CloudzerNet.py | 17 | ||||
| -rw-r--r-- | pyload/plugin/hoster/CloudzillaTo.py | 58 | ||||
| -rw-r--r-- | pyload/plugin/hoster/CramitIn.py | 20 | ||||
| -rw-r--r-- | pyload/plugin/hoster/CrockoCom.py | 63 | ||||
| -rw-r--r-- | pyload/plugin/hoster/CyberlockerCh.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/CzshareCom.py | 158 | ||||
| -rw-r--r-- | pyload/plugin/hoster/DailymotionCom.py (renamed from module/plugins/hoster/DailymotionCom.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/DataHu.py | 31 | ||||
| -rw-r--r-- | pyload/plugin/hoster/DataportCz.py | 54 | ||||
| -rw-r--r-- | pyload/plugin/hoster/DateiTo.py | 79 | ||||
| -rw-r--r-- | pyload/plugin/hoster/DdlstorageCom.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/hoster/DebridItaliaCom.py | 40 | ||||
| -rw-r--r-- | pyload/plugin/hoster/DepositfilesCom.py | 112 | ||||
| -rw-r--r-- | pyload/plugin/hoster/DevhostSt.py | 33 | ||||
| -rw-r--r-- | pyload/plugin/hoster/DlFreeFr.py | 137 | ||||
| -rw-r--r-- | pyload/plugin/hoster/DodanePl.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/DuploadOrg.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/EasybytezCom.py | 21 | ||||
| -rw-r--r-- | pyload/plugin/hoster/EdiskCz.py | 53 | ||||
| -rw-r--r-- | pyload/plugin/hoster/EgoFilesCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/EnteruploadCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/EpicShareNet.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/EuroshareEu.py | 64 | ||||
| -rw-r--r-- | pyload/plugin/hoster/ExashareCom.py | 35 | ||||
| -rw-r--r-- | pyload/plugin/hoster/ExtabitCom.py | 75 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FastixRu.py | 63 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FastshareCz.py | 76 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FileApeCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FileSharkPl.py | 130 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FileStoreTo.py | 34 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FilebeerInfo.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FilecloudIo.py | 123 | ||||
| -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.py | 30 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FilepostCom.py | 130 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FilepupNet.py | 44 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FilerNet.py | 71 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FilerioCom.py | 20 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FilesMailRu.py (renamed from module/plugins/hoster/FilesMailRu.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FileserveCom.py | 216 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FileshareInUa.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FilesonicCom.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FilezyNet.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FiredriveCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FlyFilesNet.py (renamed from module/plugins/hoster/FlyFilesNet.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FourSharedCom.py | 59 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FreakshareCom.py | 180 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FreeWayMe.py | 50 | ||||
| -rw-r--r-- | pyload/plugin/hoster/FreevideoCz.py | 15 | ||||
| -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.py | 61 | ||||
| -rw-r--r-- | pyload/plugin/hoster/GooIm.py | 34 | ||||
| -rw-r--r-- | pyload/plugin/hoster/GoogledriveCom.py | 62 | ||||
| -rw-r--r-- | pyload/plugin/hoster/HellshareCz.py | 32 | ||||
| -rw-r--r-- | pyload/plugin/hoster/HellspyCz.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/HotfileCom.py | 18 | ||||
| -rw-r--r-- | pyload/plugin/hoster/HugefilesNet.py | 22 | ||||
| -rw-r--r-- | pyload/plugin/hoster/HundredEightyUploadCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/IFileWs.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/IcyFilesCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/IfileIt.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/IfolderRu.py | 73 | ||||
| -rw-r--r-- | pyload/plugin/hoster/JumbofilesCom.py | 33 | ||||
| -rw-r--r-- | pyload/plugin/hoster/JunocloudMe.py | 21 | ||||
| -rw-r--r-- | pyload/plugin/hoster/Keep2ShareCc.py | 109 | ||||
| -rw-r--r-- | pyload/plugin/hoster/KickloadCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/KingfilesNet.py | 75 | ||||
| -rw-r--r-- | pyload/plugin/hoster/LemUploadsCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/LetitbitNet.py | 155 | ||||
| -rw-r--r-- | pyload/plugin/hoster/LinksnappyCom.py | 55 | ||||
| -rw-r--r-- | pyload/plugin/hoster/LoadTo.py | 65 | ||||
| -rw-r--r-- | pyload/plugin/hoster/LomafileCom.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/hoster/LuckyShareNet.py | 71 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MediafireCom.py (renamed from module/plugins/hoster/MediafireCom.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MegaCoNz.py | 217 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MegaDebridEu.py | 86 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MegaFilesSe.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MegaRapidCz.py | 65 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MegacrypterCom.py (renamed from module/plugins/hoster/MegacrypterCom.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MegareleaseOrg.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MegasharesCom.py | 110 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MegauploadCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MegavideoCom.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MovReelCom.py | 18 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MultihostersCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MultishareCz.py | 51 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MyfastfileCom.py | 36 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MystoreTo.py | 42 | ||||
| -rw-r--r-- | pyload/plugin/hoster/MyvideoDe.py (renamed from module/plugins/hoster/MyvideoDe.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/NahrajCz.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/NarodRu.py | 63 | ||||
| -rw-r--r-- | pyload/plugin/hoster/NetloadIn.py (renamed from module/plugins/hoster/NetloadIn.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/NitroflareCom.py | 107 | ||||
| -rw-r--r-- | pyload/plugin/hoster/NoPremiumPl.py | 103 | ||||
| -rw-r--r-- | pyload/plugin/hoster/NosuploadCom.py | 39 | ||||
| -rw-r--r-- | pyload/plugin/hoster/NovafileCom.py | 26 | ||||
| -rw-r--r-- | pyload/plugin/hoster/NowDownloadSx.py | 61 | ||||
| -rw-r--r-- | pyload/plugin/hoster/NowVideoSx.py | 41 | ||||
| -rw-r--r-- | pyload/plugin/hoster/OboomCom.py (renamed from module/plugins/hoster/OboomCom.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/OneFichierCom.py | 58 | ||||
| -rw-r--r-- | pyload/plugin/hoster/OronCom.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/hoster/OverLoadMe.py | 73 | ||||
| -rw-r--r-- | pyload/plugin/hoster/PandaplaNet.py | 15 | ||||
| -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.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/PremiumTo.py | 52 | ||||
| -rw-r--r-- | pyload/plugin/hoster/PremiumizeMe.py | 57 | ||||
| -rw-r--r-- | pyload/plugin/hoster/PromptfileCom.py | 42 | ||||
| -rw-r--r-- | pyload/plugin/hoster/PrzeklejPl.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/PutdriveCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/QuickshareCz.py | 86 | ||||
| -rw-r--r-- | pyload/plugin/hoster/RPNetBiz.py | 77 | ||||
| -rw-r--r-- | pyload/plugin/hoster/RapideoPl.py | 103 | ||||
| -rw-r--r-- | pyload/plugin/hoster/RapidfileshareNet.py | 22 | ||||
| -rw-r--r-- | pyload/plugin/hoster/RapidgatorNet.py | 169 | ||||
| -rw-r--r-- | pyload/plugin/hoster/RapiduNet.py | 83 | ||||
| -rw-r--r-- | pyload/plugin/hoster/RarefileNet.py | 20 | ||||
| -rw-r--r-- | pyload/plugin/hoster/RealdebridCom.py | 76 | ||||
| -rw-r--r-- | pyload/plugin/hoster/RedtubeCom.py (renamed from module/plugins/hoster/RedtubeCom.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/RehostTo.py | 25 | ||||
| -rw-r--r-- | pyload/plugin/hoster/RemixshareCom.py | 57 | ||||
| -rw-r--r-- | pyload/plugin/hoster/RgHostNet.py | 23 | ||||
| -rw-r--r-- | pyload/plugin/hoster/SafesharingEu.py | 18 | ||||
| -rw-r--r-- | pyload/plugin/hoster/SecureUploadEu.py | 18 | ||||
| -rw-r--r-- | pyload/plugin/hoster/SendspaceCom.py | 58 | ||||
| -rw-r--r-- | pyload/plugin/hoster/Share4WebCom.py | 18 | ||||
| -rw-r--r-- | pyload/plugin/hoster/Share76Com.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/ShareFilesCo.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/SharebeesCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/ShareonlineBiz.py | 184 | ||||
| -rw-r--r-- | pyload/plugin/hoster/ShareplaceCom.py (renamed from module/plugins/hoster/ShareplaceCom.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/SharingmatrixCom.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/hoster/ShragleCom.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/hoster/SimplyPremiumCom.py | 78 | ||||
| -rw-r--r-- | pyload/plugin/hoster/SimplydebridCom.py | 45 | ||||
| -rw-r--r-- | pyload/plugin/hoster/SmoozedCom.py | 63 | ||||
| -rw-r--r-- | pyload/plugin/hoster/SockshareCom.py | 17 | ||||
| -rw-r--r-- | pyload/plugin/hoster/SoundcloudCom.py (renamed from module/plugins/hoster/SoundcloudCom.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/SpeedLoadOrg.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/SpeedfileCz.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/SpeedyshareCom.py | 41 | ||||
| -rw-r--r-- | pyload/plugin/hoster/StorageTo.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/StreamCz.py (renamed from module/plugins/hoster/StreamCz.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/StreamcloudEu.py | 28 | ||||
| -rw-r--r-- | pyload/plugin/hoster/TurbobitNet.py | 164 | ||||
| -rw-r--r-- | pyload/plugin/hoster/TurbouploadCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/TusfilesNet.py | 37 | ||||
| -rw-r--r-- | pyload/plugin/hoster/TwoSharedCom.py | 29 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UlozTo.py | 155 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UloziskoSk.py | 68 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UnibytesCom.py | 70 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UnrestrictLi.py | 82 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UpleaCom.py | 56 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UploadStationCom.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UploadableCh.py | 76 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UploadboxCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UploadedTo.py | 117 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UploadhereCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UploadheroCom.py | 73 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UploadingCom.py | 96 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UploadkingCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UpstoreNet.py | 69 | ||||
| -rw-r--r-- | pyload/plugin/hoster/UptoboxCom.py | 29 | ||||
| -rw-r--r-- | pyload/plugin/hoster/VeehdCom.py (renamed from module/plugins/hoster/VeehdCom.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/VeohCom.py | 51 | ||||
| -rw-r--r-- | pyload/plugin/hoster/VidPlayNet.py | 21 | ||||
| -rw-r--r-- | pyload/plugin/hoster/VimeoCom.py | 71 | ||||
| -rw-r--r-- | pyload/plugin/hoster/Vipleech4UCom.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/WarserverCz.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/WebshareCz.py | 60 | ||||
| -rw-r--r-- | pyload/plugin/hoster/WrzucTo.py | 49 | ||||
| -rw-r--r-- | pyload/plugin/hoster/WuploadCom.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/hoster/X7To.py | 15 | ||||
| -rw-r--r-- | pyload/plugin/hoster/XFileSharingPro.py | 59 | ||||
| -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.py | 35 | ||||
| -rw-r--r-- | pyload/plugin/hoster/Xdcc.py (renamed from module/plugins/hoster/Xdcc.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/hoster/YibaishiwuCom.py | 56 | ||||
| -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.py | 16 | ||||
| -rw-r--r-- | pyload/plugin/hoster/ZeveraCom.py | 31 | ||||
| -rw-r--r-- | pyload/plugin/hoster/ZippyshareCom.py | 62 | ||||
| -rw-r--r-- | pyload/plugin/hoster/__init__.py (renamed from module/plugins/internal/__init__.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/internal/BasePlugin.py | 92 | ||||
| -rw-r--r-- | pyload/plugin/internal/DeadCrypter.py | 27 | ||||
| -rw-r--r-- | pyload/plugin/internal/DeadHoster.py | 27 | ||||
| -rw-r--r-- | pyload/plugin/internal/MultiHook.py | 308 | ||||
| -rw-r--r-- | pyload/plugin/internal/MultiHoster.py | 85 | ||||
| -rw-r--r-- | pyload/plugin/internal/SimpleCrypter.py | 157 | ||||
| -rw-r--r-- | pyload/plugin/internal/SimpleDereferer.py | 98 | ||||
| -rw-r--r-- | pyload/plugin/internal/SimpleHoster.py | 701 | ||||
| -rw-r--r-- | pyload/plugin/internal/UpdateManager.py | 306 | ||||
| -rw-r--r-- | pyload/plugin/internal/XFSAccount.py (renamed from module/plugins/internal/XFSAccount.py) | 0 | ||||
| -rw-r--r-- | pyload/plugin/internal/XFSCrypter.py | 45 | ||||
| -rw-r--r-- | pyload/plugin/internal/XFSHoster.py | 326 | ||||
| -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__.py | 1 | ||||
| -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) | bin | 689 -> 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) | bin | 1472 -> 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) | bin | 2073 -> 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) | bin | 1651 -> 1651 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/button.png (renamed from module/webui/themes/Dark/img/button.png) | bin | 569 -> 569 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/dark-bg.jpg (renamed from module/webui/themes/Dark/img/dark-bg.jpg) | bin | 40930 -> 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) | bin | 571 -> 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) | bin | 404 -> 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) | bin | 685 -> 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) | bin | 349 -> 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) | bin | 1905 -> 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) | bin | 728 -> 728 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/default/body.png (renamed from module/webui/themes/Dark/img/default/body.png) | bin | 402 -> 402 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/default/closebtn.gif (renamed from module/webui/themes/Dark/img/default/closebtn.gif) | bin | 254 -> 254 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/default/cog.png (renamed from module/webui/themes/Dark/img/default/cog.png) | bin | 512 -> 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) | bin | 446 -> 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) | bin | 845 -> 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) | bin | 3349 -> 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) | bin | 787 -> 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) | bin | 598 -> 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) | bin | 721 -> 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) | bin | 592 -> 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) | bin | 717 -> 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) | bin | 403 -> 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) | bin | 695 -> 695 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/default/delete.png (renamed from module/webui/themes/Dark/img/default/delete.png) | bin | 715 -> 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) | bin | 76 -> 76 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/default/error.png (renamed from module/webui/themes/Dark/img/default/error.png) | bin | 701 -> 701 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/default/folder.png (renamed from module/webui/themes/Dark/img/default/folder.png) | bin | 537 -> 537 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/default/full.png (renamed from module/webui/themes/Dark/img/default/full.png) | bin | 3543 -> 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) | bin | 1288 -> 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) | bin | 1953 -> 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) | bin | 1802 -> 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) | bin | 876 -> 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) | bin | 721 -> 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) | bin | 920 -> 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) | bin | 482 -> 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) | bin | 628 -> 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) | bin | 2629 -> 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) | bin | 932 -> 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) | bin | 1204 -> 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) | bin | 1187 -> 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) | bin | 125 -> 125 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/default/images.png (renamed from module/webui/themes/Dark/img/default/images.png) | bin | 661 -> 661 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/default/notice.png (renamed from module/webui/themes/Dark/img/default/notice.png) | bin | 778 -> 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) | bin | 898 -> 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) | bin | 540 -> 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) | bin | 574 -> 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) | bin | 603 -> 603 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/default/parseUri.png (renamed from module/webui/themes/Dark/img/default/parseUri.png) | bin | 666 -> 666 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/default/pencil.png (renamed from module/webui/themes/Dark/img/default/pencil.png) | bin | 450 -> 450 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/default/reconnect.png (renamed from module/webui/themes/Dark/img/default/reconnect.png) | bin | 755 -> 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) | bin | 7613 -> 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) | bin | 943 -> 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) | bin | 701 -> 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) | bin | 781 -> 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) | bin | 700 -> 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) | bin | 512 -> 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) | bin | 7613 -> 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) | bin | 889 -> 889 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/default/success.png (renamed from module/webui/themes/Dark/img/default/success.png) | bin | 781 -> 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) | bin | 163 -> 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) | bin | 799 -> 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) | bin | 628 -> 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) | bin | 3963 -> 3963 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/pyload-logo.png (renamed from module/webui/themes/Dark/img/pyload-logo.png) | bin | 6947 -> 6947 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Dark/img/tab-background.png (renamed from module/webui/themes/Dark/img/tab-background.png) | bin | 3044 -> 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) | bin | 689 -> 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) | bin | 1472 -> 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) | bin | 2073 -> 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) | bin | 1651 -> 1651 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/add_folder.png (renamed from module/webui/themes/Default/img/add_folder.png) | bin | 571 -> 571 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/ajax-loader.gif (renamed from module/webui/themes/Default/img/ajax-loader.gif) | bin | 404 -> 404 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/arrow_refresh.png (renamed from module/webui/themes/Default/img/arrow_refresh.png) | bin | 685 -> 685 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/arrow_right.png (renamed from module/webui/themes/Default/img/arrow_right.png) | bin | 349 -> 349 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/big_button.gif (renamed from module/webui/themes/Default/img/big_button.gif) | bin | 1905 -> 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) | bin | 728 -> 728 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/body.png (renamed from module/webui/themes/Default/img/body.png) | bin | 402 -> 402 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/button.png (renamed from module/webui/themes/Default/img/button.png) | bin | 452 -> 452 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/closebtn.gif (renamed from module/webui/themes/Default/img/closebtn.gif) | bin | 254 -> 254 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/cog.png (renamed from module/webui/themes/Default/img/cog.png) | bin | 512 -> 512 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/control_add.png (renamed from module/webui/themes/Default/img/control_add.png) | bin | 446 -> 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) | bin | 845 -> 845 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/control_cancel.png (renamed from module/webui/themes/Default/img/control_cancel.png) | bin | 3349 -> 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) | bin | 787 -> 787 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/control_pause.png (renamed from module/webui/themes/Default/img/control_pause.png) | bin | 598 -> 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) | bin | 721 -> 721 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/control_play.png (renamed from module/webui/themes/Default/img/control_play.png) | bin | 592 -> 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) | bin | 717 -> 717 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/control_stop.png (renamed from module/webui/themes/Default/img/control_stop.png) | bin | 403 -> 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) | bin | 695 -> 695 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/delete.png (renamed from module/webui/themes/Default/img/delete.png) | bin | 715 -> 715 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/drag_corner.gif (renamed from module/webui/themes/Default/img/drag_corner.gif) | bin | 76 -> 76 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/error.png (renamed from module/webui/themes/Default/img/error.png) | bin | 701 -> 701 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/folder.png (renamed from module/webui/themes/Default/img/folder.png) | bin | 537 -> 537 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/full.png (renamed from module/webui/themes/Default/img/full.png) | bin | 3543 -> 3543 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/head-login.png (renamed from module/webui/themes/Default/img/head-login.png) | bin | 1288 -> 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) | bin | 1953 -> 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) | bin | 1802 -> 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) | bin | 876 -> 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) | bin | 721 -> 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) | bin | 920 -> 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) | bin | 482 -> 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) | bin | 628 -> 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) | bin | 2629 -> 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) | bin | 932 -> 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) | bin | 1204 -> 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) | bin | 1187 -> 1187 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/head_bg1.png (renamed from module/webui/themes/Default/img/head_bg1.png) | bin | 125 -> 125 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/images.png (renamed from module/webui/themes/Default/img/images.png) | bin | 661 -> 661 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/notice.png (renamed from module/webui/themes/Default/img/notice.png) | bin | 778 -> 778 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/package_go.png (renamed from module/webui/themes/Default/img/package_go.png) | bin | 898 -> 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) | bin | 540 -> 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) | bin | 574 -> 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) | bin | 603 -> 603 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/parseUri.png (renamed from module/webui/themes/Default/img/parseUri.png) | bin | 666 -> 666 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/pencil.png (renamed from module/webui/themes/Default/img/pencil.png) | bin | 450 -> 450 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/pyload-logo.png (renamed from module/webui/themes/Default/img/pyload-logo.png) | bin | 8457 -> 8457 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/reconnect.png (renamed from module/webui/themes/Default/img/reconnect.png) | bin | 755 -> 755 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/status_None.png (renamed from module/webui/themes/Default/img/status_None.png) | bin | 7613 -> 7613 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/status_downloading.png (renamed from module/webui/themes/Default/img/status_downloading.png) | bin | 943 -> 943 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/status_failed.png (renamed from module/webui/themes/Default/img/status_failed.png) | bin | 701 -> 701 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/status_finished.png (renamed from module/webui/themes/Default/img/status_finished.png) | bin | 781 -> 781 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/status_offline.png (renamed from module/webui/themes/Default/img/status_offline.png) | bin | 700 -> 700 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/status_proc.png (renamed from module/webui/themes/Default/img/status_proc.png) | bin | 512 -> 512 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/status_queue.png (renamed from module/webui/themes/Default/img/status_queue.png) | bin | 7613 -> 7613 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/status_waiting.png (renamed from module/webui/themes/Default/img/status_waiting.png) | bin | 889 -> 889 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/success.png (renamed from module/webui/themes/Default/img/success.png) | bin | 781 -> 781 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/tab-background.png (renamed from module/webui/themes/Default/img/tab-background.png) | bin | 179 -> 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) | bin | 163 -> 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) | bin | 799 -> 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) | bin | 628 -> 628 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Default/img/user-info.png (renamed from module/webui/themes/Default/img/user-info.png) | bin | 3963 -> 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) | bin | 689 -> 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) | bin | 1472 -> 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) | bin | 2073 -> 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) | bin | 1651 -> 1651 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/arrow_refresh.png (renamed from module/webui/themes/Flat/img/arrow_refresh.png) | bin | 119032 -> 119032 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/arrow_right.png (renamed from module/webui/themes/Flat/img/arrow_right.png) | bin | 136967 -> 136967 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/button.png (renamed from module/webui/themes/Flat/img/button.png) | bin | 569 -> 569 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/cog.png (renamed from module/webui/themes/Flat/img/cog.png) | bin | 137406 -> 137406 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/control_add.png (renamed from module/webui/themes/Flat/img/control_add.png) | bin | 116941 -> 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) | bin | 116941 -> 116941 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/control_cancel.png (renamed from module/webui/themes/Flat/img/control_cancel.png) | bin | 116939 -> 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) | bin | 116939 -> 116939 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/control_pause.png (renamed from module/webui/themes/Flat/img/control_pause.png) | bin | 134855 -> 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) | bin | 134855 -> 134855 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/control_play.png (renamed from module/webui/themes/Flat/img/control_play.png) | bin | 134904 -> 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) | bin | 134904 -> 134904 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/control_stop.png (renamed from module/webui/themes/Flat/img/control_stop.png) | bin | 134835 -> 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) | bin | 134835 -> 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) | bin | 571 -> 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) | bin | 404 -> 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) | bin | 1905 -> 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) | bin | 728 -> 728 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/default/body.png (renamed from module/webui/themes/Flat/img/default/body.png) | bin | 402 -> 402 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/default/closebtn.gif (renamed from module/webui/themes/Flat/img/default/closebtn.gif) | bin | 254 -> 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) | bin | 76 -> 76 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/default/full.png (renamed from module/webui/themes/Flat/img/default/full.png) | bin | 3543 -> 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) | bin | 932 -> 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) | bin | 125 -> 125 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/default/images.png (renamed from module/webui/themes/Flat/img/default/images.png) | bin | 661 -> 661 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/default/parseUri.png (renamed from module/webui/themes/Flat/img/default/parseUri.png) | bin | 666 -> 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) | bin | 8457 -> 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) | bin | 179 -> 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) | bin | 163 -> 163 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/delete.png (renamed from module/webui/themes/Flat/img/delete.png) | bin | 117658 -> 117658 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/error.png (renamed from module/webui/themes/Flat/img/error.png) | bin | 137673 -> 137673 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/folder.png (renamed from module/webui/themes/Flat/img/folder.png) | bin | 134669 -> 134669 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/head-login.png (renamed from module/webui/themes/Flat/img/head-login.png) | bin | 137406 -> 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) | bin | 134985 -> 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) | bin | 137664 -> 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) | bin | 135818 -> 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) | bin | 137664 -> 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) | bin | 139387 -> 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) | bin | 136511 -> 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) | bin | 136511 -> 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) | bin | 136269 -> 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) | bin | 137217 -> 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) | bin | 137217 -> 137217 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/notice.png (renamed from module/webui/themes/Flat/img/notice.png) | bin | 3061 -> 3061 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/package_go.png (renamed from module/webui/themes/Flat/img/package_go.png) | bin | 136299 -> 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) | bin | 138112 -> 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) | bin | 138112 -> 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) | bin | 138112 -> 138112 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/pencil.png (renamed from module/webui/themes/Flat/img/pencil.png) | bin | 138112 -> 138112 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/reconnect.png (renamed from module/webui/themes/Flat/img/reconnect.png) | bin | 3063 -> 3063 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/status_None.png (renamed from module/webui/themes/Flat/img/status_None.png) | bin | 138112 -> 138112 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/status_downloading.png (renamed from module/webui/themes/Flat/img/status_downloading.png) | bin | 3061 -> 3061 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/status_failed.png (renamed from module/webui/themes/Flat/img/status_failed.png) | bin | 137673 -> 137673 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/status_finished.png (renamed from module/webui/themes/Flat/img/status_finished.png) | bin | 117658 -> 117658 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/status_offline.png (renamed from module/webui/themes/Flat/img/status_offline.png) | bin | 137673 -> 137673 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/status_proc.png (renamed from module/webui/themes/Flat/img/status_proc.png) | bin | 137406 -> 137406 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/status_queue.png (renamed from module/webui/themes/Flat/img/status_queue.png) | bin | 138112 -> 138112 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/status_waiting.png (renamed from module/webui/themes/Flat/img/status_waiting.png) | bin | 138112 -> 138112 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/success.png (renamed from module/webui/themes/Flat/img/success.png) | bin | 117658 -> 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) | bin | 138112 -> 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) | bin | 138112 -> 138112 bytes | |||
| -rw-r--r-- | pyload/webui/themes/Flat/img/user-info.png (renamed from module/webui/themes/Flat/img/user-info.png) | bin | 3080 -> 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' ·  (?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> </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öß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.,]+) (?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>:  (?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é n\'a pas été trouvé' - - -    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>.*?)  <' -    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'>"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>(?:<[^>]*>| )*([^<]*)' - -    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`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.,]+) (?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 = [(' ', '')] - -    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\'> \((?P<S>\d+) (?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' ·  (?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> </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öß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.,]+) (?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>:  (?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é n\'a pas été trouvé' + + +    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>.*?)  <' +    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'>"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>(?:<[^>]*>| )*([^<]*)' + +    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`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.,]+) (?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 = [(' ', '')] + +    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\'> \((?P<S>\d+) (?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 Binary files differindex 81ebb88b2..81ebb88b2 100644 --- a/module/webui/themes/Dark/img/MooDialog/dialog-close.png +++ b/pyload/webui/themes/Dark/img/MooDialog/dialog-close.png diff --git a/module/webui/themes/Dark/img/MooDialog/dialog-error.png b/pyload/webui/themes/Dark/img/MooDialog/dialog-error.png Binary files differindex d70328403..d70328403 100644 --- a/module/webui/themes/Dark/img/MooDialog/dialog-error.png +++ b/pyload/webui/themes/Dark/img/MooDialog/dialog-error.png diff --git a/module/webui/themes/Dark/img/MooDialog/dialog-question.png b/pyload/webui/themes/Dark/img/MooDialog/dialog-question.png Binary files differindex b0af3db5b..b0af3db5b 100644 --- a/module/webui/themes/Dark/img/MooDialog/dialog-question.png +++ b/pyload/webui/themes/Dark/img/MooDialog/dialog-question.png diff --git a/module/webui/themes/Dark/img/MooDialog/dialog-warning.png b/pyload/webui/themes/Dark/img/MooDialog/dialog-warning.png Binary files differindex aad64d4be..aad64d4be 100644 --- a/module/webui/themes/Dark/img/MooDialog/dialog-warning.png +++ b/pyload/webui/themes/Dark/img/MooDialog/dialog-warning.png diff --git a/module/webui/themes/Dark/img/button.png b/pyload/webui/themes/Dark/img/button.png Binary files differindex bb408a7d6..bb408a7d6 100644 --- a/module/webui/themes/Dark/img/button.png +++ b/pyload/webui/themes/Dark/img/button.png diff --git a/module/webui/themes/Dark/img/dark-bg.jpg b/pyload/webui/themes/Dark/img/dark-bg.jpg Binary files differindex 637fa6b93..637fa6b93 100644 --- a/module/webui/themes/Dark/img/dark-bg.jpg +++ b/pyload/webui/themes/Dark/img/dark-bg.jpg diff --git a/module/webui/themes/Dark/img/default/add_folder.png b/pyload/webui/themes/Dark/img/default/add_folder.png Binary files differindex 8acbc411b..8acbc411b 100644 --- a/module/webui/themes/Dark/img/default/add_folder.png +++ b/pyload/webui/themes/Dark/img/default/add_folder.png diff --git a/module/webui/themes/Dark/img/default/ajax-loader.gif b/pyload/webui/themes/Dark/img/default/ajax-loader.gif Binary files differindex 2fd8e0737..2fd8e0737 100644 --- a/module/webui/themes/Dark/img/default/ajax-loader.gif +++ b/pyload/webui/themes/Dark/img/default/ajax-loader.gif diff --git a/module/webui/themes/Dark/img/default/arrow_refresh.png b/pyload/webui/themes/Dark/img/default/arrow_refresh.png Binary files differindex 0de26566d..0de26566d 100644 --- a/module/webui/themes/Dark/img/default/arrow_refresh.png +++ b/pyload/webui/themes/Dark/img/default/arrow_refresh.png diff --git a/module/webui/themes/Dark/img/default/arrow_right.png b/pyload/webui/themes/Dark/img/default/arrow_right.png Binary files differindex b1a181923..b1a181923 100644 --- a/module/webui/themes/Dark/img/default/arrow_right.png +++ b/pyload/webui/themes/Dark/img/default/arrow_right.png diff --git a/module/webui/themes/Dark/img/default/big_button.gif b/pyload/webui/themes/Dark/img/default/big_button.gif Binary files differindex 7680490ea..7680490ea 100644 --- a/module/webui/themes/Dark/img/default/big_button.gif +++ b/pyload/webui/themes/Dark/img/default/big_button.gif diff --git a/module/webui/themes/Dark/img/default/big_button_over.gif b/pyload/webui/themes/Dark/img/default/big_button_over.gif Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/body.png b/pyload/webui/themes/Dark/img/default/body.png Binary files differindex 7ff1043e0..7ff1043e0 100644 --- a/module/webui/themes/Dark/img/default/body.png +++ b/pyload/webui/themes/Dark/img/default/body.png diff --git a/module/webui/themes/Dark/img/default/closebtn.gif b/pyload/webui/themes/Dark/img/default/closebtn.gif Binary files differindex 3e27e6030..3e27e6030 100644 --- a/module/webui/themes/Dark/img/default/closebtn.gif +++ b/pyload/webui/themes/Dark/img/default/closebtn.gif diff --git a/module/webui/themes/Dark/img/default/cog.png b/pyload/webui/themes/Dark/img/default/cog.png Binary files differindex 67de2c6cc..67de2c6cc 100644 --- a/module/webui/themes/Dark/img/default/cog.png +++ b/pyload/webui/themes/Dark/img/default/cog.png diff --git a/module/webui/themes/Dark/img/default/control_add.png b/pyload/webui/themes/Dark/img/default/control_add.png Binary files differindex d39886893..d39886893 100644 --- a/module/webui/themes/Dark/img/default/control_add.png +++ b/pyload/webui/themes/Dark/img/default/control_add.png diff --git a/module/webui/themes/Dark/img/default/control_add_blue.png b/pyload/webui/themes/Dark/img/default/control_add_blue.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/control_cancel.png b/pyload/webui/themes/Dark/img/default/control_cancel.png Binary files differindex 7b9bc3fba..7b9bc3fba 100644 --- a/module/webui/themes/Dark/img/default/control_cancel.png +++ b/pyload/webui/themes/Dark/img/default/control_cancel.png diff --git a/module/webui/themes/Dark/img/default/control_cancel_blue.png b/pyload/webui/themes/Dark/img/default/control_cancel_blue.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/control_pause.png b/pyload/webui/themes/Dark/img/default/control_pause.png Binary files differindex 2d9ce9c4e..2d9ce9c4e 100644 --- a/module/webui/themes/Dark/img/default/control_pause.png +++ b/pyload/webui/themes/Dark/img/default/control_pause.png diff --git a/module/webui/themes/Dark/img/default/control_pause_blue.png b/pyload/webui/themes/Dark/img/default/control_pause_blue.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/control_play.png b/pyload/webui/themes/Dark/img/default/control_play.png Binary files differindex 0846555d0..0846555d0 100644 --- a/module/webui/themes/Dark/img/default/control_play.png +++ b/pyload/webui/themes/Dark/img/default/control_play.png diff --git a/module/webui/themes/Dark/img/default/control_play_blue.png b/pyload/webui/themes/Dark/img/default/control_play_blue.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/control_stop.png b/pyload/webui/themes/Dark/img/default/control_stop.png Binary files differindex 893bb60e5..893bb60e5 100644 --- a/module/webui/themes/Dark/img/default/control_stop.png +++ b/pyload/webui/themes/Dark/img/default/control_stop.png diff --git a/module/webui/themes/Dark/img/default/control_stop_blue.png b/pyload/webui/themes/Dark/img/default/control_stop_blue.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/delete.png b/pyload/webui/themes/Dark/img/default/delete.png Binary files differindex 08f249365..08f249365 100644 --- a/module/webui/themes/Dark/img/default/delete.png +++ b/pyload/webui/themes/Dark/img/default/delete.png diff --git a/module/webui/themes/Dark/img/default/drag_corner.gif b/pyload/webui/themes/Dark/img/default/drag_corner.gif Binary files differindex befb1adf1..befb1adf1 100644 --- a/module/webui/themes/Dark/img/default/drag_corner.gif +++ b/pyload/webui/themes/Dark/img/default/drag_corner.gif diff --git a/module/webui/themes/Dark/img/default/error.png b/pyload/webui/themes/Dark/img/default/error.png Binary files differindex c37bd062e..c37bd062e 100644 --- a/module/webui/themes/Dark/img/default/error.png +++ b/pyload/webui/themes/Dark/img/default/error.png diff --git a/module/webui/themes/Dark/img/default/folder.png b/pyload/webui/themes/Dark/img/default/folder.png Binary files differindex 784e8fa48..784e8fa48 100644 --- a/module/webui/themes/Dark/img/default/folder.png +++ b/pyload/webui/themes/Dark/img/default/folder.png diff --git a/module/webui/themes/Dark/img/default/full.png b/pyload/webui/themes/Dark/img/default/full.png Binary files differindex fea52af76..fea52af76 100644 --- a/module/webui/themes/Dark/img/default/full.png +++ b/pyload/webui/themes/Dark/img/default/full.png diff --git a/module/webui/themes/Dark/img/default/head-login.png b/pyload/webui/themes/Dark/img/default/head-login.png Binary files differindex b59b7cbbf..b59b7cbbf 100644 --- a/module/webui/themes/Dark/img/default/head-login.png +++ b/pyload/webui/themes/Dark/img/default/head-login.png diff --git a/module/webui/themes/Dark/img/default/head-menu-collector.png b/pyload/webui/themes/Dark/img/default/head-menu-collector.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/head-menu-config.png b/pyload/webui/themes/Dark/img/default/head-menu-config.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/head-menu-development.png b/pyload/webui/themes/Dark/img/default/head-menu-development.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/head-menu-download.png b/pyload/webui/themes/Dark/img/default/head-menu-download.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/head-menu-home.png b/pyload/webui/themes/Dark/img/default/head-menu-home.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/head-menu-index.png b/pyload/webui/themes/Dark/img/default/head-menu-index.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/head-menu-news.png b/pyload/webui/themes/Dark/img/default/head-menu-news.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/head-menu-queue.png b/pyload/webui/themes/Dark/img/default/head-menu-queue.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/head-menu-recent.png b/pyload/webui/themes/Dark/img/default/head-menu-recent.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/head-menu-wiki.png b/pyload/webui/themes/Dark/img/default/head-menu-wiki.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/head-search-noshadow.png b/pyload/webui/themes/Dark/img/default/head-search-noshadow.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/head_bg1.png b/pyload/webui/themes/Dark/img/default/head_bg1.png Binary files differindex f2848c3cc..f2848c3cc 100644 --- a/module/webui/themes/Dark/img/default/head_bg1.png +++ b/pyload/webui/themes/Dark/img/default/head_bg1.png diff --git a/module/webui/themes/Dark/img/default/images.png b/pyload/webui/themes/Dark/img/default/images.png Binary files differindex 184860d1e..184860d1e 100644 --- a/module/webui/themes/Dark/img/default/images.png +++ b/pyload/webui/themes/Dark/img/default/images.png diff --git a/module/webui/themes/Dark/img/default/notice.png b/pyload/webui/themes/Dark/img/default/notice.png Binary files differindex 12cd1aef9..12cd1aef9 100644 --- a/module/webui/themes/Dark/img/default/notice.png +++ b/pyload/webui/themes/Dark/img/default/notice.png diff --git a/module/webui/themes/Dark/img/default/package_go.png b/pyload/webui/themes/Dark/img/default/package_go.png Binary files differindex aace63ad6..aace63ad6 100644 --- a/module/webui/themes/Dark/img/default/package_go.png +++ b/pyload/webui/themes/Dark/img/default/package_go.png diff --git a/module/webui/themes/Dark/img/default/page-tools-backlinks.png b/pyload/webui/themes/Dark/img/default/page-tools-backlinks.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/page-tools-edit.png b/pyload/webui/themes/Dark/img/default/page-tools-edit.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/page-tools-revisions.png b/pyload/webui/themes/Dark/img/default/page-tools-revisions.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/parseUri.png b/pyload/webui/themes/Dark/img/default/parseUri.png Binary files differindex 937bded9d..937bded9d 100644 --- a/module/webui/themes/Dark/img/default/parseUri.png +++ b/pyload/webui/themes/Dark/img/default/parseUri.png diff --git a/module/webui/themes/Dark/img/default/pencil.png b/pyload/webui/themes/Dark/img/default/pencil.png Binary files differindex 0bfecd50e..0bfecd50e 100644 --- a/module/webui/themes/Dark/img/default/pencil.png +++ b/pyload/webui/themes/Dark/img/default/pencil.png diff --git a/module/webui/themes/Dark/img/default/reconnect.png b/pyload/webui/themes/Dark/img/default/reconnect.png Binary files differindex 49b269145..49b269145 100644 --- a/module/webui/themes/Dark/img/default/reconnect.png +++ b/pyload/webui/themes/Dark/img/default/reconnect.png diff --git a/module/webui/themes/Dark/img/default/status_None.png b/pyload/webui/themes/Dark/img/default/status_None.png Binary files differindex 293b13f77..293b13f77 100644 --- a/module/webui/themes/Dark/img/default/status_None.png +++ b/pyload/webui/themes/Dark/img/default/status_None.png diff --git a/module/webui/themes/Dark/img/default/status_downloading.png b/pyload/webui/themes/Dark/img/default/status_downloading.png Binary files differindex fb4ebc850..fb4ebc850 100644 --- a/module/webui/themes/Dark/img/default/status_downloading.png +++ b/pyload/webui/themes/Dark/img/default/status_downloading.png diff --git a/module/webui/themes/Dark/img/default/status_failed.png b/pyload/webui/themes/Dark/img/default/status_failed.png Binary files differindex c37bd062e..c37bd062e 100644 --- a/module/webui/themes/Dark/img/default/status_failed.png +++ b/pyload/webui/themes/Dark/img/default/status_failed.png diff --git a/module/webui/themes/Dark/img/default/status_finished.png b/pyload/webui/themes/Dark/img/default/status_finished.png Binary files differindex 89c8129a4..89c8129a4 100644 --- a/module/webui/themes/Dark/img/default/status_finished.png +++ b/pyload/webui/themes/Dark/img/default/status_finished.png diff --git a/module/webui/themes/Dark/img/default/status_offline.png b/pyload/webui/themes/Dark/img/default/status_offline.png Binary files differindex 0cfd58596..0cfd58596 100644 --- a/module/webui/themes/Dark/img/default/status_offline.png +++ b/pyload/webui/themes/Dark/img/default/status_offline.png diff --git a/module/webui/themes/Dark/img/default/status_proc.png b/pyload/webui/themes/Dark/img/default/status_proc.png Binary files differindex 67de2c6cc..67de2c6cc 100644 --- a/module/webui/themes/Dark/img/default/status_proc.png +++ b/pyload/webui/themes/Dark/img/default/status_proc.png diff --git a/module/webui/themes/Dark/img/default/status_queue.png b/pyload/webui/themes/Dark/img/default/status_queue.png Binary files differindex 293b13f77..293b13f77 100644 --- a/module/webui/themes/Dark/img/default/status_queue.png +++ b/pyload/webui/themes/Dark/img/default/status_queue.png diff --git a/module/webui/themes/Dark/img/default/status_waiting.png b/pyload/webui/themes/Dark/img/default/status_waiting.png Binary files differindex 2842cc338..2842cc338 100644 --- a/module/webui/themes/Dark/img/default/status_waiting.png +++ b/pyload/webui/themes/Dark/img/default/status_waiting.png diff --git a/module/webui/themes/Dark/img/default/success.png b/pyload/webui/themes/Dark/img/default/success.png Binary files differindex 89c8129a4..89c8129a4 100644 --- a/module/webui/themes/Dark/img/default/success.png +++ b/pyload/webui/themes/Dark/img/default/success.png diff --git a/module/webui/themes/Dark/img/default/tabs-border-bottom.png b/pyload/webui/themes/Dark/img/default/tabs-border-bottom.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/user-actions-logout.png b/pyload/webui/themes/Dark/img/default/user-actions-logout.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/user-actions-profile.png b/pyload/webui/themes/Dark/img/default/user-actions-profile.png Binary files differindex 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 diff --git a/module/webui/themes/Dark/img/default/user-info.png b/pyload/webui/themes/Dark/img/default/user-info.png Binary files differindex 6e643100f..6e643100f 100644 --- a/module/webui/themes/Dark/img/default/user-info.png +++ b/pyload/webui/themes/Dark/img/default/user-info.png diff --git a/module/webui/themes/Dark/img/pyload-logo.png b/pyload/webui/themes/Dark/img/pyload-logo.png Binary files differindex e878afee5..e878afee5 100644 --- a/module/webui/themes/Dark/img/pyload-logo.png +++ b/pyload/webui/themes/Dark/img/pyload-logo.png diff --git a/module/webui/themes/Dark/img/tab-background.png b/pyload/webui/themes/Dark/img/tab-background.png Binary files differindex ee96b8407..ee96b8407 100644 --- a/module/webui/themes/Dark/img/tab-background.png +++ b/pyload/webui/themes/Dark/img/tab-background.png 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 Binary files differindex 81ebb88b2..81ebb88b2 100644 --- a/module/webui/themes/Default/img/MooDialog/dialog-close.png +++ b/pyload/webui/themes/Default/img/MooDialog/dialog-close.png diff --git a/module/webui/themes/Default/img/MooDialog/dialog-error.png b/pyload/webui/themes/Default/img/MooDialog/dialog-error.png Binary files differindex d70328403..d70328403 100644 --- a/module/webui/themes/Default/img/MooDialog/dialog-error.png +++ b/pyload/webui/themes/Default/img/MooDialog/dialog-error.png diff --git a/module/webui/themes/Default/img/MooDialog/dialog-question.png b/pyload/webui/themes/Default/img/MooDialog/dialog-question.png Binary files differindex b0af3db5b..b0af3db5b 100644 --- a/module/webui/themes/Default/img/MooDialog/dialog-question.png +++ b/pyload/webui/themes/Default/img/MooDialog/dialog-question.png diff --git a/module/webui/themes/Default/img/MooDialog/dialog-warning.png b/pyload/webui/themes/Default/img/MooDialog/dialog-warning.png Binary files differindex aad64d4be..aad64d4be 100644 --- a/module/webui/themes/Default/img/MooDialog/dialog-warning.png +++ b/pyload/webui/themes/Default/img/MooDialog/dialog-warning.png diff --git a/module/webui/themes/Default/img/add_folder.png b/pyload/webui/themes/Default/img/add_folder.png Binary files differindex 8acbc411b..8acbc411b 100644 --- a/module/webui/themes/Default/img/add_folder.png +++ b/pyload/webui/themes/Default/img/add_folder.png diff --git a/module/webui/themes/Default/img/ajax-loader.gif b/pyload/webui/themes/Default/img/ajax-loader.gif Binary files differindex 2fd8e0737..2fd8e0737 100644 --- a/module/webui/themes/Default/img/ajax-loader.gif +++ b/pyload/webui/themes/Default/img/ajax-loader.gif diff --git a/module/webui/themes/Default/img/arrow_refresh.png b/pyload/webui/themes/Default/img/arrow_refresh.png Binary files differindex 0de26566d..0de26566d 100644 --- a/module/webui/themes/Default/img/arrow_refresh.png +++ b/pyload/webui/themes/Default/img/arrow_refresh.png diff --git a/module/webui/themes/Default/img/arrow_right.png b/pyload/webui/themes/Default/img/arrow_right.png Binary files differindex b1a181923..b1a181923 100644 --- a/module/webui/themes/Default/img/arrow_right.png +++ b/pyload/webui/themes/Default/img/arrow_right.png diff --git a/module/webui/themes/Default/img/big_button.gif b/pyload/webui/themes/Default/img/big_button.gif Binary files differindex 7680490ea..7680490ea 100644 --- a/module/webui/themes/Default/img/big_button.gif +++ b/pyload/webui/themes/Default/img/big_button.gif diff --git a/module/webui/themes/Default/img/big_button_over.gif b/pyload/webui/themes/Default/img/big_button_over.gif Binary files differindex 2e3ee10d2..2e3ee10d2 100644 --- a/module/webui/themes/Default/img/big_button_over.gif +++ b/pyload/webui/themes/Default/img/big_button_over.gif diff --git a/module/webui/themes/Default/img/body.png b/pyload/webui/themes/Default/img/body.png Binary files differindex 7ff1043e0..7ff1043e0 100644 --- a/module/webui/themes/Default/img/body.png +++ b/pyload/webui/themes/Default/img/body.png diff --git a/module/webui/themes/Default/img/button.png b/pyload/webui/themes/Default/img/button.png Binary files differindex 890160614..890160614 100644 --- a/module/webui/themes/Default/img/button.png +++ b/pyload/webui/themes/Default/img/button.png diff --git a/module/webui/themes/Default/img/closebtn.gif b/pyload/webui/themes/Default/img/closebtn.gif Binary files differindex 3e27e6030..3e27e6030 100644 --- a/module/webui/themes/Default/img/closebtn.gif +++ b/pyload/webui/themes/Default/img/closebtn.gif diff --git a/module/webui/themes/Default/img/cog.png b/pyload/webui/themes/Default/img/cog.png Binary files differindex 67de2c6cc..67de2c6cc 100644 --- a/module/webui/themes/Default/img/cog.png +++ b/pyload/webui/themes/Default/img/cog.png diff --git a/module/webui/themes/Default/img/control_add.png b/pyload/webui/themes/Default/img/control_add.png Binary files differindex d39886893..d39886893 100644 --- a/module/webui/themes/Default/img/control_add.png +++ b/pyload/webui/themes/Default/img/control_add.png diff --git a/module/webui/themes/Default/img/control_add_blue.png b/pyload/webui/themes/Default/img/control_add_blue.png Binary files differindex d11b7f41d..d11b7f41d 100644 --- a/module/webui/themes/Default/img/control_add_blue.png +++ b/pyload/webui/themes/Default/img/control_add_blue.png diff --git a/module/webui/themes/Default/img/control_cancel.png b/pyload/webui/themes/Default/img/control_cancel.png Binary files differindex 7b9bc3fba..7b9bc3fba 100644 --- a/module/webui/themes/Default/img/control_cancel.png +++ b/pyload/webui/themes/Default/img/control_cancel.png diff --git a/module/webui/themes/Default/img/control_cancel_blue.png b/pyload/webui/themes/Default/img/control_cancel_blue.png Binary files differindex 0c5c96ce3..0c5c96ce3 100644 --- a/module/webui/themes/Default/img/control_cancel_blue.png +++ b/pyload/webui/themes/Default/img/control_cancel_blue.png diff --git a/module/webui/themes/Default/img/control_pause.png b/pyload/webui/themes/Default/img/control_pause.png Binary files differindex 2d9ce9c4e..2d9ce9c4e 100644 --- a/module/webui/themes/Default/img/control_pause.png +++ b/pyload/webui/themes/Default/img/control_pause.png diff --git a/module/webui/themes/Default/img/control_pause_blue.png b/pyload/webui/themes/Default/img/control_pause_blue.png Binary files differindex ec61099b0..ec61099b0 100644 --- a/module/webui/themes/Default/img/control_pause_blue.png +++ b/pyload/webui/themes/Default/img/control_pause_blue.png diff --git a/module/webui/themes/Default/img/control_play.png b/pyload/webui/themes/Default/img/control_play.png Binary files differindex 0846555d0..0846555d0 100644 --- a/module/webui/themes/Default/img/control_play.png +++ b/pyload/webui/themes/Default/img/control_play.png diff --git a/module/webui/themes/Default/img/control_play_blue.png b/pyload/webui/themes/Default/img/control_play_blue.png Binary files differindex f8c8ec683..f8c8ec683 100644 --- a/module/webui/themes/Default/img/control_play_blue.png +++ b/pyload/webui/themes/Default/img/control_play_blue.png diff --git a/module/webui/themes/Default/img/control_stop.png b/pyload/webui/themes/Default/img/control_stop.png Binary files differindex 893bb60e5..893bb60e5 100644 --- a/module/webui/themes/Default/img/control_stop.png +++ b/pyload/webui/themes/Default/img/control_stop.png diff --git a/module/webui/themes/Default/img/control_stop_blue.png b/pyload/webui/themes/Default/img/control_stop_blue.png Binary files differindex e6f75d232..e6f75d232 100644 --- a/module/webui/themes/Default/img/control_stop_blue.png +++ b/pyload/webui/themes/Default/img/control_stop_blue.png diff --git a/module/webui/themes/Default/img/delete.png b/pyload/webui/themes/Default/img/delete.png Binary files differindex 08f249365..08f249365 100644 --- a/module/webui/themes/Default/img/delete.png +++ b/pyload/webui/themes/Default/img/delete.png diff --git a/module/webui/themes/Default/img/drag_corner.gif b/pyload/webui/themes/Default/img/drag_corner.gif Binary files differindex befb1adf1..befb1adf1 100644 --- a/module/webui/themes/Default/img/drag_corner.gif +++ b/pyload/webui/themes/Default/img/drag_corner.gif diff --git a/module/webui/themes/Default/img/error.png b/pyload/webui/themes/Default/img/error.png Binary files differindex c37bd062e..c37bd062e 100644 --- a/module/webui/themes/Default/img/error.png +++ b/pyload/webui/themes/Default/img/error.png diff --git a/module/webui/themes/Default/img/folder.png b/pyload/webui/themes/Default/img/folder.png Binary files differindex 784e8fa48..784e8fa48 100644 --- a/module/webui/themes/Default/img/folder.png +++ b/pyload/webui/themes/Default/img/folder.png diff --git a/module/webui/themes/Default/img/full.png b/pyload/webui/themes/Default/img/full.png Binary files differindex fea52af76..fea52af76 100644 --- a/module/webui/themes/Default/img/full.png +++ b/pyload/webui/themes/Default/img/full.png diff --git a/module/webui/themes/Default/img/head-login.png b/pyload/webui/themes/Default/img/head-login.png Binary files differindex b59b7cbbf..b59b7cbbf 100644 --- a/module/webui/themes/Default/img/head-login.png +++ b/pyload/webui/themes/Default/img/head-login.png diff --git a/module/webui/themes/Default/img/head-menu-collector.png b/pyload/webui/themes/Default/img/head-menu-collector.png Binary files differindex 861be40bc..861be40bc 100644 --- a/module/webui/themes/Default/img/head-menu-collector.png +++ b/pyload/webui/themes/Default/img/head-menu-collector.png diff --git a/module/webui/themes/Default/img/head-menu-config.png b/pyload/webui/themes/Default/img/head-menu-config.png Binary files differindex bbf43d4f3..bbf43d4f3 100644 --- a/module/webui/themes/Default/img/head-menu-config.png +++ b/pyload/webui/themes/Default/img/head-menu-config.png diff --git a/module/webui/themes/Default/img/head-menu-development.png b/pyload/webui/themes/Default/img/head-menu-development.png Binary files differindex fad150fe1..fad150fe1 100644 --- a/module/webui/themes/Default/img/head-menu-development.png +++ b/pyload/webui/themes/Default/img/head-menu-development.png diff --git a/module/webui/themes/Default/img/head-menu-download.png b/pyload/webui/themes/Default/img/head-menu-download.png Binary files differindex 98c5da9db..98c5da9db 100644 --- a/module/webui/themes/Default/img/head-menu-download.png +++ b/pyload/webui/themes/Default/img/head-menu-download.png diff --git a/module/webui/themes/Default/img/head-menu-home.png b/pyload/webui/themes/Default/img/head-menu-home.png Binary files differindex 9d62109aa..9d62109aa 100644 --- a/module/webui/themes/Default/img/head-menu-home.png +++ b/pyload/webui/themes/Default/img/head-menu-home.png diff --git a/module/webui/themes/Default/img/head-menu-index.png b/pyload/webui/themes/Default/img/head-menu-index.png Binary files differindex 44d631064..44d631064 100644 --- a/module/webui/themes/Default/img/head-menu-index.png +++ b/pyload/webui/themes/Default/img/head-menu-index.png diff --git a/module/webui/themes/Default/img/head-menu-news.png b/pyload/webui/themes/Default/img/head-menu-news.png Binary files differindex 43950ebc9..43950ebc9 100644 --- a/module/webui/themes/Default/img/head-menu-news.png +++ b/pyload/webui/themes/Default/img/head-menu-news.png diff --git a/module/webui/themes/Default/img/head-menu-queue.png b/pyload/webui/themes/Default/img/head-menu-queue.png Binary files differindex be98793ce..be98793ce 100644 --- a/module/webui/themes/Default/img/head-menu-queue.png +++ b/pyload/webui/themes/Default/img/head-menu-queue.png diff --git a/module/webui/themes/Default/img/head-menu-recent.png b/pyload/webui/themes/Default/img/head-menu-recent.png Binary files differindex fc9b0497f..fc9b0497f 100644 --- a/module/webui/themes/Default/img/head-menu-recent.png +++ b/pyload/webui/themes/Default/img/head-menu-recent.png diff --git a/module/webui/themes/Default/img/head-menu-wiki.png b/pyload/webui/themes/Default/img/head-menu-wiki.png Binary files differindex 07cf0102d..07cf0102d 100644 --- a/module/webui/themes/Default/img/head-menu-wiki.png +++ b/pyload/webui/themes/Default/img/head-menu-wiki.png diff --git a/module/webui/themes/Default/img/head-search-noshadow.png b/pyload/webui/themes/Default/img/head-search-noshadow.png Binary files differindex aafdae015..aafdae015 100644 --- a/module/webui/themes/Default/img/head-search-noshadow.png +++ b/pyload/webui/themes/Default/img/head-search-noshadow.png diff --git a/module/webui/themes/Default/img/head_bg1.png b/pyload/webui/themes/Default/img/head_bg1.png Binary files differindex f2848c3cc..f2848c3cc 100644 --- a/module/webui/themes/Default/img/head_bg1.png +++ b/pyload/webui/themes/Default/img/head_bg1.png diff --git a/module/webui/themes/Default/img/images.png b/pyload/webui/themes/Default/img/images.png Binary files differindex 184860d1e..184860d1e 100644 --- a/module/webui/themes/Default/img/images.png +++ b/pyload/webui/themes/Default/img/images.png diff --git a/module/webui/themes/Default/img/notice.png b/pyload/webui/themes/Default/img/notice.png Binary files differindex 12cd1aef9..12cd1aef9 100644 --- a/module/webui/themes/Default/img/notice.png +++ b/pyload/webui/themes/Default/img/notice.png diff --git a/module/webui/themes/Default/img/package_go.png b/pyload/webui/themes/Default/img/package_go.png Binary files differindex aace63ad6..aace63ad6 100644 --- a/module/webui/themes/Default/img/package_go.png +++ b/pyload/webui/themes/Default/img/package_go.png diff --git a/module/webui/themes/Default/img/page-tools-backlinks.png b/pyload/webui/themes/Default/img/page-tools-backlinks.png Binary files differindex 3eb6a9ce3..3eb6a9ce3 100644 --- a/module/webui/themes/Default/img/page-tools-backlinks.png +++ b/pyload/webui/themes/Default/img/page-tools-backlinks.png diff --git a/module/webui/themes/Default/img/page-tools-edit.png b/pyload/webui/themes/Default/img/page-tools-edit.png Binary files differindex 188e1c12b..188e1c12b 100644 --- a/module/webui/themes/Default/img/page-tools-edit.png +++ b/pyload/webui/themes/Default/img/page-tools-edit.png diff --git a/module/webui/themes/Default/img/page-tools-revisions.png b/pyload/webui/themes/Default/img/page-tools-revisions.png Binary files differindex 5c3b8587f..5c3b8587f 100644 --- a/module/webui/themes/Default/img/page-tools-revisions.png +++ b/pyload/webui/themes/Default/img/page-tools-revisions.png diff --git a/module/webui/themes/Default/img/parseUri.png b/pyload/webui/themes/Default/img/parseUri.png Binary files differindex 937bded9d..937bded9d 100644 --- a/module/webui/themes/Default/img/parseUri.png +++ b/pyload/webui/themes/Default/img/parseUri.png diff --git a/module/webui/themes/Default/img/pencil.png b/pyload/webui/themes/Default/img/pencil.png Binary files differindex 0bfecd50e..0bfecd50e 100644 --- a/module/webui/themes/Default/img/pencil.png +++ b/pyload/webui/themes/Default/img/pencil.png diff --git a/module/webui/themes/Default/img/pyload-logo.png b/pyload/webui/themes/Default/img/pyload-logo.png Binary files differindex 2443cd8b1..2443cd8b1 100644 --- a/module/webui/themes/Default/img/pyload-logo.png +++ b/pyload/webui/themes/Default/img/pyload-logo.png diff --git a/module/webui/themes/Default/img/reconnect.png b/pyload/webui/themes/Default/img/reconnect.png Binary files differindex 49b269145..49b269145 100644 --- a/module/webui/themes/Default/img/reconnect.png +++ b/pyload/webui/themes/Default/img/reconnect.png diff --git a/module/webui/themes/Default/img/status_None.png b/pyload/webui/themes/Default/img/status_None.png Binary files differindex 293b13f77..293b13f77 100644 --- a/module/webui/themes/Default/img/status_None.png +++ b/pyload/webui/themes/Default/img/status_None.png diff --git a/module/webui/themes/Default/img/status_downloading.png b/pyload/webui/themes/Default/img/status_downloading.png Binary files differindex fb4ebc850..fb4ebc850 100644 --- a/module/webui/themes/Default/img/status_downloading.png +++ b/pyload/webui/themes/Default/img/status_downloading.png diff --git a/module/webui/themes/Default/img/status_failed.png b/pyload/webui/themes/Default/img/status_failed.png Binary files differindex c37bd062e..c37bd062e 100644 --- a/module/webui/themes/Default/img/status_failed.png +++ b/pyload/webui/themes/Default/img/status_failed.png diff --git a/module/webui/themes/Default/img/status_finished.png b/pyload/webui/themes/Default/img/status_finished.png Binary files differindex 89c8129a4..89c8129a4 100644 --- a/module/webui/themes/Default/img/status_finished.png +++ b/pyload/webui/themes/Default/img/status_finished.png diff --git a/module/webui/themes/Default/img/status_offline.png b/pyload/webui/themes/Default/img/status_offline.png Binary files differindex 0cfd58596..0cfd58596 100644 --- a/module/webui/themes/Default/img/status_offline.png +++ b/pyload/webui/themes/Default/img/status_offline.png diff --git a/module/webui/themes/Default/img/status_proc.png b/pyload/webui/themes/Default/img/status_proc.png Binary files differindex 67de2c6cc..67de2c6cc 100644 --- a/module/webui/themes/Default/img/status_proc.png +++ b/pyload/webui/themes/Default/img/status_proc.png diff --git a/module/webui/themes/Default/img/status_queue.png b/pyload/webui/themes/Default/img/status_queue.png Binary files differindex 293b13f77..293b13f77 100644 --- a/module/webui/themes/Default/img/status_queue.png +++ b/pyload/webui/themes/Default/img/status_queue.png diff --git a/module/webui/themes/Default/img/status_waiting.png b/pyload/webui/themes/Default/img/status_waiting.png Binary files differindex 2842cc338..2842cc338 100644 --- a/module/webui/themes/Default/img/status_waiting.png +++ b/pyload/webui/themes/Default/img/status_waiting.png diff --git a/module/webui/themes/Default/img/success.png b/pyload/webui/themes/Default/img/success.png Binary files differindex 89c8129a4..89c8129a4 100644 --- a/module/webui/themes/Default/img/success.png +++ b/pyload/webui/themes/Default/img/success.png diff --git a/module/webui/themes/Default/img/tab-background.png b/pyload/webui/themes/Default/img/tab-background.png Binary files differindex 29a5d1991..29a5d1991 100644 --- a/module/webui/themes/Default/img/tab-background.png +++ b/pyload/webui/themes/Default/img/tab-background.png diff --git a/module/webui/themes/Default/img/tabs-border-bottom.png b/pyload/webui/themes/Default/img/tabs-border-bottom.png Binary files differindex 02440f428..02440f428 100644 --- a/module/webui/themes/Default/img/tabs-border-bottom.png +++ b/pyload/webui/themes/Default/img/tabs-border-bottom.png diff --git a/module/webui/themes/Default/img/user-actions-logout.png b/pyload/webui/themes/Default/img/user-actions-logout.png Binary files differindex 0010931e2..0010931e2 100644 --- a/module/webui/themes/Default/img/user-actions-logout.png +++ b/pyload/webui/themes/Default/img/user-actions-logout.png diff --git a/module/webui/themes/Default/img/user-actions-profile.png b/pyload/webui/themes/Default/img/user-actions-profile.png Binary files differindex 46573fff6..46573fff6 100644 --- a/module/webui/themes/Default/img/user-actions-profile.png +++ b/pyload/webui/themes/Default/img/user-actions-profile.png diff --git a/module/webui/themes/Default/img/user-info.png b/pyload/webui/themes/Default/img/user-info.png Binary files differindex 6e643100f..6e643100f 100644 --- a/module/webui/themes/Default/img/user-info.png +++ b/pyload/webui/themes/Default/img/user-info.png 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 Binary files differindex 81ebb88b2..81ebb88b2 100644 --- a/module/webui/themes/Flat/img/MooDialog/dialog-close.png +++ b/pyload/webui/themes/Flat/img/MooDialog/dialog-close.png diff --git a/module/webui/themes/Flat/img/MooDialog/dialog-error.png b/pyload/webui/themes/Flat/img/MooDialog/dialog-error.png Binary files differindex d70328403..d70328403 100644 --- a/module/webui/themes/Flat/img/MooDialog/dialog-error.png +++ b/pyload/webui/themes/Flat/img/MooDialog/dialog-error.png diff --git a/module/webui/themes/Flat/img/MooDialog/dialog-question.png b/pyload/webui/themes/Flat/img/MooDialog/dialog-question.png Binary files differindex b0af3db5b..b0af3db5b 100644 --- a/module/webui/themes/Flat/img/MooDialog/dialog-question.png +++ b/pyload/webui/themes/Flat/img/MooDialog/dialog-question.png diff --git a/module/webui/themes/Flat/img/MooDialog/dialog-warning.png b/pyload/webui/themes/Flat/img/MooDialog/dialog-warning.png Binary files differindex aad64d4be..aad64d4be 100644 --- a/module/webui/themes/Flat/img/MooDialog/dialog-warning.png +++ b/pyload/webui/themes/Flat/img/MooDialog/dialog-warning.png diff --git a/module/webui/themes/Flat/img/arrow_refresh.png b/pyload/webui/themes/Flat/img/arrow_refresh.png Binary files differindex b1b6fa4dc..b1b6fa4dc 100644 --- a/module/webui/themes/Flat/img/arrow_refresh.png +++ b/pyload/webui/themes/Flat/img/arrow_refresh.png diff --git a/module/webui/themes/Flat/img/arrow_right.png b/pyload/webui/themes/Flat/img/arrow_right.png Binary files differindex 68f379fc7..68f379fc7 100644 --- a/module/webui/themes/Flat/img/arrow_right.png +++ b/pyload/webui/themes/Flat/img/arrow_right.png diff --git a/module/webui/themes/Flat/img/button.png b/pyload/webui/themes/Flat/img/button.png Binary files differindex bb408a7d6..bb408a7d6 100644 --- a/module/webui/themes/Flat/img/button.png +++ b/pyload/webui/themes/Flat/img/button.png diff --git a/module/webui/themes/Flat/img/cog.png b/pyload/webui/themes/Flat/img/cog.png Binary files differindex 833f779ac..833f779ac 100644 --- a/module/webui/themes/Flat/img/cog.png +++ b/pyload/webui/themes/Flat/img/cog.png diff --git a/module/webui/themes/Flat/img/control_add.png b/pyload/webui/themes/Flat/img/control_add.png Binary files differindex e3f29fab2..e3f29fab2 100644 --- a/module/webui/themes/Flat/img/control_add.png +++ b/pyload/webui/themes/Flat/img/control_add.png diff --git a/module/webui/themes/Flat/img/control_add_blue.png b/pyload/webui/themes/Flat/img/control_add_blue.png Binary files differindex e3f29fab2..e3f29fab2 100644 --- a/module/webui/themes/Flat/img/control_add_blue.png +++ b/pyload/webui/themes/Flat/img/control_add_blue.png diff --git a/module/webui/themes/Flat/img/control_cancel.png b/pyload/webui/themes/Flat/img/control_cancel.png Binary files differindex 07c9cad30..07c9cad30 100644 --- a/module/webui/themes/Flat/img/control_cancel.png +++ b/pyload/webui/themes/Flat/img/control_cancel.png diff --git a/module/webui/themes/Flat/img/control_cancel_blue.png b/pyload/webui/themes/Flat/img/control_cancel_blue.png Binary files differindex 07c9cad30..07c9cad30 100644 --- a/module/webui/themes/Flat/img/control_cancel_blue.png +++ b/pyload/webui/themes/Flat/img/control_cancel_blue.png diff --git a/module/webui/themes/Flat/img/control_pause.png b/pyload/webui/themes/Flat/img/control_pause.png Binary files differindex 24e3705fa..24e3705fa 100644 --- a/module/webui/themes/Flat/img/control_pause.png +++ b/pyload/webui/themes/Flat/img/control_pause.png diff --git a/module/webui/themes/Flat/img/control_pause_blue.png b/pyload/webui/themes/Flat/img/control_pause_blue.png Binary files differindex 24e3705fa..24e3705fa 100644 --- a/module/webui/themes/Flat/img/control_pause_blue.png +++ b/pyload/webui/themes/Flat/img/control_pause_blue.png diff --git a/module/webui/themes/Flat/img/control_play.png b/pyload/webui/themes/Flat/img/control_play.png Binary files differindex 15ced1e21..15ced1e21 100644 --- a/module/webui/themes/Flat/img/control_play.png +++ b/pyload/webui/themes/Flat/img/control_play.png diff --git a/module/webui/themes/Flat/img/control_play_blue.png b/pyload/webui/themes/Flat/img/control_play_blue.png Binary files differindex 15ced1e21..15ced1e21 100644 --- a/module/webui/themes/Flat/img/control_play_blue.png +++ b/pyload/webui/themes/Flat/img/control_play_blue.png diff --git a/module/webui/themes/Flat/img/control_stop.png b/pyload/webui/themes/Flat/img/control_stop.png Binary files differindex 71215ef67..71215ef67 100644 --- a/module/webui/themes/Flat/img/control_stop.png +++ b/pyload/webui/themes/Flat/img/control_stop.png diff --git a/module/webui/themes/Flat/img/control_stop_blue.png b/pyload/webui/themes/Flat/img/control_stop_blue.png Binary files differindex 71215ef67..71215ef67 100644 --- a/module/webui/themes/Flat/img/control_stop_blue.png +++ b/pyload/webui/themes/Flat/img/control_stop_blue.png diff --git a/module/webui/themes/Flat/img/default/add_folder.png b/pyload/webui/themes/Flat/img/default/add_folder.png Binary files differindex 8acbc411b..8acbc411b 100644 --- a/module/webui/themes/Flat/img/default/add_folder.png +++ b/pyload/webui/themes/Flat/img/default/add_folder.png diff --git a/module/webui/themes/Flat/img/default/ajax-loader.gif b/pyload/webui/themes/Flat/img/default/ajax-loader.gif Binary files differindex 2fd8e0737..2fd8e0737 100644 --- a/module/webui/themes/Flat/img/default/ajax-loader.gif +++ b/pyload/webui/themes/Flat/img/default/ajax-loader.gif diff --git a/module/webui/themes/Flat/img/default/big_button.gif b/pyload/webui/themes/Flat/img/default/big_button.gif Binary files differindex 7680490ea..7680490ea 100644 --- a/module/webui/themes/Flat/img/default/big_button.gif +++ b/pyload/webui/themes/Flat/img/default/big_button.gif diff --git a/module/webui/themes/Flat/img/default/big_button_over.gif b/pyload/webui/themes/Flat/img/default/big_button_over.gif Binary files differindex 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 diff --git a/module/webui/themes/Flat/img/default/body.png b/pyload/webui/themes/Flat/img/default/body.png Binary files differindex 7ff1043e0..7ff1043e0 100644 --- a/module/webui/themes/Flat/img/default/body.png +++ b/pyload/webui/themes/Flat/img/default/body.png diff --git a/module/webui/themes/Flat/img/default/closebtn.gif b/pyload/webui/themes/Flat/img/default/closebtn.gif Binary files differindex 3e27e6030..3e27e6030 100644 --- a/module/webui/themes/Flat/img/default/closebtn.gif +++ b/pyload/webui/themes/Flat/img/default/closebtn.gif diff --git a/module/webui/themes/Flat/img/default/drag_corner.gif b/pyload/webui/themes/Flat/img/default/drag_corner.gif Binary files differindex befb1adf1..befb1adf1 100644 --- a/module/webui/themes/Flat/img/default/drag_corner.gif +++ b/pyload/webui/themes/Flat/img/default/drag_corner.gif diff --git a/module/webui/themes/Flat/img/default/full.png b/pyload/webui/themes/Flat/img/default/full.png Binary files differindex fea52af76..fea52af76 100644 --- a/module/webui/themes/Flat/img/default/full.png +++ b/pyload/webui/themes/Flat/img/default/full.png diff --git a/module/webui/themes/Flat/img/default/head-menu-recent.png b/pyload/webui/themes/Flat/img/default/head-menu-recent.png Binary files differindex 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 diff --git a/module/webui/themes/Flat/img/default/head_bg1.png b/pyload/webui/themes/Flat/img/default/head_bg1.png Binary files differindex f2848c3cc..f2848c3cc 100644 --- a/module/webui/themes/Flat/img/default/head_bg1.png +++ b/pyload/webui/themes/Flat/img/default/head_bg1.png diff --git a/module/webui/themes/Flat/img/default/images.png b/pyload/webui/themes/Flat/img/default/images.png Binary files differindex 184860d1e..184860d1e 100644 --- a/module/webui/themes/Flat/img/default/images.png +++ b/pyload/webui/themes/Flat/img/default/images.png diff --git a/module/webui/themes/Flat/img/default/parseUri.png b/pyload/webui/themes/Flat/img/default/parseUri.png Binary files differindex 937bded9d..937bded9d 100644 --- a/module/webui/themes/Flat/img/default/parseUri.png +++ b/pyload/webui/themes/Flat/img/default/parseUri.png diff --git a/module/webui/themes/Flat/img/default/pyload-logo.png b/pyload/webui/themes/Flat/img/default/pyload-logo.png Binary files differindex 2443cd8b1..2443cd8b1 100644 --- a/module/webui/themes/Flat/img/default/pyload-logo.png +++ b/pyload/webui/themes/Flat/img/default/pyload-logo.png diff --git a/module/webui/themes/Flat/img/default/tab-background.png b/pyload/webui/themes/Flat/img/default/tab-background.png Binary files differindex 29a5d1991..29a5d1991 100644 --- a/module/webui/themes/Flat/img/default/tab-background.png +++ b/pyload/webui/themes/Flat/img/default/tab-background.png diff --git a/module/webui/themes/Flat/img/default/tabs-border-bottom.png b/pyload/webui/themes/Flat/img/default/tabs-border-bottom.png Binary files differindex 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 diff --git a/module/webui/themes/Flat/img/delete.png b/pyload/webui/themes/Flat/img/delete.png Binary files differindex 4539cff12..4539cff12 100644 --- a/module/webui/themes/Flat/img/delete.png +++ b/pyload/webui/themes/Flat/img/delete.png diff --git a/module/webui/themes/Flat/img/error.png b/pyload/webui/themes/Flat/img/error.png Binary files differindex 6c565c99c..6c565c99c 100644 --- a/module/webui/themes/Flat/img/error.png +++ b/pyload/webui/themes/Flat/img/error.png diff --git a/module/webui/themes/Flat/img/folder.png b/pyload/webui/themes/Flat/img/folder.png Binary files differindex 0b067dd3c..0b067dd3c 100644 --- a/module/webui/themes/Flat/img/folder.png +++ b/pyload/webui/themes/Flat/img/folder.png diff --git a/module/webui/themes/Flat/img/head-login.png b/pyload/webui/themes/Flat/img/head-login.png Binary files differindex 6b57515bc..6b57515bc 100644 --- a/module/webui/themes/Flat/img/head-login.png +++ b/pyload/webui/themes/Flat/img/head-login.png diff --git a/module/webui/themes/Flat/img/head-menu-collector.png b/pyload/webui/themes/Flat/img/head-menu-collector.png Binary files differindex bbcbe6406..bbcbe6406 100644 --- a/module/webui/themes/Flat/img/head-menu-collector.png +++ b/pyload/webui/themes/Flat/img/head-menu-collector.png diff --git a/module/webui/themes/Flat/img/head-menu-config.png b/pyload/webui/themes/Flat/img/head-menu-config.png Binary files differindex 93e8f83ac..93e8f83ac 100644 --- a/module/webui/themes/Flat/img/head-menu-config.png +++ b/pyload/webui/themes/Flat/img/head-menu-config.png diff --git a/module/webui/themes/Flat/img/head-menu-development.png b/pyload/webui/themes/Flat/img/head-menu-development.png Binary files differindex 33d8b062f..33d8b062f 100644 --- a/module/webui/themes/Flat/img/head-menu-development.png +++ b/pyload/webui/themes/Flat/img/head-menu-development.png diff --git a/module/webui/themes/Flat/img/head-menu-download.png b/pyload/webui/themes/Flat/img/head-menu-download.png Binary files differindex 3691deebc..3691deebc 100644 --- a/module/webui/themes/Flat/img/head-menu-download.png +++ b/pyload/webui/themes/Flat/img/head-menu-download.png diff --git a/module/webui/themes/Flat/img/head-menu-home.png b/pyload/webui/themes/Flat/img/head-menu-home.png Binary files differindex b77bef5eb..b77bef5eb 100644 --- a/module/webui/themes/Flat/img/head-menu-home.png +++ b/pyload/webui/themes/Flat/img/head-menu-home.png diff --git a/module/webui/themes/Flat/img/head-menu-index.png b/pyload/webui/themes/Flat/img/head-menu-index.png Binary files differindex 8bc6e9604..8bc6e9604 100644 --- a/module/webui/themes/Flat/img/head-menu-index.png +++ b/pyload/webui/themes/Flat/img/head-menu-index.png diff --git a/module/webui/themes/Flat/img/head-menu-news.png b/pyload/webui/themes/Flat/img/head-menu-news.png Binary files differindex 44e79a9a9..44e79a9a9 100644 --- a/module/webui/themes/Flat/img/head-menu-news.png +++ b/pyload/webui/themes/Flat/img/head-menu-news.png diff --git a/module/webui/themes/Flat/img/head-menu-queue.png b/pyload/webui/themes/Flat/img/head-menu-queue.png Binary files differindex e4fa41ad8..e4fa41ad8 100644 --- a/module/webui/themes/Flat/img/head-menu-queue.png +++ b/pyload/webui/themes/Flat/img/head-menu-queue.png diff --git a/module/webui/themes/Flat/img/head-menu-wiki.png b/pyload/webui/themes/Flat/img/head-menu-wiki.png Binary files differindex 61b0e54ea..61b0e54ea 100644 --- a/module/webui/themes/Flat/img/head-menu-wiki.png +++ b/pyload/webui/themes/Flat/img/head-menu-wiki.png diff --git a/module/webui/themes/Flat/img/head-search-noshadow.png b/pyload/webui/themes/Flat/img/head-search-noshadow.png Binary files differindex 16d39bd06..16d39bd06 100644 --- a/module/webui/themes/Flat/img/head-search-noshadow.png +++ b/pyload/webui/themes/Flat/img/head-search-noshadow.png diff --git a/module/webui/themes/Flat/img/notice.png b/pyload/webui/themes/Flat/img/notice.png Binary files differindex a52b067cb..a52b067cb 100644 --- a/module/webui/themes/Flat/img/notice.png +++ b/pyload/webui/themes/Flat/img/notice.png diff --git a/module/webui/themes/Flat/img/package_go.png b/pyload/webui/themes/Flat/img/package_go.png Binary files differindex 80b2c42ee..80b2c42ee 100644 --- a/module/webui/themes/Flat/img/package_go.png +++ b/pyload/webui/themes/Flat/img/package_go.png diff --git a/module/webui/themes/Flat/img/page-tools-backlinks.png b/pyload/webui/themes/Flat/img/page-tools-backlinks.png Binary files differindex fb8f55b38..fb8f55b38 100644 --- a/module/webui/themes/Flat/img/page-tools-backlinks.png +++ b/pyload/webui/themes/Flat/img/page-tools-backlinks.png diff --git a/module/webui/themes/Flat/img/page-tools-edit.png b/pyload/webui/themes/Flat/img/page-tools-edit.png Binary files differindex 67177cf89..67177cf89 100644 --- a/module/webui/themes/Flat/img/page-tools-edit.png +++ b/pyload/webui/themes/Flat/img/page-tools-edit.png diff --git a/module/webui/themes/Flat/img/page-tools-revisions.png b/pyload/webui/themes/Flat/img/page-tools-revisions.png Binary files differindex 088fe0087..088fe0087 100644 --- a/module/webui/themes/Flat/img/page-tools-revisions.png +++ b/pyload/webui/themes/Flat/img/page-tools-revisions.png diff --git a/module/webui/themes/Flat/img/pencil.png b/pyload/webui/themes/Flat/img/pencil.png Binary files differindex e39c93cd8..e39c93cd8 100644 --- a/module/webui/themes/Flat/img/pencil.png +++ b/pyload/webui/themes/Flat/img/pencil.png diff --git a/module/webui/themes/Flat/img/reconnect.png b/pyload/webui/themes/Flat/img/reconnect.png Binary files differindex cd35c9325..cd35c9325 100644 --- a/module/webui/themes/Flat/img/reconnect.png +++ b/pyload/webui/themes/Flat/img/reconnect.png diff --git a/module/webui/themes/Flat/img/status_None.png b/pyload/webui/themes/Flat/img/status_None.png Binary files differindex 1400d3eb3..1400d3eb3 100644 --- a/module/webui/themes/Flat/img/status_None.png +++ b/pyload/webui/themes/Flat/img/status_None.png diff --git a/module/webui/themes/Flat/img/status_downloading.png b/pyload/webui/themes/Flat/img/status_downloading.png Binary files differindex db8ad8cd6..db8ad8cd6 100644 --- a/module/webui/themes/Flat/img/status_downloading.png +++ b/pyload/webui/themes/Flat/img/status_downloading.png diff --git a/module/webui/themes/Flat/img/status_failed.png b/pyload/webui/themes/Flat/img/status_failed.png Binary files differindex 6c565c99c..6c565c99c 100644 --- a/module/webui/themes/Flat/img/status_failed.png +++ b/pyload/webui/themes/Flat/img/status_failed.png diff --git a/module/webui/themes/Flat/img/status_finished.png b/pyload/webui/themes/Flat/img/status_finished.png Binary files differindex 2c4aca40d..2c4aca40d 100644 --- a/module/webui/themes/Flat/img/status_finished.png +++ b/pyload/webui/themes/Flat/img/status_finished.png diff --git a/module/webui/themes/Flat/img/status_offline.png b/pyload/webui/themes/Flat/img/status_offline.png Binary files differindex 6c565c99c..6c565c99c 100644 --- a/module/webui/themes/Flat/img/status_offline.png +++ b/pyload/webui/themes/Flat/img/status_offline.png diff --git a/module/webui/themes/Flat/img/status_proc.png b/pyload/webui/themes/Flat/img/status_proc.png Binary files differindex 833f779ac..833f779ac 100644 --- a/module/webui/themes/Flat/img/status_proc.png +++ b/pyload/webui/themes/Flat/img/status_proc.png diff --git a/module/webui/themes/Flat/img/status_queue.png b/pyload/webui/themes/Flat/img/status_queue.png Binary files differindex 1400d3eb3..1400d3eb3 100644 --- a/module/webui/themes/Flat/img/status_queue.png +++ b/pyload/webui/themes/Flat/img/status_queue.png diff --git a/module/webui/themes/Flat/img/status_waiting.png b/pyload/webui/themes/Flat/img/status_waiting.png Binary files differindex fd038175e..fd038175e 100644 --- a/module/webui/themes/Flat/img/status_waiting.png +++ b/pyload/webui/themes/Flat/img/status_waiting.png diff --git a/module/webui/themes/Flat/img/success.png b/pyload/webui/themes/Flat/img/success.png Binary files differindex 2c4aca40d..2c4aca40d 100644 --- a/module/webui/themes/Flat/img/success.png +++ b/pyload/webui/themes/Flat/img/success.png diff --git a/module/webui/themes/Flat/img/user-actions-logout.png b/pyload/webui/themes/Flat/img/user-actions-logout.png Binary files differindex d4ef360e8..d4ef360e8 100644 --- a/module/webui/themes/Flat/img/user-actions-logout.png +++ b/pyload/webui/themes/Flat/img/user-actions-logout.png diff --git a/module/webui/themes/Flat/img/user-actions-profile.png b/pyload/webui/themes/Flat/img/user-actions-profile.png Binary files differindex 9ec410b13..9ec410b13 100644 --- a/module/webui/themes/Flat/img/user-actions-profile.png +++ b/pyload/webui/themes/Flat/img/user-actions-profile.png diff --git a/module/webui/themes/Flat/img/user-info.png b/pyload/webui/themes/Flat/img/user-info.png Binary files differindex 345ed52e4..345ed52e4 100644 --- a/module/webui/themes/Flat/img/user-info.png +++ b/pyload/webui/themes/Flat/img/user-info.png 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  | 
