-added support for diskfiles

-added support for streamin
-improved simplypremium

git-svn-id: svn://svn.jdownloader.org/jdownloader/trunk@25221 ebf7c1c2-ba36-0410-9fe8-c592906822b4
This commit is contained in:
psp 2014-04-30 14:16:52 +00:00
parent 3d9f24cc9d
commit 858049b093
3 changed files with 1795 additions and 1 deletions

View File

@ -0,0 +1,984 @@
//jDownloader - Downloadmanager
//Copyright (C) 2013 JD-Team support@jdownloader.org
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program. If not, see <http://www.gnu.org/licenses/>.
package jd.plugins.hoster;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
import jd.PluginWrapper;
import jd.config.Property;
import jd.http.Browser;
import jd.http.Cookie;
import jd.http.Cookies;
import jd.http.URLConnectionAdapter;
import jd.nutils.encoding.Encoding;
import jd.parser.Regex;
import jd.parser.html.Form;
import jd.parser.html.HTMLParser;
import jd.parser.html.InputField;
import jd.plugins.Account;
import jd.plugins.AccountInfo;
import jd.plugins.DownloadLink;
import jd.plugins.DownloadLink.AvailableStatus;
import jd.plugins.HostPlugin;
import jd.plugins.LinkStatus;
import jd.plugins.Plugin;
import jd.plugins.PluginException;
import jd.plugins.PluginForDecrypt;
import jd.plugins.PluginForHost;
import jd.plugins.hoster.DdlStorageCom.StringContainer;
import jd.utils.JDUtilities;
import jd.utils.locale.JDL;
import org.appwork.utils.formatter.SizeFormatter;
import org.appwork.utils.formatter.TimeFormatter;
@HostPlugin(revision = "$Revision$", interfaceVersion = 2, names = { "diskfiles.net" }, urls = { "https?://(www\\.)?diskfiles\\.net/(vidembed\\-)?[a-z0-9]{12}" }, flags = { 2 })
public class DiskFilesNet extends PluginForHost {
private String correctedBR = "";
private String passCode = null;
private static final String PASSWORDTEXT = "<br><b>Passwor(d|t):</b> <input";
/* primary website url, take note of redirects */
private static final String COOKIE_HOST = "http://diskfiles.net";
private static final String NICE_HOST = COOKIE_HOST.replaceAll("(https://|http://)", "");
private static final String NICE_HOSTproperty = COOKIE_HOST.replaceAll("(https://|http://|\\.|\\-)", "");
/* domain names used within download links */
private static final String DOMAINS = "(diskfiles\\.net)";
private static final String MAINTENANCE = ">This server is in maintenance mode";
private static final String MAINTENANCEUSERTEXT = JDL.L("hoster.xfilesharingprobasic.errors.undermaintenance", "This server is under maintenance");
private static final String ALLWAIT_SHORT = JDL.L("hoster.xfilesharingprobasic.errors.waitingfordownloads", "Waiting till new downloads can be started");
private static final String PREMIUMONLY1 = JDL.L("hoster.xfilesharingprobasic.errors.premiumonly1", "Max downloadable filesize for free users:");
private static final String PREMIUMONLY2 = JDL.L("hoster.xfilesharingprobasic.errors.premiumonly2", "Only downloadable via premium or registered");
private static final boolean VIDEOHOSTER = false;
private static final boolean VIDEOHOSTER_2 = false;
private static final boolean SUPPORTSHTTPS = false;
private final boolean ENABLE_RANDOM_UA = false;
private static StringContainer agent = new StringContainer();
/* Connection stuff */
private static final boolean FREE_RESUME = true;
private static final int FREE_MAXCHUNKS = 1;
private static final int FREE_MAXDOWNLOADS = 1;
private static final boolean ACCOUNT_FREE_RESUME = true;
private static final int ACCOUNT_FREE_MAXCHUNKS = 1;
private static final int ACCOUNT_FREE_MAXDOWNLOADS = 1;
private static final boolean ACCOUNT_PREMIUM_RESUME = true;
private static final int ACCOUNT_PREMIUM_MAXCHUNKS = 0;
private static final int ACCOUNT_PREMIUM_MAXDOWNLOADS = 20;
/* note: CAN NOT be negative or zero! (ie. -1 or 0) Otherwise math sections fail. .:. use [1-20] */
private static AtomicInteger totalMaxSimultanFreeDownload = new AtomicInteger(FREE_MAXDOWNLOADS);
/* don't touch the following! */
private static AtomicInteger maxFree = new AtomicInteger(1);
private static AtomicInteger maxPrem = new AtomicInteger(1);
private static Object LOCK = new Object();
private String fuid = null;
/* DEV NOTES */
// XfileSharingProBasic Version 2.6.5.8
// mods:
// limit-info: free acc untested
// protocol: no https
// captchatype: null
// other:
@Override
public void correctDownloadLink(final DownloadLink link) {
/* link cleanup, but respect users protocol choosing */
if (!SUPPORTSHTTPS) {
link.setUrlDownload(link.getDownloadURL().replaceFirst("https://", "http://"));
}
final String fid = new Regex(link.getDownloadURL(), "([a-z0-9]{12})$").getMatch(0);
link.setUrlDownload(COOKIE_HOST + "/" + fid);
}
@Override
public String getAGBLink() {
return COOKIE_HOST + "/tos.html";
}
public DiskFilesNet(PluginWrapper wrapper) {
super(wrapper);
this.enablePremium(COOKIE_HOST + "/premium.html");
}
@Override
public AvailableStatus requestFileInformation(final DownloadLink link) throws Exception {
br.setFollowRedirects(true);
prepBrowser(br);
setFUID(link);
getPage(link.getDownloadURL());
if (new Regex(correctedBR, "(No such file|>File Not Found<|>The file was removed by|Reason for deletion:\n)").matches()) throw new PluginException(LinkStatus.ERROR_FILE_NOT_FOUND);
if (new Regex(correctedBR, MAINTENANCE).matches()) {
link.getLinkStatus().setStatusText(MAINTENANCEUSERTEXT);
return AvailableStatus.UNCHECKABLE;
}
if (br.getURL().contains("/?op=login&redirect=")) {
link.getLinkStatus().setStatusText(PREMIUMONLY2);
return AvailableStatus.UNCHECKABLE;
}
final String[] fileInfo = new String[3];
scanInfo(fileInfo);
if (fileInfo[0] == null || fileInfo[0].equals("")) {
if (correctedBR.contains("You have reached the download(\\-| )limit")) {
logger.warning("Waittime detected, please reconnect to make the linkchecker work!");
return AvailableStatus.UNCHECKABLE;
}
logger.warning("filename equals null, throwing \"plugin defect\"");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
if (fileInfo[2] != null && !fileInfo[2].equals("")) link.setMD5Hash(fileInfo[2].trim());
fileInfo[0] = fileInfo[0].replaceAll("(</b>|<b>|\\.html)", "");
link.setName(fileInfo[0].trim());
if (fileInfo[1] != null && !fileInfo[1].equals("")) link.setDownloadSize(SizeFormatter.getSize(fileInfo[1]));
return AvailableStatus.TRUE;
}
private String[] scanInfo(final String[] fileInfo) {
/* standard traits from base page */
if (fileInfo[0] == null) {
fileInfo[0] = new Regex(correctedBR, "You have requested.*?https?://(www\\.)?" + DOMAINS + "/" + fuid + "/(.*?)</font>").getMatch(2);
if (fileInfo[0] == null) {
fileInfo[0] = new Regex(correctedBR, "fname\"( type=\"hidden\")? value=\"(.*?)\"").getMatch(1);
if (fileInfo[0] == null) {
fileInfo[0] = new Regex(correctedBR, "<h2>Download File(.*?)</h2>").getMatch(0);
/* traits from download1 page below */
if (fileInfo[0] == null) {
fileInfo[0] = new Regex(correctedBR, "Filename:? ?(<[^>]+> ?)+?([^<>\"\\']+)").getMatch(1);
// next two are details from sharing box
if (fileInfo[0] == null) {
fileInfo[0] = new Regex(correctedBR, "copy\\(this\\);.+>(.+) \\- [\\d\\.]+ (KB|MB|GB)</a></textarea>[\r\n\t ]+</div>").getMatch(0);
if (fileInfo[0] == null) {
fileInfo[0] = new Regex(correctedBR, "copy\\(this\\);.+\\](.+) \\- [\\d\\.]+ (KB|MB|GB)\\[/URL\\]").getMatch(0);
if (fileInfo[0] == null) {
/* Link of the box without filesize */
fileInfo[0] = new Regex(correctedBR, "onFocus=\"copy\\(this\\);\">http://(www\\.)?" + DOMAINS + "/" + fuid + "/([^<>\"]*?)</textarea").getMatch(2);
}
}
}
}
}
}
}
if (fileInfo[1] == null) {
fileInfo[1] = new Regex(correctedBR, "\\(([0-9]+ bytes)\\)").getMatch(0);
if (fileInfo[1] == null) {
fileInfo[1] = new Regex(correctedBR, "</font>[ ]+\\(([^<>\"\\'/]+)\\)(.*?)</font>").getMatch(0);
if (fileInfo[1] == null) {
fileInfo[1] = new Regex(correctedBR, "(\\d+(\\.\\d+)? ?(KB|MB|GB))").getMatch(0);
}
}
}
if (fileInfo[2] == null) fileInfo[2] = new Regex(correctedBR, "<b>MD5.*?</b>.*?nowrap>(.*?)<").getMatch(0);
return fileInfo;
}
@Override
public void handleFree(final DownloadLink downloadLink) throws Exception, PluginException {
requestFileInformation(downloadLink);
doFree(downloadLink, FREE_RESUME, FREE_MAXCHUNKS, "freelink");
}
@SuppressWarnings("unused")
public void doFree(final DownloadLink downloadLink, final boolean resumable, final int maxchunks, final String directlinkproperty) throws Exception, PluginException {
br.setFollowRedirects(false);
passCode = downloadLink.getStringProperty("pass");
/* First, bring up saved final links */
String dllink = checkDirectLink(downloadLink, directlinkproperty);
/* Second, check for streaming/direct links on the first page */
if (dllink == null) dllink = getDllink();
/* Third, do they provide video hosting? */
if (dllink == null && VIDEOHOSTER) {
try {
logger.info("Trying to get link via vidembed");
final Browser brv = br.cloneBrowser();
brv.getPage("/vidembed-" + fuid);
dllink = brv.getRedirectLocation();
if (dllink == null)
logger.info("Failed to get link via vidembed");
else
logger.info("Successfully found link via vidembed");
} catch (final Throwable e) {
logger.info("Failed to get link via vidembed");
}
}
if (dllink == null && VIDEOHOSTER_2) {
try {
logger.info("Trying to get link via embed");
final String embed_access = "http://" + COOKIE_HOST.replace("http://", "") + "/embed-" + fuid + ".html";
this.postPage(embed_access, "op=video_embed3&usr_login=&id2=" + fuid + "&fname=" + Encoding.urlEncode(downloadLink.getName()) + "&referer=&file_code=" + fuid + "&method_free=Click+here+to+watch+the+Video");
// brv.getPage("http://grifthost.com/embed-" + fuid + ".html");
dllink = getDllink();
if (dllink == null)
logger.info("Failed to get link via embed");
else
logger.info("Successfully found link via embed");
} catch (final Throwable e) {
logger.info("Failed to get link via embed");
}
if (dllink == null) getPage(downloadLink.getDownloadURL());
}
/* Fourth, continue like normal */
if (dllink == null) {
checkErrors(downloadLink, false);
final Form download1 = getFormByKey("op", "download1");
if (download1 != null) {
download1.remove("method_premium");
/* stable is lame, issue finding input data fields correctly. eg. closes at ' quotation mark - remove when jd2 goes stable! */
if (downloadLink.getName().contains("'")) {
String fname = new Regex(br, "<input type=\"hidden\" name=\"fname\" value=\"([^\"]+)\">").getMatch(0);
if (fname != null) {
download1.put("fname", Encoding.urlEncode(fname));
} else {
logger.warning("Could not find 'fname'");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
}
/* end of backward compatibility */
download1.put("method_free", "Free+User");
sendForm(download1);
checkErrors(downloadLink, false);
dllink = getDllink();
}
}
if (dllink == null) {
Form dlForm = br.getFormbyProperty("name", "F1");
if (dlForm == null) {
handlePluginBroken(downloadLink, "dlform_f1_null", 3);
}
/* how many forms deep do you want to try? */
int repeat = 2;
for (int i = 0; i <= repeat; i++) {
dlForm.remove(null);
final long timeBefore = System.currentTimeMillis();
boolean password = false;
boolean skipWaittime = false;
if (new Regex(correctedBR, PASSWORDTEXT).matches()) {
password = true;
logger.info("The downloadlink seems to be password protected.");
}
/* md5 can be on the subsequent pages - it is to be found very rare in current XFS versions */
if (downloadLink.getMD5Hash() == null) {
String md5hash = new Regex(correctedBR, "<b>MD5.*?</b>.*?nowrap>(.*?)<").getMatch(0);
if (md5hash != null) downloadLink.setMD5Hash(md5hash.trim());
}
/* Captcha START */
if (correctedBR.contains(";background:#ccc;text-align")) {
logger.info("Detected captcha method \"plaintext captchas\" for this host");
/* Captcha method by ManiacMansion */
final String[][] letters = new Regex(br, "<span style=\\'position:absolute;padding\\-left:(\\d+)px;padding\\-top:\\d+px;\\'>(&#\\d+;)</span>").getMatches();
if (letters == null || letters.length == 0) {
logger.warning("plaintext captchahandling broken!");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
final SortedMap<Integer, String> capMap = new TreeMap<Integer, String>();
for (String[] letter : letters) {
capMap.put(Integer.parseInt(letter[0]), Encoding.htmlDecode(letter[1]));
}
final StringBuilder code = new StringBuilder();
for (String value : capMap.values()) {
code.append(value);
}
dlForm.put("code", code.toString());
logger.info("Put captchacode " + code.toString() + " obtained by captcha metod \"plaintext captchas\" in the form.");
} else if (correctedBR.contains("/captchas/")) {
logger.info("Detected captcha method \"Standard captcha\" for this host");
final String[] sitelinks = HTMLParser.getHttpLinks(br.toString(), null);
String captchaurl = null;
if (sitelinks == null || sitelinks.length == 0) {
logger.warning("Standard captcha captchahandling broken!");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
for (String link : sitelinks) {
if (link.contains("/captchas/")) {
captchaurl = link;
break;
}
}
if (captchaurl == null) {
logger.warning("Standard captcha captchahandling broken!");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
String code = getCaptchaCode("xfilesharingprobasic", captchaurl, downloadLink);
dlForm.put("code", code);
logger.info("Put captchacode " + code + " obtained by captcha metod \"Standard captcha\" in the form.");
} else if (new Regex(correctedBR, "(api\\.recaptcha\\.net|google\\.com/recaptcha/api/)").matches()) {
logger.info("Detected captcha method \"Re Captcha\" for this host");
final PluginForHost recplug = JDUtilities.getPluginForHost("DirectHTTP");
final jd.plugins.hoster.DirectHTTP.Recaptcha rc = ((DirectHTTP) recplug).getReCaptcha(br);
rc.findID();
rc.load();
final File cf = rc.downloadCaptcha(getLocalCaptchaFile());
final String c = getCaptchaCode(cf, downloadLink);
dlForm.put("recaptcha_challenge_field", rc.getChallenge());
dlForm.put("recaptcha_response_field", Encoding.urlEncode(c));
logger.info("Put captchacode " + c + " obtained by captcha metod \"Re Captcha\" in the form and submitted it.");
/* wait time is usually skippable for reCaptcha handling */
skipWaittime = true;
} else if (br.containsHTML("solvemedia\\.com/papi/")) {
logger.info("Detected captcha method \"solvemedia\" for this host");
final PluginForDecrypt solveplug = JDUtilities.getPluginForDecrypt("linkcrypt.ws");
final jd.plugins.decrypter.LnkCrptWs.SolveMedia sm = ((jd.plugins.decrypter.LnkCrptWs) solveplug).getSolveMedia(br);
File cf = null;
try {
cf = sm.downloadCaptcha(getLocalCaptchaFile());
} catch (final Exception e) {
if (jd.plugins.decrypter.LnkCrptWs.SolveMedia.FAIL_CAUSE_CKEY_MISSING.equals(e.getMessage())) throw new PluginException(LinkStatus.ERROR_FATAL, "Host side solvemedia.com captcha error - please contact the " + this.getHost() + " support");
throw e;
}
final String code = getCaptchaCode(cf, downloadLink);
final String chid = sm.getChallenge(code);
dlForm.put("adcopy_challenge", chid);
dlForm.put("adcopy_response", "manual_challenge");
} else if (br.containsHTML("id=\"capcode\" name= \"capcode\"")) {
logger.info("Detected captcha method \"keycaptca\"");
String result = null;
final PluginForDecrypt keycplug = JDUtilities.getPluginForDecrypt("linkcrypt.ws");
try {
final jd.plugins.decrypter.LnkCrptWs.KeyCaptcha kc = ((jd.plugins.decrypter.LnkCrptWs) keycplug).getKeyCaptcha(br);
result = kc.showDialog(downloadLink.getDownloadURL());
} catch (final Throwable e) {
result = null;
}
if (result == null) throw new PluginException(LinkStatus.ERROR_CAPTCHA);
if ("CANCEL".equals(result)) throw new PluginException(LinkStatus.ERROR_FATAL);
dlForm.put("capcode", result);
skipWaittime = false;
}
/* Captcha END */
if (password) passCode = handlePassword(dlForm, downloadLink);
if (!skipWaittime) waitTime(timeBefore, downloadLink);
sendForm(dlForm);
logger.info("Submitted DLForm");
checkErrors(downloadLink, true);
dllink = getDllink();
if (dllink == null && (!br.containsHTML("<Form name=\"F1\" method=\"POST\" action=\"\"") || i == repeat)) {
logger.warning("Final downloadlink (String is \"dllink\") regex didn't match!");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
} else if (dllink == null && br.containsHTML("<Form name=\"F1\" method=\"POST\" action=\"\"")) {
dlForm = br.getFormbyProperty("name", "F1");
try {
invalidateLastChallengeResponse();
} catch (final Throwable e) {
}
continue;
} else {
try {
validateLastChallengeResponse();
} catch (final Throwable e) {
}
break;
}
}
}
logger.info("Final downloadlink = " + dllink + " starting the download...");
dl = jd.plugins.BrowserAdapter.openDownload(br, downloadLink, dllink, resumable, maxchunks);
if (dl.getConnection().getContentType().contains("html")) {
if (dl.getConnection().getResponseCode() == 503) throw new PluginException(LinkStatus.ERROR_HOSTER_TEMPORARILY_UNAVAILABLE, "Connection limit reached, please contact our support!", 5 * 60 * 1000l);
logger.warning("The final dllink seems not to be a file!");
br.followConnection();
correctBR();
checkServerErrors();
handlePluginBroken(downloadLink, "dllinknofile", 3);
}
downloadLink.setProperty(directlinkproperty, dllink);
fixFilename(downloadLink);
try {
/* add a download slot */
controlFree(+1);
/* start the dl */
dl.startDownload();
} finally {
/* remove download slot */
controlFree(-1);
}
}
@Override
public int getMaxSimultanFreeDownloadNum() {
return maxFree.get();
}
/* do not add @Override here to keep 0.* compatibility */
public boolean hasAutoCaptcha() {
return true;
}
/* NO OVERRIDE!! We need to stay 0.9*compatible */
public boolean hasCaptcha(DownloadLink link, jd.plugins.Account acc) {
if (acc == null) {
/* no account, yes we can expect captcha */
return true;
}
if (Boolean.TRUE.equals(acc.getBooleanProperty("nopremium"))) {
/* free accounts also have captchas */
return true;
}
return false;
}
private void prepBrowser(final Browser br) {
/* define custom browser headers and language settings */
br.getHeaders().put("Accept-Language", "en-gb, en;q=0.9");
br.setCookie(COOKIE_HOST, "lang", "english");
if (ENABLE_RANDOM_UA) {
if (agent.string == null) {
/* we first have to load the plugin, before we can reference it */
JDUtilities.getPluginForHost("mediafire.com");
agent.string = jd.plugins.hoster.MediafireCom.stringUserAgent();
}
br.getHeaders().put("User-Agent", agent.string);
}
}
/**
* Prevents more than one free download from starting at a given time. One step prior to dl.startDownload(), it adds a slot to maxFree
* which allows the next singleton download to start, or at least try.
*
* This is needed because xfileshare(website) only throws errors after a final dllink starts transferring or at a given step within pre
* download sequence. But this template(XfileSharingProBasic) allows multiple slots(when available) to commence the download sequence,
* this.setstartintival does not resolve this issue. Which results in x(20) captcha events all at once and only allows one download to
* start. This prevents wasting peoples time and effort on captcha solving and|or wasting captcha trading credits. Users will experience
* minimal harm to downloading as slots are freed up soon as current download begins.
*
* @param controlFree
* (+1|-1)
*/
public synchronized void controlFree(final int num) {
logger.info("maxFree was = " + maxFree.get());
maxFree.set(Math.min(Math.max(1, maxFree.addAndGet(num)), totalMaxSimultanFreeDownload.get()));
logger.info("maxFree now = " + maxFree.get());
}
/* Removes HTML code which could break the plugin */
public void correctBR() throws NumberFormatException, PluginException {
correctedBR = br.toString();
ArrayList<String> regexStuff = new ArrayList<String>();
// remove custom rules first!!! As html can change because of generic cleanup rules.
/* generic cleanup */
regexStuff.add("<\\!(\\-\\-.*?\\-\\-)>");
regexStuff.add("(display: ?none;\">.*?</div>)");
regexStuff.add("(visibility:hidden>.*?<)");
for (String aRegex : regexStuff) {
String results[] = new Regex(correctedBR, aRegex).getColumn(0);
if (results != null) {
for (String result : results) {
correctedBR = correctedBR.replace(result, "");
}
}
}
}
public String getDllink() {
String dllink = br.getRedirectLocation();
if (dllink == null) {
dllink = new Regex(correctedBR, "(\"|\\')(https?://(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|([\\w\\-\\.]+\\.)?" + DOMAINS + ")(:\\d{1,4})?/(files|d|cgi\\-bin/dl\\.cgi)/(\\d+/)?[a-z0-9]+/[^<>\"/]*?)(\"|\\')").getMatch(1);
if (dllink == null) {
final String cryptedScripts[] = new Regex(correctedBR, "p\\}\\((.*?)\\.split\\('\\|'\\)").getColumn(0);
if (cryptedScripts != null && cryptedScripts.length != 0) {
for (String crypted : cryptedScripts) {
dllink = decodeDownloadLink(crypted);
if (dllink != null) break;
}
}
}
}
return dllink;
}
private String decodeDownloadLink(final String s) {
String decoded = null;
try {
Regex params = new Regex(s, "\\'(.*?[^\\\\])\\',(\\d+),(\\d+),\\'(.*?)\\'");
String p = params.getMatch(0).replaceAll("\\\\", "");
int a = Integer.parseInt(params.getMatch(1));
int c = Integer.parseInt(params.getMatch(2));
String[] k = params.getMatch(3).split("\\|");
while (c != 0) {
c--;
if (k[c].length() != 0) p = p.replaceAll("\\b" + Integer.toString(c, a) + "\\b", k[c]);
}
decoded = p;
} catch (Exception e) {
}
String finallink = null;
if (decoded != null) {
/* Open regex is possible because in the unpacked JS there are usually only 1 links */
finallink = new Regex(decoded, "(\"|\\')(https?://[^<>\"\\']*?\\.(mp4|flv))(\"|\\')").getMatch(1);
}
return finallink;
}
private String checkDirectLink(final DownloadLink downloadLink, final String property) {
String dllink = downloadLink.getStringProperty(property);
if (dllink != null) {
try {
final Browser br2 = br.cloneBrowser();
URLConnectionAdapter con = br2.openGetConnection(dllink);
if (con.getContentType().contains("html") || con.getLongContentLength() == -1) {
downloadLink.setProperty(property, Property.NULL);
dllink = null;
}
con.disconnect();
} catch (final Exception e) {
downloadLink.setProperty(property, Property.NULL);
dllink = null;
}
}
return dllink;
}
private void getPage(final String page) throws Exception {
br.getPage(page);
correctBR();
}
@SuppressWarnings("unused")
private void postPage(final String page, final String postdata) throws Exception {
br.postPage(page, postdata);
correctBR();
}
private void sendForm(final Form form) throws Exception {
br.submitForm(form);
correctBR();
}
private void waitTime(long timeBefore, final DownloadLink downloadLink) throws PluginException {
int passedTime = (int) ((System.currentTimeMillis() - timeBefore) / 1000) - 1;
/** Ticket Time */
final String ttt = new Regex(correctedBR, "id=\"countdown_str\">[^<>\"]+<span id=\"[^<>\"]+\"( class=\"[^<>\"]+\")?>([\n ]+)?(\\d+)([\n ]+)?</span>").getMatch(2);
if (ttt != null) {
int wait = Integer.parseInt(ttt);
wait -= passedTime;
logger.info("[Seconds] Waittime on the page: " + ttt);
logger.info("[Seconds] Passed time: " + passedTime);
logger.info("[Seconds] Total time to wait: " + wait);
if (wait > 0) {
sleep(wait * 1000l, downloadLink);
}
}
}
// TODO: remove this when v2 becomes stable. use br.getFormbyKey(String key, String value)
/**
* Returns the first form that has a 'key' that equals 'value'.
*
* @param key
* @param value
* @return
*/
private Form getFormByKey(final String key, final String value) {
Form[] workaround = br.getForms();
if (workaround != null) {
for (Form f : workaround) {
for (InputField field : f.getInputFields()) {
if (key != null && key.equals(field.getKey())) {
if (value == null && field.getValue() == null) return f;
if (value != null && value.equals(field.getValue())) return f;
}
}
}
}
return null;
}
/**
* Validates string to series of conditions, null, whitespace, or "". This saves effort factor within if/for/while statements
*
* @param s
* Imported String to match against.
* @return <b>true</b> on valid rule match. <b>false</b> on invalid rule match.
* @author raztoki
* */
private boolean inValidate(final String s) {
if (s == null || s != null && (s.matches("[\r\n\t ]+") || s.equals("")))
return true;
else
return false;
}
/**
* This fixes filenames from all xfs modules: file hoster, audio/video streaming (including transcoded video), or blocked link checking
* which is based on fuid.
*
* @version 0.2
* @author raztoki
* */
private void fixFilename(final DownloadLink downloadLink) {
String orgName = null;
String orgExt = null;
String servName = null;
String servExt = null;
String orgNameExt = downloadLink.getFinalFileName();
if (orgNameExt == null) orgNameExt = downloadLink.getName();
if (!inValidate(orgNameExt) && orgNameExt.contains(".")) orgExt = orgNameExt.substring(orgNameExt.lastIndexOf("."));
if (!inValidate(orgExt))
orgName = new Regex(orgNameExt, "(.+)" + orgExt).getMatch(0);
else
orgName = orgNameExt;
// if (orgName.endsWith("...")) orgName = orgName.replaceFirst("\\.\\.\\.$", "");
String servNameExt = Encoding.htmlDecode(getFileNameFromHeader(dl.getConnection()));
if (!inValidate(servNameExt) && servNameExt.contains(".")) {
servExt = servNameExt.substring(servNameExt.lastIndexOf("."));
servName = new Regex(servNameExt, "(.+)" + servExt).getMatch(0);
} else
servName = servNameExt;
String FFN = null;
if (orgName.equalsIgnoreCase(fuid.toLowerCase()))
FFN = servNameExt;
else if (inValidate(orgExt) && !inValidate(servExt) && (servName.toLowerCase().contains(orgName.toLowerCase()) && !servName.equalsIgnoreCase(orgName)))
/* when partial match of filename exists. eg cut off by quotation mark miss match, or orgNameExt has been abbreviated by hoster */
FFN = servNameExt;
else if (!inValidate(orgExt) && !inValidate(servExt) && !orgExt.equalsIgnoreCase(servExt))
FFN = orgName + servExt;
else
FFN = orgNameExt;
downloadLink.setFinalFileName(FFN);
}
private void setFUID(final DownloadLink dl) {
fuid = new Regex(dl.getDownloadURL(), "([a-z0-9]{12})$").getMatch(0);
}
private String handlePassword(final Form pwform, final DownloadLink thelink) throws PluginException {
if (passCode == null) passCode = Plugin.getUserInput("Password?", thelink);
if (passCode == null || passCode.equals("")) {
logger.info("User has entered blank password, exiting handlePassword");
passCode = null;
thelink.setProperty("pass", Property.NULL);
return null;
}
if (pwform == null) {
/* so we know handlePassword triggered without any form */
logger.info("Password Form == null");
} else {
logger.info("Put password \"" + passCode + "\" entered by user in the DLForm.");
pwform.put("password", Encoding.urlEncode(passCode));
}
thelink.setProperty("pass", passCode);
return passCode;
}
public void checkErrors(final DownloadLink theLink, final boolean checkAll) throws NumberFormatException, PluginException {
if (checkAll) {
if (new Regex(correctedBR, PASSWORDTEXT).matches() && correctedBR.contains("Wrong password")) {
/* handle password has failed in the past, additional try catching / resetting values */
logger.warning("Wrong password, the entered password \"" + passCode + "\" is wrong, retrying...");
passCode = null;
theLink.setProperty("pass", Property.NULL);
throw new PluginException(LinkStatus.ERROR_RETRY, "Wrong password entered");
}
if (correctedBR.contains("Wrong captcha")) {
logger.warning("Wrong captcha or wrong password!");
throw new PluginException(LinkStatus.ERROR_CAPTCHA);
}
if (correctedBR.contains("\">Skipped countdown<")) throw new PluginException(LinkStatus.ERROR_FATAL, "Fatal countdown error (countdown skipped)");
}
/** Wait time reconnect handling */
if (new Regex(correctedBR, "(You have reached the download(\\-| )limit|You have to wait)").matches()) {
/* adjust this regex to catch the wait time string for COOKIE_HOST */
String WAIT = new Regex(correctedBR, "((You have reached the download(\\-| )limit|You have to wait)[^<>]+)").getMatch(0);
String tmphrs = new Regex(WAIT, "\\s+(\\d+)\\s+hours?").getMatch(0);
if (tmphrs == null) tmphrs = new Regex(correctedBR, "You have to wait.*?\\s+(\\d+)\\s+hours?").getMatch(0);
String tmpmin = new Regex(WAIT, "\\s+(\\d+)\\s+minutes?").getMatch(0);
if (tmpmin == null) tmpmin = new Regex(correctedBR, "You have to wait.*?\\s+(\\d+)\\s+minutes?").getMatch(0);
String tmpsec = new Regex(WAIT, "\\s+(\\d+)\\s+seconds?").getMatch(0);
String tmpdays = new Regex(WAIT, "\\s+(\\d+)\\s+days?").getMatch(0);
if (tmphrs == null && tmpmin == null && tmpsec == null && tmpdays == null) {
logger.info("Waittime regexes seem to be broken");
throw new PluginException(LinkStatus.ERROR_IP_BLOCKED, null, 60 * 60 * 1000l);
} else {
int minutes = 0, seconds = 0, hours = 0, days = 0;
if (tmphrs != null) hours = Integer.parseInt(tmphrs);
if (tmpmin != null) minutes = Integer.parseInt(tmpmin);
if (tmpsec != null) seconds = Integer.parseInt(tmpsec);
if (tmpdays != null) days = Integer.parseInt(tmpdays);
int waittime = ((days * 24 * 3600) + (3600 * hours) + (60 * minutes) + seconds + 1) * 1000;
logger.info("Detected waittime #2, waiting " + waittime + "milliseconds");
/* Not enough wait time to reconnect -> Wait short and retry */
if (waittime < 180000) { throw new PluginException(LinkStatus.ERROR_HOSTER_TEMPORARILY_UNAVAILABLE, JDL.L("plugins.hoster.xfilesharingprobasic.allwait", ALLWAIT_SHORT), waittime); }
throw new PluginException(LinkStatus.ERROR_IP_BLOCKED, null, waittime);
}
}
if (correctedBR.contains("You're using all download slots for IP")) { throw new PluginException(LinkStatus.ERROR_IP_BLOCKED, null, 10 * 60 * 1001l); }
if (correctedBR.contains("Error happened when generating Download Link")) throw new PluginException(LinkStatus.ERROR_TEMPORARILY_UNAVAILABLE, "Server error!", 10 * 60 * 1000l);
/** Error handling for only-premium links */
if (new Regex(correctedBR, "( can download files up to |Upgrade your account to download bigger files|>Upgrade your account to download larger files|>The file you requested reached max downloads limit for Free Users|Please Buy Premium To download this file<|This file reached max downloads limit)").matches()) {
String filesizelimit = new Regex(correctedBR, "You can download files up to(.*?)only").getMatch(0);
if (filesizelimit != null) {
filesizelimit = filesizelimit.trim();
logger.info("As free user you can download files up to " + filesizelimit + " only");
try {
throw new PluginException(LinkStatus.ERROR_PREMIUM, PluginException.VALUE_ID_PREMIUM_ONLY);
} catch (final Throwable e) {
if (e instanceof PluginException) throw (PluginException) e;
}
throw new PluginException(LinkStatus.ERROR_FATAL, PREMIUMONLY1 + " " + filesizelimit);
} else {
logger.info("Only downloadable via premium");
try {
throw new PluginException(LinkStatus.ERROR_PREMIUM, PluginException.VALUE_ID_PREMIUM_ONLY);
} catch (final Throwable e) {
if (e instanceof PluginException) throw (PluginException) e;
}
throw new PluginException(LinkStatus.ERROR_FATAL, PREMIUMONLY2);
}
} else if (br.getURL().contains("/?op=login&redirect=")) {
logger.info("Only downloadable via premium");
try {
throw new PluginException(LinkStatus.ERROR_PREMIUM, PluginException.VALUE_ID_PREMIUM_ONLY);
} catch (final Throwable e) {
if (e instanceof PluginException) throw (PluginException) e;
}
throw new PluginException(LinkStatus.ERROR_FATAL, PREMIUMONLY2);
}
if (new Regex(correctedBR, MAINTENANCE).matches()) throw new PluginException(LinkStatus.ERROR_TEMPORARILY_UNAVAILABLE, MAINTENANCEUSERTEXT, 2 * 60 * 60 * 1000l);
}
public void checkServerErrors() throws NumberFormatException, PluginException {
if (new Regex(correctedBR, Pattern.compile("No file", Pattern.CASE_INSENSITIVE)).matches()) throw new PluginException(LinkStatus.ERROR_TEMPORARILY_UNAVAILABLE, "Server error: 'no file'", 2 * 60 * 60 * 1000l);
if (new Regex(correctedBR, Pattern.compile("Wrong IP", Pattern.CASE_INSENSITIVE)).matches()) throw new PluginException(LinkStatus.ERROR_TEMPORARILY_UNAVAILABLE, "Server error: 'Wrong IP'", 2 * 60 * 60 * 1000l);
if (new Regex(correctedBR, "(File Not Found|<h1>404 Not Found</h1>)").matches()) throw new PluginException(LinkStatus.ERROR_TEMPORARILY_UNAVAILABLE, "Server error (404)", 30 * 60 * 1000l);
}
/**
* Is intended to handle out of date errors which might occur seldom by re-tring a couple of times before throwing the out of date
* error.
*
* @param dl
* : The DownloadLink
* @param error
* : The name of the error
* @param maxRetries
* : Max retries before out of date error is thrown
*/
private void handlePluginBroken(final DownloadLink dl, final String error, final int maxRetries) throws PluginException {
int timesFailed = dl.getIntegerProperty(NICE_HOSTproperty + "failedtimes_" + error, 0);
dl.getLinkStatus().setRetryCount(0);
if (timesFailed <= maxRetries) {
logger.info(NICE_HOST + ": " + error + " -> Retrying");
timesFailed++;
dl.setProperty(NICE_HOSTproperty + "failedtimes_" + error, timesFailed);
throw new PluginException(LinkStatus.ERROR_RETRY, "Final download link not found");
} else {
dl.setProperty(NICE_HOSTproperty + "failedtimes_" + error, Property.NULL);
logger.info(NICE_HOST + ": " + error + " -> Plugin is broken");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
}
@Override
public AccountInfo fetchAccountInfo(final Account account) throws Exception {
final AccountInfo ai = new AccountInfo();
/* reset maxPrem workaround on every fetchaccount info */
maxPrem.set(1);
try {
login(account, true);
} catch (final PluginException e) {
account.setValid(false);
throw e;
}
final String space[] = new Regex(correctedBR, ">Used space:</td>.*?<td.*?b>([0-9\\.]+) ?(KB|MB|GB|TB)?</b>").getRow(0);
if ((space != null && space.length != 0) && (space[0] != null && space[1] != null)) {
/* free users it's provided by default */
ai.setUsedSpace(space[0] + " " + space[1]);
} else if ((space != null && space.length != 0) && space[0] != null) {
/* premium users the Mb value isn't provided for some reason... */
ai.setUsedSpace(space[0] + "Mb");
}
account.setValid(true);
final String availabletraffic = new Regex(correctedBR, "Traffic available.*?:</TD><TD><b>([^<>\"\\']+)</b>").getMatch(0);
if (availabletraffic != null && !availabletraffic.contains("nlimited") && !availabletraffic.equalsIgnoreCase(" Mb")) {
availabletraffic.trim();
/* need to set 0 traffic left, as getSize returns positive result, even when negative value supplied. */
if (!availabletraffic.startsWith("-")) {
ai.setTrafficLeft(SizeFormatter.getSize(availabletraffic));
} else {
ai.setTrafficLeft(0);
}
} else {
ai.setUnlimitedTraffic();
}
/* If the premium account is expired we'll simply accept it as a free account. */
final String expire = new Regex(correctedBR, "(\\d{1,2} (January|February|March|April|May|June|July|August|September|October|November|December) \\d{4})").getMatch(0);
long expiretime = 0;
if (expire != null) expiretime = TimeFormatter.getMilliSeconds(expire, "dd MMMM yyyy", Locale.ENGLISH);
if (account.getBooleanProperty("nopremium") && (expiretime - System.currentTimeMillis()) <= 0) {
try {
maxPrem.set(ACCOUNT_FREE_MAXDOWNLOADS);
/* free accounts can still have captcha */
totalMaxSimultanFreeDownload.set(maxPrem.get());
account.setMaxSimultanDownloads(maxPrem.get());
account.setConcurrentUsePossible(false);
} catch (final Throwable e) {
/* not available in old Stable 0.9.581 */
}
ai.setStatus("Registered (free) user");
} else {
ai.setValidUntil(expiretime);
try {
maxPrem.set(ACCOUNT_PREMIUM_MAXDOWNLOADS);
account.setMaxSimultanDownloads(maxPrem.get());
account.setConcurrentUsePossible(true);
} catch (final Throwable e) {
/* not available in old Stable 0.9.581 */
}
ai.setStatus("Premium user");
}
return ai;
}
@SuppressWarnings("unchecked")
private void login(final Account account, final boolean force) throws Exception {
synchronized (LOCK) {
try {
/* Load cookies */
br.setCookiesExclusive(true);
prepBrowser(br);
final Object ret = account.getProperty("cookies", null);
boolean acmatch = Encoding.urlEncode(account.getUser()).equals(account.getStringProperty("name", Encoding.urlEncode(account.getUser())));
if (acmatch) acmatch = Encoding.urlEncode(account.getPass()).equals(account.getStringProperty("pass", Encoding.urlEncode(account.getPass())));
if (acmatch && ret != null && ret instanceof HashMap<?, ?> && !force) {
final HashMap<String, String> cookies = (HashMap<String, String>) ret;
if (account.isValid()) {
for (final Map.Entry<String, String> cookieEntry : cookies.entrySet()) {
final String key = cookieEntry.getKey();
final String value = cookieEntry.getValue();
this.br.setCookie(COOKIE_HOST, key, value);
}
return;
}
}
br.setFollowRedirects(true);
getPage(COOKIE_HOST + "/login.html");
final String lang = System.getProperty("user.language");
final Form loginform = br.getFormbyProperty("name", "FL");
if (loginform == null) {
if ("de".equalsIgnoreCase(lang)) {
throw new PluginException(LinkStatus.ERROR_PREMIUM, "\r\nPlugin defekt, bitte den JDownloader Support kontaktieren!", PluginException.VALUE_ID_PREMIUM_DISABLE);
} else {
throw new PluginException(LinkStatus.ERROR_PREMIUM, "\r\nPlugin broken, please contact the JDownloader Support!", PluginException.VALUE_ID_PREMIUM_DISABLE);
}
}
loginform.put("login", Encoding.urlEncode(account.getUser()));
loginform.put("password", Encoding.urlEncode(account.getPass()));
sendForm(loginform);
if (br.getCookie(COOKIE_HOST, "login") == null || br.getCookie(COOKIE_HOST, "xfss") == null) {
if ("de".equalsIgnoreCase(lang)) {
throw new PluginException(LinkStatus.ERROR_PREMIUM, "\r\nUngültiger Benutzername oder ungültiges Passwort!\r\nDu bist dir sicher, dass dein eingegebener Benutzername und Passwort stimmen? Versuche folgendes:\r\n1. Falls dein Passwort Sonderzeichen enthält, ändere es (entferne diese) und versuche es erneut!\r\n2. Gib deine Zugangsdaten per Hand (ohne kopieren/einfügen) ein.", PluginException.VALUE_ID_PREMIUM_DISABLE);
} else {
throw new PluginException(LinkStatus.ERROR_PREMIUM, "\r\nInvalid username/password!\r\nYou're sure that the username and password you entered are correct? Some hints:\r\n1. If your password contains special characters, change it (remove them) and try again!\r\n2. Type in your username/password by hand without copy & paste.", PluginException.VALUE_ID_PREMIUM_DISABLE);
}
}
if (!br.getURL().contains("/?op=my_account")) {
getPage("/?op=my_account");
}
if (!new Regex(correctedBR, "(Premium(\\-| )Account expire|>Renew premium<)").matches()) {
account.setProperty("nopremium", true);
} else {
account.setProperty("nopremium", false);
}
/* Save cookies */
final HashMap<String, String> cookies = new HashMap<String, String>();
final Cookies add = this.br.getCookies(COOKIE_HOST);
for (final Cookie c : add.getCookies()) {
cookies.put(c.getKey(), c.getValue());
}
account.setProperty("name", Encoding.urlEncode(account.getUser()));
account.setProperty("pass", Encoding.urlEncode(account.getPass()));
account.setProperty("cookies", cookies);
} catch (final PluginException e) {
account.setProperty("cookies", Property.NULL);
throw e;
}
}
}
@Override
public void handlePremium(final DownloadLink downloadLink, final Account account) throws Exception {
passCode = downloadLink.getStringProperty("pass");
requestFileInformation(downloadLink);
login(account, false);
if (account.getBooleanProperty("nopremium")) {
requestFileInformation(downloadLink);
doFree(downloadLink, ACCOUNT_FREE_RESUME, ACCOUNT_FREE_MAXCHUNKS, "freelink2");
} else {
String dllink = checkDirectLink(downloadLink, "premlink");
if (dllink == null) {
br.setFollowRedirects(false);
getPage(downloadLink.getDownloadURL());
dllink = getDllink();
if (dllink == null) {
Form dlform = br.getFormbyProperty("name", "F1");
if (dlform != null && new Regex(correctedBR, PASSWORDTEXT).matches()) passCode = handlePassword(dlform, downloadLink);
checkErrors(downloadLink, true);
if (dlform == null) throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
sendForm(dlform);
checkErrors(downloadLink, true);
dllink = getDllink();
}
}
if (dllink == null) {
logger.warning("Final downloadlink (String is \"dllink\") regex didn't match!");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
logger.info("Final downloadlink = " + dllink + " starting the download...");
dl = jd.plugins.BrowserAdapter.openDownload(br, downloadLink, dllink, ACCOUNT_PREMIUM_RESUME, ACCOUNT_PREMIUM_MAXCHUNKS);
if (dl.getConnection().getContentType().contains("html")) {
if (dl.getConnection().getResponseCode() == 503) throw new PluginException(LinkStatus.ERROR_HOSTER_TEMPORARILY_UNAVAILABLE, "Connection limit reached, please contact our support!", 5 * 60 * 1000l);
logger.warning("The final dllink seems not to be a file!");
br.followConnection();
correctBR();
checkServerErrors();
handlePluginBroken(downloadLink, "dllinknofile", 3);
}
fixFilename(downloadLink);
downloadLink.setProperty("premlink", dllink);
dl.startDownload();
}
}
@Override
public int getMaxSimultanPremiumDownloadNum() {
/* workaround for free/premium issue on stable 09581 */
return maxPrem.get();
}
@Override
public void reset() {
}
@Override
public void resetDownloadlink(DownloadLink link) {
}
}

View File

@ -327,8 +327,10 @@ public class SimplyPremiumCom extends PluginForHost {
private void getapikey(final Account acc) throws IOException, PluginException {
synchronized (LOCK) {
boolean acmatch = Encoding.urlEncode(acc.getUser()).equals(acc.getStringProperty("name", Encoding.urlEncode(acc.getUser())));
if (acmatch) acmatch = Encoding.urlEncode(acc.getPass()).equals(acc.getStringProperty("pass", Encoding.urlEncode(acc.getPass())));
APIKEY = acc.getStringProperty(NICE_HOSTproperty + "apikey", null);
if (APIKEY != null) {
if (APIKEY != null && acmatch) {
br.setCookie("http://simply-premium.com/", "apikey", APIKEY);
} else {
login(acc);
@ -391,6 +393,8 @@ public class SimplyPremiumCom extends PluginForHost {
}
}
account.setProperty(NICE_HOSTproperty + "apikey", APIKEY);
account.setProperty("name", Encoding.urlEncode(account.getUser()));
account.setProperty("pass", Encoding.urlEncode(account.getPass()));
}
private void showMessage(DownloadLink link, String message) {

View File

@ -0,0 +1,806 @@
//jDownloader - Downloadmanager
//Copyright (C) 2013 JD-Team support@jdownloader.org
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program. If not, see <http://www.gnu.org/licenses/>.
package jd.plugins.hoster;
import java.io.File;
import java.util.ArrayList;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
import jd.PluginWrapper;
import jd.config.Property;
import jd.http.Browser;
import jd.http.URLConnectionAdapter;
import jd.nutils.encoding.Encoding;
import jd.parser.Regex;
import jd.parser.html.Form;
import jd.parser.html.HTMLParser;
import jd.parser.html.InputField;
import jd.plugins.DownloadLink;
import jd.plugins.DownloadLink.AvailableStatus;
import jd.plugins.HostPlugin;
import jd.plugins.LinkStatus;
import jd.plugins.Plugin;
import jd.plugins.PluginException;
import jd.plugins.PluginForDecrypt;
import jd.plugins.PluginForHost;
import jd.plugins.hoster.DdlStorageCom.StringContainer;
import jd.utils.JDUtilities;
import jd.utils.locale.JDL;
import org.appwork.utils.formatter.SizeFormatter;
@HostPlugin(revision = "$Revision$", interfaceVersion = 2, names = { "streamin.to" }, urls = { "https?://(www\\.)?streamin\\.to/(vidembed\\-)?[a-z0-9]{12}" }, flags = { 0 })
public class StreaminTo extends PluginForHost {
private String correctedBR = "";
private String passCode = null;
private static final String PASSWORDTEXT = "<br><b>Passwor(d|t):</b> <input";
/* primary website url, take note of redirects */
private static final String COOKIE_HOST = "http://streamin.to";
private static final String NICE_HOST = COOKIE_HOST.replaceAll("(https://|http://)", "");
private static final String NICE_HOSTproperty = COOKIE_HOST.replaceAll("(https://|http://|\\.|\\-)", "");
/* domain names used within download links */
private static final String DOMAINS = "(streamin\\.to)";
private static final String MAINTENANCE = ">This server is in maintenance mode";
private static final String MAINTENANCEUSERTEXT = JDL.L("hoster.xfilesharingprobasic.errors.undermaintenance", "This server is under maintenance");
private static final String ALLWAIT_SHORT = JDL.L("hoster.xfilesharingprobasic.errors.waitingfordownloads", "Waiting till new downloads can be started");
private static final String PREMIUMONLY1 = JDL.L("hoster.xfilesharingprobasic.errors.premiumonly1", "Max downloadable filesize for free users:");
private static final String PREMIUMONLY2 = JDL.L("hoster.xfilesharingprobasic.errors.premiumonly2", "Only downloadable via premium or registered");
private static final boolean VIDEOHOSTER = false;
private static final boolean VIDEOHOSTER_2 = true;
private static final boolean SUPPORTSHTTPS = false;
private final boolean ENABLE_RANDOM_UA = false;
private static StringContainer agent = new StringContainer();
/* Connection stuff */
private static final boolean FREE_RESUME = true;
private static final int FREE_MAXCHUNKS = -2;
private static final int FREE_MAXDOWNLOADS = 1;
private static final boolean ACCOUNT_FREE_RESUME = true;
private static final int ACCOUNT_FREE_MAXCHUNKS = 0;
private static final int ACCOUNT_FREE_MAXDOWNLOADS = 20;
private static final boolean ACCOUNT_PREMIUM_RESUME = true;
private static final int ACCOUNT_PREMIUM_MAXCHUNKS = 0;
private static final int ACCOUNT_PREMIUM_MAXDOWNLOADS = 20;
/* note: CAN NOT be negative or zero! (ie. -1 or 0) Otherwise math sections fail. .:. use [1-20] */
private static AtomicInteger totalMaxSimultanFreeDownload = new AtomicInteger(FREE_MAXDOWNLOADS);
/* don't touch the following! */
private static AtomicInteger maxFree = new AtomicInteger(1);
private static AtomicInteger maxPrem = new AtomicInteger(1);
private static Object LOCK = new Object();
private String fuid = null;
/* DEV NOTES */
// XfileSharingProBasic Version 2.6.5.8
// mods: heavily modified, do NOT upgrade!
// limit-info:
// protocol: no https
// captchatype: null
// other:
@Override
public void correctDownloadLink(final DownloadLink link) {
/* link cleanup, but respect users protocol choosing */
if (!SUPPORTSHTTPS) {
link.setUrlDownload(link.getDownloadURL().replaceFirst("https://", "http://"));
}
final String fid = new Regex(link.getDownloadURL(), "([a-z0-9]{12})$").getMatch(0);
link.setUrlDownload(COOKIE_HOST + "/" + fid);
}
@Override
public String getAGBLink() {
return COOKIE_HOST + "/tos.html";
}
public StreaminTo(PluginWrapper wrapper) {
super(wrapper);
// this.enablePremium(COOKIE_HOST + "/premium.html");
}
@Override
public AvailableStatus requestFileInformation(final DownloadLink link) throws Exception {
br.setFollowRedirects(true);
prepBrowser(br);
setFUID(link);
getPage(link.getDownloadURL());
if (new Regex(correctedBR, "(No such file|>File Not Found<|>The file was removed by|Reason for deletion:\n|<Title>Watch </Title>)").matches()) throw new PluginException(LinkStatus.ERROR_FILE_NOT_FOUND);
if (new Regex(correctedBR, MAINTENANCE).matches()) {
link.getLinkStatus().setStatusText(MAINTENANCEUSERTEXT);
return AvailableStatus.UNCHECKABLE;
}
if (br.getURL().contains("/?op=login&redirect=")) {
link.getLinkStatus().setStatusText(PREMIUMONLY2);
return AvailableStatus.UNCHECKABLE;
}
final String[] fileInfo = new String[3];
scanInfo(fileInfo);
if (fileInfo[0] == null || fileInfo[0].equals("")) {
if (correctedBR.contains("You have reached the download(\\-| )limit")) {
logger.warning("Waittime detected, please reconnect to make the linkchecker work!");
return AvailableStatus.UNCHECKABLE;
}
logger.warning("filename equals null, throwing \"plugin defect\"");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
if (fileInfo[2] != null && !fileInfo[2].equals("")) link.setMD5Hash(fileInfo[2].trim());
fileInfo[0] = fileInfo[0].replaceAll("(</b>|<b>|\\.html)", "");
link.setName(fileInfo[0].trim());
if (fileInfo[1] != null && !fileInfo[1].equals("")) link.setDownloadSize(SizeFormatter.getSize(fileInfo[1]));
return AvailableStatus.TRUE;
}
private String[] scanInfo(final String[] fileInfo) {
/* standard traits from base page */
if (fileInfo[0] == null) {
fileInfo[0] = new Regex(correctedBR, "You have requested.*?https?://(www\\.)?" + DOMAINS + "/" + fuid + "/(.*?)</font>").getMatch(2);
if (fileInfo[0] == null) {
fileInfo[0] = new Regex(correctedBR, "fname\"( type=\"hidden\")? value=\"(.*?)\"").getMatch(1);
if (fileInfo[0] == null) {
fileInfo[0] = new Regex(correctedBR, "<h2>Download File(.*?)</h2>").getMatch(0);
/* traits from download1 page below */
if (fileInfo[0] == null) {
fileInfo[0] = new Regex(correctedBR, "Filename:? ?(<[^>]+> ?)+?([^<>\"\\']+)").getMatch(1);
// next two are details from sharing box
if (fileInfo[0] == null) {
fileInfo[0] = new Regex(correctedBR, "copy\\(this\\);.+>(.+) \\- [\\d\\.]+ (KB|MB|GB)</a></textarea>[\r\n\t ]+</div>").getMatch(0);
if (fileInfo[0] == null) {
fileInfo[0] = new Regex(correctedBR, "copy\\(this\\);.+\\](.+) \\- [\\d\\.]+ (KB|MB|GB)\\[/URL\\]").getMatch(0);
if (fileInfo[0] == null) {
/* Link of the box without filesize */
fileInfo[0] = new Regex(correctedBR, "onFocus=\"copy\\(this\\);\">http://(www\\.)?" + DOMAINS + "/" + fuid + "/([^<>\"]*?)</textarea").getMatch(2);
}
}
}
}
}
}
}
if (fileInfo[1] == null) {
fileInfo[1] = new Regex(correctedBR, "\\(([0-9]+ bytes)\\)").getMatch(0);
if (fileInfo[1] == null) {
fileInfo[1] = new Regex(correctedBR, "</font>[ ]+\\(([^<>\"\\'/]+)\\)(.*?)</font>").getMatch(0);
if (fileInfo[1] == null) {
fileInfo[1] = new Regex(correctedBR, "(\\d+(\\.\\d+)? ?(KB|MB|GB))").getMatch(0);
}
}
}
if (fileInfo[2] == null) fileInfo[2] = new Regex(correctedBR, "<b>MD5.*?</b>.*?nowrap>(.*?)<").getMatch(0);
return fileInfo;
}
@Override
public void handleFree(final DownloadLink downloadLink) throws Exception, PluginException {
requestFileInformation(downloadLink);
doFree(downloadLink, FREE_RESUME, FREE_MAXCHUNKS, "freelink");
}
@SuppressWarnings("unused")
public void doFree(final DownloadLink downloadLink, final boolean resumable, final int maxchunks, final String directlinkproperty) throws Exception, PluginException {
br.setFollowRedirects(false);
passCode = downloadLink.getStringProperty("pass");
/* First, bring up saved final links */
String dllink = checkDirectLink(downloadLink, directlinkproperty);
/* Second, check for streaming/direct links on the first page */
if (dllink == null) dllink = getDllink();
/* Third, do they provide video hosting? */
if (dllink == null && VIDEOHOSTER) {
try {
logger.info("Trying to get link via vidembed");
final Browser brv = br.cloneBrowser();
brv.getPage("/vidembed-" + fuid);
dllink = brv.getRedirectLocation();
if (dllink == null)
logger.info("Failed to get link via vidembed");
else
logger.info("Successfully found link via vidembed");
} catch (final Throwable e) {
logger.info("Failed to get link via vidembed");
}
}
if (dllink == null && VIDEOHOSTER_2) {
try {
logger.info("Trying to get link via embed");
final String embed_access = "http://" + COOKIE_HOST.replace("http://", "") + "/embed-" + fuid + ".html";
getPage(embed_access);
dllink = getDllink();
if (dllink == null)
logger.info("Failed to get link via embed");
else
logger.info("Successfully found link via embed");
} catch (final Throwable e) {
logger.info("Failed to get link via embed");
}
if (dllink == null) getPage(downloadLink.getDownloadURL());
}
/* Fourth, continue like normal */
if (dllink == null) {
checkErrors(downloadLink, false);
final Form download1 = getFormByKey("op", "download1");
if (download1 != null) {
download1.remove("method_premium");
/* stable is lame, issue finding input data fields correctly. eg. closes at ' quotation mark - remove when jd2 goes stable! */
if (downloadLink.getName().contains("'")) {
String fname = new Regex(br, "<input type=\"hidden\" name=\"fname\" value=\"([^\"]+)\">").getMatch(0);
if (fname != null) {
download1.put("fname", Encoding.urlEncode(fname));
} else {
logger.warning("Could not find 'fname'");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
}
/* end of backward compatibility */
waitTime(System.currentTimeMillis(), downloadLink);
sendForm(download1);
checkErrors(downloadLink, false);
dllink = getDllink();
}
}
if (dllink == null) {
Form dlForm = br.getFormbyProperty("name", "F1");
if (dlForm == null) {
handlePluginBroken(downloadLink, "dlform_f1_null", 3);
}
/* how many forms deep do you want to try? */
int repeat = 2;
for (int i = 0; i <= repeat; i++) {
dlForm.remove(null);
final long timeBefore = System.currentTimeMillis();
boolean password = false;
boolean skipWaittime = false;
if (new Regex(correctedBR, PASSWORDTEXT).matches()) {
password = true;
logger.info("The downloadlink seems to be password protected.");
}
/* md5 can be on the subsequent pages - it is to be found very rare in current XFS versions */
if (downloadLink.getMD5Hash() == null) {
String md5hash = new Regex(correctedBR, "<b>MD5.*?</b>.*?nowrap>(.*?)<").getMatch(0);
if (md5hash != null) downloadLink.setMD5Hash(md5hash.trim());
}
/* Captcha START */
if (correctedBR.contains(";background:#ccc;text-align")) {
logger.info("Detected captcha method \"plaintext captchas\" for this host");
/* Captcha method by ManiacMansion */
final String[][] letters = new Regex(br, "<span style=\\'position:absolute;padding\\-left:(\\d+)px;padding\\-top:\\d+px;\\'>(&#\\d+;)</span>").getMatches();
if (letters == null || letters.length == 0) {
logger.warning("plaintext captchahandling broken!");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
final SortedMap<Integer, String> capMap = new TreeMap<Integer, String>();
for (String[] letter : letters) {
capMap.put(Integer.parseInt(letter[0]), Encoding.htmlDecode(letter[1]));
}
final StringBuilder code = new StringBuilder();
for (String value : capMap.values()) {
code.append(value);
}
dlForm.put("code", code.toString());
logger.info("Put captchacode " + code.toString() + " obtained by captcha metod \"plaintext captchas\" in the form.");
} else if (correctedBR.contains("/captchas/")) {
logger.info("Detected captcha method \"Standard captcha\" for this host");
final String[] sitelinks = HTMLParser.getHttpLinks(br.toString(), null);
String captchaurl = null;
if (sitelinks == null || sitelinks.length == 0) {
logger.warning("Standard captcha captchahandling broken!");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
for (String link : sitelinks) {
if (link.contains("/captchas/")) {
captchaurl = link;
break;
}
}
if (captchaurl == null) {
logger.warning("Standard captcha captchahandling broken!");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
String code = getCaptchaCode("xfilesharingprobasic", captchaurl, downloadLink);
dlForm.put("code", code);
logger.info("Put captchacode " + code + " obtained by captcha metod \"Standard captcha\" in the form.");
} else if (new Regex(correctedBR, "(api\\.recaptcha\\.net|google\\.com/recaptcha/api/)").matches()) {
logger.info("Detected captcha method \"Re Captcha\" for this host");
final PluginForHost recplug = JDUtilities.getPluginForHost("DirectHTTP");
final jd.plugins.hoster.DirectHTTP.Recaptcha rc = ((DirectHTTP) recplug).getReCaptcha(br);
rc.findID();
rc.load();
final File cf = rc.downloadCaptcha(getLocalCaptchaFile());
final String c = getCaptchaCode(cf, downloadLink);
dlForm.put("recaptcha_challenge_field", rc.getChallenge());
dlForm.put("recaptcha_response_field", Encoding.urlEncode(c));
logger.info("Put captchacode " + c + " obtained by captcha metod \"Re Captcha\" in the form and submitted it.");
/* wait time is usually skippable for reCaptcha handling */
skipWaittime = true;
} else if (br.containsHTML("solvemedia\\.com/papi/")) {
logger.info("Detected captcha method \"solvemedia\" for this host");
final PluginForDecrypt solveplug = JDUtilities.getPluginForDecrypt("linkcrypt.ws");
final jd.plugins.decrypter.LnkCrptWs.SolveMedia sm = ((jd.plugins.decrypter.LnkCrptWs) solveplug).getSolveMedia(br);
File cf = null;
try {
cf = sm.downloadCaptcha(getLocalCaptchaFile());
} catch (final Exception e) {
if (jd.plugins.decrypter.LnkCrptWs.SolveMedia.FAIL_CAUSE_CKEY_MISSING.equals(e.getMessage())) throw new PluginException(LinkStatus.ERROR_FATAL, "Host side solvemedia.com captcha error - please contact the " + this.getHost() + " support");
throw e;
}
final String code = getCaptchaCode(cf, downloadLink);
final String chid = sm.getChallenge(code);
dlForm.put("adcopy_challenge", chid);
dlForm.put("adcopy_response", "manual_challenge");
} else if (br.containsHTML("id=\"capcode\" name= \"capcode\"")) {
logger.info("Detected captcha method \"keycaptca\"");
String result = null;
final PluginForDecrypt keycplug = JDUtilities.getPluginForDecrypt("linkcrypt.ws");
try {
final jd.plugins.decrypter.LnkCrptWs.KeyCaptcha kc = ((jd.plugins.decrypter.LnkCrptWs) keycplug).getKeyCaptcha(br);
result = kc.showDialog(downloadLink.getDownloadURL());
} catch (final Throwable e) {
result = null;
}
if (result == null) throw new PluginException(LinkStatus.ERROR_CAPTCHA);
if ("CANCEL".equals(result)) throw new PluginException(LinkStatus.ERROR_FATAL);
dlForm.put("capcode", result);
skipWaittime = false;
}
/* Captcha END */
if (password) passCode = handlePassword(dlForm, downloadLink);
if (!skipWaittime) waitTime(timeBefore, downloadLink);
sendForm(dlForm);
logger.info("Submitted DLForm");
checkErrors(downloadLink, true);
dllink = getDllink();
if (dllink == null && (!br.containsHTML("<Form name=\"F1\" method=\"POST\" action=\"\"") || i == repeat)) {
logger.warning("Final downloadlink (String is \"dllink\") regex didn't match!");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
} else if (dllink == null && br.containsHTML("<Form name=\"F1\" method=\"POST\" action=\"\"")) {
dlForm = br.getFormbyProperty("name", "F1");
try {
invalidateLastChallengeResponse();
} catch (final Throwable e) {
}
continue;
} else {
try {
validateLastChallengeResponse();
} catch (final Throwable e) {
}
break;
}
}
}
logger.info("Final downloadlink = " + dllink + " starting the download...");
dl = jd.plugins.BrowserAdapter.openDownload(br, downloadLink, dllink, resumable, maxchunks);
if (dl.getConnection().getContentType().contains("html")) {
if (dl.getConnection().getResponseCode() == 503) throw new PluginException(LinkStatus.ERROR_HOSTER_TEMPORARILY_UNAVAILABLE, "Connection limit reached, please contact our support!", 5 * 60 * 1000l);
logger.warning("The final dllink seems not to be a file!");
br.followConnection();
correctBR();
checkServerErrors();
handlePluginBroken(downloadLink, "dllinknofile", 3);
}
downloadLink.setProperty(directlinkproperty, dllink);
fixFilename(downloadLink);
try {
/* add a download slot */
controlFree(+1);
/* start the dl */
dl.startDownload();
} finally {
/* remove download slot */
controlFree(-1);
}
}
@Override
public int getMaxSimultanFreeDownloadNum() {
return maxFree.get();
}
/* do not add @Override here to keep 0.* compatibility */
public boolean hasAutoCaptcha() {
return true;
}
/* NO OVERRIDE!! We need to stay 0.9*compatible */
public boolean hasCaptcha(DownloadLink link, jd.plugins.Account acc) {
if (acc == null) {
/* no account, yes we can expect captcha */
return true;
}
if (Boolean.TRUE.equals(acc.getBooleanProperty("nopremium"))) {
/* free accounts also have captchas */
return true;
}
return false;
}
private void prepBrowser(final Browser br) {
/* define custom browser headers and language settings */
br.getHeaders().put("Accept-Language", "en-gb, en;q=0.9");
br.setCookie(COOKIE_HOST, "lang", "english");
if (ENABLE_RANDOM_UA) {
if (agent.string == null) {
/* we first have to load the plugin, before we can reference it */
JDUtilities.getPluginForHost("mediafire.com");
agent.string = jd.plugins.hoster.MediafireCom.stringUserAgent();
}
br.getHeaders().put("User-Agent", agent.string);
}
}
/**
* Prevents more than one free download from starting at a given time. One step prior to dl.startDownload(), it adds a slot to maxFree
* which allows the next singleton download to start, or at least try.
*
* This is needed because xfileshare(website) only throws errors after a final dllink starts transferring or at a given step within pre
* download sequence. But this template(XfileSharingProBasic) allows multiple slots(when available) to commence the download sequence,
* this.setstartintival does not resolve this issue. Which results in x(20) captcha events all at once and only allows one download to
* start. This prevents wasting peoples time and effort on captcha solving and|or wasting captcha trading credits. Users will experience
* minimal harm to downloading as slots are freed up soon as current download begins.
*
* @param controlFree
* (+1|-1)
*/
public synchronized void controlFree(final int num) {
logger.info("maxFree was = " + maxFree.get());
maxFree.set(Math.min(Math.max(1, maxFree.addAndGet(num)), totalMaxSimultanFreeDownload.get()));
logger.info("maxFree now = " + maxFree.get());
}
/* Removes HTML code which could break the plugin */
public void correctBR() throws NumberFormatException, PluginException {
correctedBR = br.toString();
ArrayList<String> regexStuff = new ArrayList<String>();
// remove custom rules first!!! As html can change because of generic cleanup rules.
/* generic cleanup */
regexStuff.add("<\\!(\\-\\-.*?\\-\\-)>");
regexStuff.add("(display: ?none;\">.*?</div>)");
regexStuff.add("(visibility:hidden>.*?<)");
for (String aRegex : regexStuff) {
String results[] = new Regex(correctedBR, aRegex).getColumn(0);
if (results != null) {
for (String result : results) {
correctedBR = correctedBR.replace(result, "");
}
}
}
}
public String getDllink() {
String dllink = br.getRedirectLocation();
if (dllink == null) {
dllink = new Regex(correctedBR, "(\"|\\')(https?://(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|([\\w\\-\\.]+\\.)?" + DOMAINS + ")(:\\d{1,4})?/(files|d|cgi\\-bin/dl\\.cgi)/(\\d+/)?[a-z0-9]+/[^<>\"/]*?)(\"|\\')").getMatch(1);
if (dllink == null) {
final String cryptedScripts[] = new Regex(correctedBR, "p\\}\\((.*?)\\.split\\('\\|'\\)").getColumn(0);
if (cryptedScripts != null && cryptedScripts.length != 0) {
for (String crypted : cryptedScripts) {
dllink = decodeDownloadLink(crypted);
if (dllink != null) break;
}
}
}
}
/* try rtmp workaround, thx to raztoki */
if (dllink == null) {
dllink = new Regex(correctedBR, "\\?h=([a-z0-9]{30,70})").getMatch(0);
if (dllink != null) {
dllink = "http://95.211.95.238:8777/" + dllink + "/video.mp4";
}
}
return dllink;
}
private String decodeDownloadLink(final String s) {
String decoded = null;
try {
Regex params = new Regex(s, "\\'(.*?[^\\\\])\\',(\\d+),(\\d+),\\'(.*?)\\'");
String p = params.getMatch(0).replaceAll("\\\\", "");
int a = Integer.parseInt(params.getMatch(1));
int c = Integer.parseInt(params.getMatch(2));
String[] k = params.getMatch(3).split("\\|");
while (c != 0) {
c--;
if (k[c].length() != 0) p = p.replaceAll("\\b" + Integer.toString(c, a) + "\\b", k[c]);
}
decoded = p;
} catch (Exception e) {
}
String finallink = null;
if (decoded != null) {
/* Open regex is possible because in the unpacked JS there are usually only 1 links */
finallink = new Regex(decoded, "(\"|\\')(https?://[^<>\"\\']*?\\.(mp4|flv))(\"|\\')").getMatch(1);
}
return finallink;
}
private String checkDirectLink(final DownloadLink downloadLink, final String property) {
String dllink = downloadLink.getStringProperty(property);
if (dllink != null) {
try {
final Browser br2 = br.cloneBrowser();
URLConnectionAdapter con = br2.openGetConnection(dllink);
if (con.getContentType().contains("html") || con.getLongContentLength() == -1) {
downloadLink.setProperty(property, Property.NULL);
dllink = null;
}
con.disconnect();
} catch (final Exception e) {
downloadLink.setProperty(property, Property.NULL);
dllink = null;
}
}
return dllink;
}
private void getPage(final String page) throws Exception {
br.getPage(page);
correctBR();
}
@SuppressWarnings("unused")
private void postPage(final String page, final String postdata) throws Exception {
br.postPage(page, postdata);
correctBR();
}
private void sendForm(final Form form) throws Exception {
br.submitForm(form);
correctBR();
}
private void waitTime(long timeBefore, final DownloadLink downloadLink) throws PluginException {
int passedTime = (int) ((System.currentTimeMillis() - timeBefore) / 1000) - 1;
/** Ticket Time */
final String ttt = new Regex(correctedBR, "id=\"countdown_str\">[^<>\"]+<span id=\"[^<>\"]+\"( class=\"[^<>\"]+\")?>([\n ]+)?(\\d+)([\n ]+)?</span>").getMatch(2);
if (ttt != null) {
int wait = Integer.parseInt(ttt);
wait -= passedTime;
logger.info("[Seconds] Waittime on the page: " + ttt);
logger.info("[Seconds] Passed time: " + passedTime);
logger.info("[Seconds] Total time to wait: " + wait);
if (wait > 0) {
sleep(wait * 1000l, downloadLink);
}
}
}
// TODO: remove this when v2 becomes stable. use br.getFormbyKey(String key, String value)
/**
* Returns the first form that has a 'key' that equals 'value'.
*
* @param key
* @param value
* @return
*/
private Form getFormByKey(final String key, final String value) {
Form[] workaround = br.getForms();
if (workaround != null) {
for (Form f : workaround) {
for (InputField field : f.getInputFields()) {
if (key != null && key.equals(field.getKey())) {
if (value == null && field.getValue() == null) return f;
if (value != null && value.equals(field.getValue())) return f;
}
}
}
}
return null;
}
/**
* Validates string to series of conditions, null, whitespace, or "". This saves effort factor within if/for/while statements
*
* @param s
* Imported String to match against.
* @return <b>true</b> on valid rule match. <b>false</b> on invalid rule match.
* @author raztoki
* */
private boolean inValidate(final String s) {
if (s == null || s != null && (s.matches("[\r\n\t ]+") || s.equals("")))
return true;
else
return false;
}
/**
* This fixes filenames from all xfs modules: file hoster, audio/video streaming (including transcoded video), or blocked link checking
* which is based on fuid.
*
* @version 0.2
* @author raztoki
* */
private void fixFilename(final DownloadLink downloadLink) {
String orgName = null;
String orgExt = null;
String servName = null;
String servExt = null;
String orgNameExt = downloadLink.getFinalFileName();
if (orgNameExt == null) orgNameExt = downloadLink.getName();
if (!inValidate(orgNameExt) && orgNameExt.contains(".")) orgExt = orgNameExt.substring(orgNameExt.lastIndexOf("."));
if (!inValidate(orgExt))
orgName = new Regex(orgNameExt, "(.+)" + orgExt).getMatch(0);
else
orgName = orgNameExt;
// if (orgName.endsWith("...")) orgName = orgName.replaceFirst("\\.\\.\\.$", "");
String servNameExt = Encoding.htmlDecode(getFileNameFromHeader(dl.getConnection()));
if (!inValidate(servNameExt) && servNameExt.contains(".")) {
servExt = servNameExt.substring(servNameExt.lastIndexOf("."));
servName = new Regex(servNameExt, "(.+)" + servExt).getMatch(0);
} else
servName = servNameExt;
String FFN = null;
if (orgName.equalsIgnoreCase(fuid.toLowerCase()))
FFN = servNameExt;
else if (inValidate(orgExt) && !inValidate(servExt) && (servName.toLowerCase().contains(orgName.toLowerCase()) && !servName.equalsIgnoreCase(orgName)))
/* when partial match of filename exists. eg cut off by quotation mark miss match, or orgNameExt has been abbreviated by hoster */
FFN = servNameExt;
else if (!inValidate(orgExt) && !inValidate(servExt) && !orgExt.equalsIgnoreCase(servExt))
FFN = orgName + servExt;
else
FFN = orgNameExt;
downloadLink.setFinalFileName(FFN);
}
private void setFUID(final DownloadLink dl) {
fuid = new Regex(dl.getDownloadURL(), "([a-z0-9]{12})$").getMatch(0);
}
private String handlePassword(final Form pwform, final DownloadLink thelink) throws PluginException {
if (passCode == null) passCode = Plugin.getUserInput("Password?", thelink);
if (passCode == null || passCode.equals("")) {
logger.info("User has entered blank password, exiting handlePassword");
passCode = null;
thelink.setProperty("pass", Property.NULL);
return null;
}
if (pwform == null) {
/* so we know handlePassword triggered without any form */
logger.info("Password Form == null");
} else {
logger.info("Put password \"" + passCode + "\" entered by user in the DLForm.");
pwform.put("password", Encoding.urlEncode(passCode));
}
thelink.setProperty("pass", passCode);
return passCode;
}
public void checkErrors(final DownloadLink theLink, final boolean checkAll) throws NumberFormatException, PluginException {
if (checkAll) {
if (new Regex(correctedBR, PASSWORDTEXT).matches() && correctedBR.contains("Wrong password")) {
/* handle password has failed in the past, additional try catching / resetting values */
logger.warning("Wrong password, the entered password \"" + passCode + "\" is wrong, retrying...");
passCode = null;
theLink.setProperty("pass", Property.NULL);
throw new PluginException(LinkStatus.ERROR_RETRY, "Wrong password entered");
}
if (correctedBR.contains("Wrong captcha")) {
logger.warning("Wrong captcha or wrong password!");
throw new PluginException(LinkStatus.ERROR_CAPTCHA);
}
if (correctedBR.contains("\">Skipped countdown<")) throw new PluginException(LinkStatus.ERROR_FATAL, "Fatal countdown error (countdown skipped)");
}
/** Wait time reconnect handling */
if (new Regex(correctedBR, "(You have reached the download(\\-| )limit|You have to wait)").matches()) {
/* adjust this regex to catch the wait time string for COOKIE_HOST */
String WAIT = new Regex(correctedBR, "((You have reached the download(\\-| )limit|You have to wait)[^<>]+)").getMatch(0);
String tmphrs = new Regex(WAIT, "\\s+(\\d+)\\s+hours?").getMatch(0);
if (tmphrs == null) tmphrs = new Regex(correctedBR, "You have to wait.*?\\s+(\\d+)\\s+hours?").getMatch(0);
String tmpmin = new Regex(WAIT, "\\s+(\\d+)\\s+minutes?").getMatch(0);
if (tmpmin == null) tmpmin = new Regex(correctedBR, "You have to wait.*?\\s+(\\d+)\\s+minutes?").getMatch(0);
String tmpsec = new Regex(WAIT, "\\s+(\\d+)\\s+seconds?").getMatch(0);
String tmpdays = new Regex(WAIT, "\\s+(\\d+)\\s+days?").getMatch(0);
if (tmphrs == null && tmpmin == null && tmpsec == null && tmpdays == null) {
logger.info("Waittime regexes seem to be broken");
throw new PluginException(LinkStatus.ERROR_IP_BLOCKED, null, 60 * 60 * 1000l);
} else {
int minutes = 0, seconds = 0, hours = 0, days = 0;
if (tmphrs != null) hours = Integer.parseInt(tmphrs);
if (tmpmin != null) minutes = Integer.parseInt(tmpmin);
if (tmpsec != null) seconds = Integer.parseInt(tmpsec);
if (tmpdays != null) days = Integer.parseInt(tmpdays);
int waittime = ((days * 24 * 3600) + (3600 * hours) + (60 * minutes) + seconds + 1) * 1000;
logger.info("Detected waittime #2, waiting " + waittime + "milliseconds");
/* Not enough wait time to reconnect -> Wait short and retry */
if (waittime < 180000) { throw new PluginException(LinkStatus.ERROR_HOSTER_TEMPORARILY_UNAVAILABLE, JDL.L("plugins.hoster.xfilesharingprobasic.allwait", ALLWAIT_SHORT), waittime); }
throw new PluginException(LinkStatus.ERROR_IP_BLOCKED, null, waittime);
}
}
if (correctedBR.contains("You're using all download slots for IP")) { throw new PluginException(LinkStatus.ERROR_IP_BLOCKED, null, 10 * 60 * 1001l); }
if (correctedBR.contains("Error happened when generating Download Link")) throw new PluginException(LinkStatus.ERROR_TEMPORARILY_UNAVAILABLE, "Server error!", 10 * 60 * 1000l);
/** Error handling for only-premium links */
if (new Regex(correctedBR, "( can download files up to |Upgrade your account to download bigger files|>Upgrade your account to download larger files|>The file you requested reached max downloads limit for Free Users|Please Buy Premium To download this file<|This file reached max downloads limit)").matches()) {
String filesizelimit = new Regex(correctedBR, "You can download files up to(.*?)only").getMatch(0);
if (filesizelimit != null) {
filesizelimit = filesizelimit.trim();
logger.info("As free user you can download files up to " + filesizelimit + " only");
try {
throw new PluginException(LinkStatus.ERROR_PREMIUM, PluginException.VALUE_ID_PREMIUM_ONLY);
} catch (final Throwable e) {
if (e instanceof PluginException) throw (PluginException) e;
}
throw new PluginException(LinkStatus.ERROR_FATAL, PREMIUMONLY1 + " " + filesizelimit);
} else {
logger.info("Only downloadable via premium");
try {
throw new PluginException(LinkStatus.ERROR_PREMIUM, PluginException.VALUE_ID_PREMIUM_ONLY);
} catch (final Throwable e) {
if (e instanceof PluginException) throw (PluginException) e;
}
throw new PluginException(LinkStatus.ERROR_FATAL, PREMIUMONLY2);
}
} else if (br.getURL().contains("/?op=login&redirect=")) {
logger.info("Only downloadable via premium");
try {
throw new PluginException(LinkStatus.ERROR_PREMIUM, PluginException.VALUE_ID_PREMIUM_ONLY);
} catch (final Throwable e) {
if (e instanceof PluginException) throw (PluginException) e;
}
throw new PluginException(LinkStatus.ERROR_FATAL, PREMIUMONLY2);
}
if (new Regex(correctedBR, MAINTENANCE).matches()) throw new PluginException(LinkStatus.ERROR_TEMPORARILY_UNAVAILABLE, MAINTENANCEUSERTEXT, 2 * 60 * 60 * 1000l);
}
public void checkServerErrors() throws NumberFormatException, PluginException {
if (new Regex(correctedBR, Pattern.compile("No file", Pattern.CASE_INSENSITIVE)).matches()) throw new PluginException(LinkStatus.ERROR_TEMPORARILY_UNAVAILABLE, "Server error: 'no file'", 2 * 60 * 60 * 1000l);
if (new Regex(correctedBR, Pattern.compile("Wrong IP", Pattern.CASE_INSENSITIVE)).matches()) throw new PluginException(LinkStatus.ERROR_TEMPORARILY_UNAVAILABLE, "Server error: 'Wrong IP'", 2 * 60 * 60 * 1000l);
if (new Regex(correctedBR, "(File Not Found|<h1>404 Not Found</h1>)").matches()) throw new PluginException(LinkStatus.ERROR_TEMPORARILY_UNAVAILABLE, "Server error (404)", 30 * 60 * 1000l);
}
/**
* Is intended to handle out of date errors which might occur seldom by re-tring a couple of times before throwing the out of date
* error.
*
* @param dl
* : The DownloadLink
* @param error
* : The name of the error
* @param maxRetries
* : Max retries before out of date error is thrown
*/
private void handlePluginBroken(final DownloadLink dl, final String error, final int maxRetries) throws PluginException {
int timesFailed = dl.getIntegerProperty(NICE_HOSTproperty + "failedtimes_" + error, 0);
dl.getLinkStatus().setRetryCount(0);
if (timesFailed <= maxRetries) {
logger.info(NICE_HOST + ": " + error + " -> Retrying");
timesFailed++;
dl.setProperty(NICE_HOSTproperty + "failedtimes_" + error, timesFailed);
throw new PluginException(LinkStatus.ERROR_RETRY, "Final download link not found");
} else {
dl.setProperty(NICE_HOSTproperty + "failedtimes_" + error, Property.NULL);
logger.info(NICE_HOST + ": " + error + " -> Plugin is broken");
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
}
@Override
public void reset() {
}
@Override
public void resetDownloadlink(DownloadLink link) {
}
}