Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package jd.plugins.hoster;
- import java.io.File;
- import java.io.IOException;
- import java.net.URL;
- import java.util.Locale;
- import java.util.concurrent.atomic.AtomicReference;
- import jd.PluginWrapper;
- import jd.config.Property;
- import jd.http.Browser;
- import jd.http.Cookies;
- import jd.http.RequestHeader;
- import jd.http.URLConnectionAdapter;
- import jd.nutils.encoding.Encoding;
- import jd.parser.Regex;
- import jd.plugins.Account;
- import jd.plugins.Account.AccountType;
- import jd.plugins.AccountInfo;
- import jd.plugins.BrowserAdapter;
- import jd.plugins.DownloadLink;
- import jd.plugins.DownloadLink.AvailableStatus;
- import jd.plugins.HostPlugin;
- import jd.plugins.Plugin;
- import jd.plugins.PluginException;
- import jd.plugins.PluginForHost;
- import jd.plugins.components.SiteType.SiteTemplate;
- import jd.plugins.download.DownloadInterface;
- import org.appwork.utils.formatter.SizeFormatter;
- import org.appwork.utils.formatter.TimeFormatter;
- import org.appwork.utils.logging2.LogInterface;
- import org.jdownloader.captcha.v2.challenge.recaptcha.v1.Recaptcha;
- import org.jdownloader.captcha.v2.challenge.recaptcha.v2.CaptchaHelperHostPluginRecaptchaV2;
- import org.jdownloader.captcha.v2.challenge.solvemedia.SolveMedia;
- @HostPlugin(revision="$Revision: 35558 $", interfaceVersion=2, names={"rapidpaid.com"}, urls={"https?://(?:www\\.)?rapidpaid\\.com/[A-Za-z0-9]+"})
- public class RapidpaidCom
- extends PluginForHost
- {
- public RapidpaidCom(PluginWrapper wrapper)
- {
- super(wrapper);
- enablePremium("http://rapidpaid.com/upgrade.html");
- }
- public String getAGBLink()
- {
- return "http://rapidpaid.com/terms.html";
- }
- private final String mainpage = "http://rapidpaid.com";
- private final String domains = "(rapidpaid\\.com)";
- private final String type = "html";
- private static final int wait_BETWEEN_DOWNLOADS_LIMIT_MINUTES_DEFAULT = 10;
- private static final int additional_WAIT_SECONDS = 3;
- private static final int directlinkfound_WAIT_SECONDS = 10;
- private static final boolean supportshttps = false;
- private static final boolean supportshttps_FORCED = false;
- private static final boolean available_CHECK_OVER_INFO_PAGE = true;
- private static final boolean useOldLoginMethod = false;
- private static final boolean enable_RANDOM_UA = false;
- private static final String url_ERROR_SIMULTANDLSLIMIT = "e=You+have+reached+the+maximum+concurrent+downloads";
- private static final String url_ERROR_SERVER = "e=Error%3A+Could+not+open+file+for+reading.";
- private static final String url_ERROR_WAIT_BETWEEN_DOWNLOADS_LIMIT = "e=You+must+wait+";
- private static final String url_ERROR_PREMIUMONLY = "(.+e=You\\+must\\+register\\+for\\+a\\+premium\\+account\\+to.+|.+/register\\..+)";
- private static final String errortext_ERROR_WAIT_BETWEEN_DOWNLOADS_LIMIT = "You must wait between downloads!";
- private static final String errortext_ERROR_SERVER = "Server error";
- private static final String errortext_ERROR_PREMIUMONLY = "This file can only be downloaded by premium (or registered) users";
- private static final String errortext_ERROR_SIMULTANDLSLIMIT = "Max. simultan downloads limit reached, wait to start more downloads from this host";
- 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 = 1;
- private static final int account_PREMIUM_MAXDOWNLOADS = 1;
- private static AtomicReference<String> agent = new AtomicReference(null);
- public void correctDownloadLink(DownloadLink link)
- {
- link.setUrlDownload(link.getDownloadURL().replaceFirst("https://", "http://"));
- }
- public DownloadLink.AvailableStatus requestFileInformation(DownloadLink link)
- throws IOException, PluginException
- {
- setBrowserExclusive();
- this.br.setFollowRedirects(true);
- prepBrowser(this.br);
- String fid = getFID(link);
- link.setLinkID(fid);
- this.br.getPage(link.getDownloadURL() + "~i");
- if ((!this.br.getURL().contains("~i")) || (this.br.getHttpConnection().getResponseCode() == 404)) {
- throw new PluginException(32);
- }
- String[] tableData = this.br.getRegex("class=\"responsiveInfoTable\">([^<>\"/]*?)<").getColumn(0);
- String filename = this.br.getRegex("data\\-animation\\-delay=\"\\d+\">(?:Information about|Informacion) ([^<>\"]*?)</div>").getMatch(0);
- if (filename == null) {
- filename = this.br.getRegex("class=\"description\\-1\">Information about ([^<>\"]+)<").getMatch(0);
- }
- if (filename == null) {
- filename = this.br.getRegex("(?:Filename|Dateiname|??? ?????|Nome):[\t\n\r ]*?</td>[\t\n\r ]*?<td(?: class=\"responsiveInfoTable\")?>([^<>\"]*?)<").getMatch(0);
- }
- String filesize = this.br.getRegex("(?:Filesize|Dateigr??e|??? ?????|Tamanho):[\t\n\r ]*?</td>[\t\n\r ]*?<td(?: class=\"responsiveInfoTable\")?>([^<>\"]*?)<").getMatch(0);
- try
- {
- if (filename == null) {
- filename = tableData[0];
- }
- if (filesize == null) {
- filesize = tableData[1];
- }
- }
- catch (Throwable e) {}
- if ((filename == null) || (inValidate(Encoding.htmlDecode(filename).trim())) || (Encoding.htmlDecode(filename).trim().equals("��"))) {
- filename = fid;
- }
- if ((filename == null) || (filesize == null)) {
- throw new PluginException(4194304);
- }
- link.setName(Encoding.htmlDecode(filename).trim());
- link.setDownloadSize(SizeFormatter.getSize(Encoding.htmlDecode(filesize.replace(",", "")).trim()));
- return DownloadLink.AvailableStatus.TRUE;
- }
- public void handleFree(DownloadLink downloadLink)
- throws Exception, PluginException
- {
- requestFileInformation(downloadLink);
- doFree(downloadLink, true, 1, "free_directlink");
- }
- public void doFree(DownloadLink link, boolean resume, int maxchunks, String directlinkproperty)
- throws Exception, PluginException
- {
- boolean skipWaittime = false;
- String continue_link = null;
- boolean captcha = false;
- boolean success = false;
- long timeBeforeDirectlinkCheck = System.currentTimeMillis();
- continue_link = checkDirectLink(link, directlinkproperty);
- if (continue_link != null)
- {
- if (System.currentTimeMillis() - timeBeforeDirectlinkCheck > 1500L) {
- sleep(10000L, link);
- }
- this.dl = BrowserAdapter.openDownload(this.br, link, continue_link, resume, maxchunks);
- }
- else
- {
- this.br.getPage(link.getDownloadURL());
- handleErrors();
- handlePassword(link);
- for (int i = 1; i <= 5; i++)
- {
- this.logger.info("Handling pre-download page #" + i);
- long timeBeforeCaptchaInput = System.currentTimeMillis();
- continue_link = getContinueLink();
- if ((i == 1) && (continue_link == null))
- {
- this.logger.info("No continue_link available, plugin broken");
- throw new PluginException(4194304);
- }
- if (continue_link == null)
- {
- this.logger.info("No continue_link available, stepping out of pre-download loop");
- break;
- }
- this.logger.info("Found continue_link, continuing...");
- String rcID = this.br.getRegex("recaptcha/api/noscript\\?k=([^<>\"]*?)\"").getMatch(0);
- if (isDownloadlink(continue_link))
- {
- this.dl = BrowserAdapter.openDownload(this.br, link, continue_link, resume, maxchunks);
- }
- else if (this.br.containsHTML("data\\-sitekey="))
- {
- captcha = true;
- String recaptchaV2Response = new CaptchaHelperHostPluginRecaptchaV2(this, this.br).getToken();
- success = true;
- waitTime(link, timeBeforeCaptchaInput, skipWaittime);
- this.dl = BrowserAdapter.openDownload(this.br, link, continue_link, "submit=Submit&submitted=1&d=1&capcode=false&g-recaptcha-response=" + recaptchaV2Response, resume, maxchunks);
- }
- else if (rcID != null)
- {
- captcha = true;
- success = false;
- Recaptcha rc = new Recaptcha(this.br, this);
- rc.setId(rcID);
- rc.load();
- File cf = rc.downloadCaptcha(getLocalCaptchaFile());
- String c = getCaptchaCode("recaptcha", cf, link);
- waitTime(link, timeBeforeCaptchaInput, skipWaittime);
- this.dl = BrowserAdapter.openDownload(this.br, link, continue_link, "submit=continue&submitted=1&d=1&recaptcha_challenge_field=" + rc.getChallenge() + "&recaptcha_response_field=" + c, resume, maxchunks);
- }
- else if (this.br.containsHTML("solvemedia\\.com/papi/"))
- {
- captcha = true;
- success = false;
- this.logger.info("Detected captcha method \"solvemedia\" for this host");
- SolveMedia sm = new SolveMedia(this.br);
- if (this.br.containsHTML("api\\-secure\\.solvemedia\\.com/")) {
- sm.setSecure(true);
- }
- File cf = null;
- try
- {
- cf = sm.downloadCaptcha(getLocalCaptchaFile());
- }
- catch (Exception e)
- {
- if ("SolveMedia Module fails --> Probably a host side bug/wrong key".equals(e.getMessage())) {
- throw new PluginException(131072, "Host side solvemedia.com captcha error - please contact the " + getHost() + " support");
- }
- throw e;
- }
- String code = getCaptchaCode("solvemedia", cf, link);
- String chid = sm.getChallenge(code);
- waitTime(link, timeBeforeCaptchaInput, skipWaittime);
- this.dl = BrowserAdapter.openDownload(this.br, link, continue_link, "submit=continue&submitted=1&d=1&adcopy_challenge=" + Encoding.urlEncode(chid) + "&adcopy_response=" + Encoding.urlEncode(code), resume, maxchunks);
- }
- else
- {
- success = true;
- waitTime(link, timeBeforeCaptchaInput, skipWaittime);
- this.dl = BrowserAdapter.openDownload(this.br, link, continue_link, resume, maxchunks);
- }
- checkResponseCodeErrors(this.dl.getConnection());
- if (this.dl.getConnection().isContentDisposition())
- {
- success = true;
- break;
- }
- this.br.followConnection();
- handleErrors();
- if ((captcha) && (this.br.containsHTML("(api\\.recaptcha\\.net|google\\.com/recaptcha/api/)"))) {
- this.logger.info("Wrong captcha");
- }
- }
- }
- checkResponseCodeErrors(this.dl.getConnection());
- if (!this.dl.getConnection().isContentDisposition())
- {
- this.br.followConnection();
- if ((captcha) && (!success)) {
- throw new PluginException(8);
- }
- handleErrors();
- throw new PluginException(4194304);
- }
- continue_link = this.dl.getConnection().getURL().toString();
- link.setProperty(directlinkproperty, continue_link);
- this.dl.startDownload();
- }
- private String getContinueLink()
- {
- String continue_link = this.br.getRegex("\\$\\(\\'\\.download\\-timer\\'\\)\\.html\\(\"<a href=\\'(https?://[^<>\"]*?)\\'").getMatch(0);
- if (continue_link == null) {
- continue_link = this.br.getRegex("class=\\'btn btn\\-free\\' href=\\'(https?://[^<>\"]*?)\\'>").getMatch(0);
- }
- if (continue_link == null) {
- continue_link = this.br.getRegex("<div class=\"captchaPageTable\">[\t\n\r ]+<form method=\"POST\" action=\"(https?://[^<>\"]*?)\"").getMatch(0);
- }
- if (continue_link == null) {
- continue_link = this.br.getRegex("(?:\"|\\')(https?://(www\\.)?(rapidpaid\\.com)/[^<>\"]*?pt=[^<>\"]*?)(?:\"|\\')").getMatch(0);
- }
- if (continue_link == null) {
- continue_link = getDllink();
- }
- return continue_link;
- }
- private String getDllink()
- {
- return this.br.getRegex("\"(https?://(www\\.)?(?:[A-Za-z0-9\\.]+\\.)?(rapidpaid\\.com)/[^<>\"\\?]*?\\?download_token=[A-Za-z0-9]+)\"").getMatch(0);
- }
- private boolean isDownloadlink(String url)
- {
- boolean isdownloadlink = url.contains("download_token=");
- return isdownloadlink;
- }
- private void handlePassword(DownloadLink dl)
- throws PluginException, IOException
- {
- if (this.br.getURL().contains("/file_password.html"))
- {
- this.logger.info("Current link is password protected");
- String passCode = dl.getStringProperty("pass", null);
- if (passCode == null)
- {
- passCode = Plugin.getUserInput("Password?", dl);
- if ((passCode == null) || (passCode.equals("")))
- {
- this.logger.info("User has entered blank password, exiting handlePassword");
- dl.setProperty("pass", Property.NULL);
- throw new PluginException(4, "Wrong password entered");
- }
- dl.setProperty("pass", passCode);
- }
- this.br.postPage(this.br.getURL(), "submit=access+file&submitme=1&file=" + getFID(dl) + "&filePassword=" + Encoding.urlEncode(passCode));
- if (this.br.getURL().contains("/file_password.html"))
- {
- this.logger.info("User entered incorrect password --> Retrying");
- dl.setProperty("pass", Property.NULL);
- throw new PluginException(4, "Wrong password entered");
- }
- this.logger.info("User entered correct password --> Continuing");
- }
- }
- private void waitTime(DownloadLink downloadLink, long timeBefore, boolean skipWaittime)
- throws PluginException
- {
- if (skipWaittime)
- {
- this.logger.info("Skipping waittime");
- }
- else
- {
- int wait = 0;
- int passedTime = (int)((System.currentTimeMillis() - timeBefore) / 1000L) - 1;
- String ttt = this.br.getRegex("\\$\\(\\'\\.download\\-timer\\-seconds\\'\\)\\.html\\((\\d+)\\);").getMatch(0);
- if (ttt == null) {
- ttt = this.br.getRegex("var\\s*?seconds\\s*?= (\\d+);").getMatch(0);
- }
- if (ttt != null)
- {
- this.logger.info("Found waittime, parsing waittime: " + ttt);
- wait = Integer.parseInt(ttt) + 3;
- wait -= passedTime;
- if (wait > 0)
- {
- this.logger.info("Waittime minus captcha input time: " + wait);
- sleep(wait * 1000L, downloadLink);
- }
- else
- {
- this.logger.info("Waittime is zero or lower, not waiting");
- }
- }
- else
- {
- this.logger.info("Failed to find waittime, either there is none or plugin is out of date");
- }
- }
- }
- private void handleErrors()
- throws PluginException
- {
- if (this.br.containsHTML("Error: Too many concurrent download requests")) {
- throw new PluginException(4096, "Wait before starting new downloads", 180000L);
- }
- if (this.br.getURL().contains("e=You+have+reached+the+maximum+concurrent+downloads")) {
- throw new PluginException(4096, "Max. simultan downloads limit reached, wait to start more downloads from this host", 60000L);
- }
- if (this.br.getURL().contains("error.php?e=Error%3A+Could+not+open+file+for+reading")) {
- throw new PluginException(4096, "Server error", 3600000L);
- }
- if (this.br.getURL().contains("e=You+must+wait+"))
- {
- String wait_minutes = new Regex(this.br.getURL(), "wait\\+(\\d+)\\+minutes?").getMatch(0);
- if (wait_minutes != null) {
- throw new PluginException(16, "You must wait between downloads!", Integer.parseInt(wait_minutes) * 60 * 1001L);
- }
- throw new PluginException(16, "You must wait between downloads!", 600600L);
- }
- if (this.br.getURL().matches("(.+e=You\\+must\\+register\\+for\\+a\\+premium\\+account\\+to.+|.+/register\\..+)")) {
- throw new PluginException(256, PluginException.VALUE_ID_PREMIUM_ONLY);
- }
- if (this.br.getURL().contains("You+have+reached+the+maximum+permitted+downloads+in")) {
- throw new PluginException(16, "Daily limit reached", 10810800L);
- }
- if (this.br.toString().equals("unknown user")) {
- throw new PluginException(2048, "Server error 'Unknown user'", 1800000L);
- }
- checkResponseCodeErrors(this.br.getHttpConnection());
- }
- private void checkResponseCodeErrors(URLConnectionAdapter con)
- throws PluginException
- {
- if (con == null) {
- return;
- }
- long responsecode = con.getResponseCode();
- if (responsecode == 403L) {
- throw new PluginException(2048, "Server error 403", 300000L);
- }
- if (responsecode == 404L) {
- throw new PluginException(2048, "Server error 404", 300000L);
- }
- if (responsecode == 416L) {
- throw new PluginException(2048, "Server error 416", 120000L);
- }
- if (responsecode == 429L) {
- throw new PluginException(4096, "Server error 429 connection limit reached, please contact our support!", 300000L);
- }
- }
- private String checkDirectLink(DownloadLink downloadLink, String property)
- {
- dllink = downloadLink.getStringProperty(property);
- if (dllink != null)
- {
- Browser br2 = this.br.cloneBrowser();
- br2.setFollowRedirects(true);
- URLConnectionAdapter con = null;
- try
- {
- con = br2.openHeadConnection(dllink);
- if ((con.getContentType().contains("html")) || (con.getLongContentLength() == -1L)) {
- downloadLink.setProperty(property, Property.NULL);
- }
- return null;
- }
- catch (Exception e)
- {
- downloadLink.setProperty(property, Property.NULL);
- dllink = null;
- }
- finally
- {
- try
- {
- con.disconnect();
- }
- catch (Throwable e) {}
- }
- }
- }
- private String getFID(DownloadLink dl)
- {
- return new Regex(dl.getDownloadURL(), "([A-Za-z0-9]+)$").getMatch(0);
- }
- private boolean inValidate(String s)
- {
- if ((s == null) || ((s != null) && ((s.matches("[\r\n\t ]+")) || (s.equals(""))))) {
- return true;
- }
- return false;
- }
- private String getProtocol()
- {
- if ((this.br.getURL() != null) && (this.br.getURL().contains("https://"))) {
- return "https://";
- }
- return "http://";
- }
- public int getMaxSimultanFreeDownloadNum()
- {
- return 1;
- }
- private Browser prepBrowser(Browser br)
- {
- br.setAllowedResponseCodes(new int[] { 416, 429 });
- return br;
- }
- private static final Object LOCK = new Object();
- private void login(Account account, boolean force)
- throws Exception
- {
- synchronized (LOCK)
- {
- try
- {
- this.br.setCookiesExclusive(true);
- prepBrowser(this.br);
- this.br.setFollowRedirects(true);
- Cookies cookies = account.loadCookies("");
- if ((cookies != null) && (!force))
- {
- this.br.setCookies(getHost(), cookies);
- return;
- }
- this.br.getPage(getProtocol() + getHost() + "/");
- String lang = System.getProperty("user.language");
- String loginstart = new Regex(this.br.getURL(), "(https?://(www\\.)?)").getMatch(0);
- this.br.getPage(getProtocol() + getHost() + "/login." + "html");
- String loginpostpage = loginstart + getHost() + "/ajax/_account_login.ajax.php";
- this.br.getHeaders().put("X-Requested-With", "XMLHttpRequest");
- this.br.getHeaders().put("Accept", "application/json, text/javascript, */*; q=0.01");
- this.br.postPage(loginpostpage, "username=" + Encoding.urlEncode(account.getUser()) + "&password=" + Encoding.urlEncode(account.getPass()));
- if (!this.br.containsHTML("\"login_status\":\"success\""))
- {
- if ("de".equalsIgnoreCase(lang)) {
- throw new PluginException(256, "\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);
- }
- throw new PluginException(256, "\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);
- }
- this.br.getPage(loginstart + getHost() + "/account_home." + "html");
- account.saveCookies(this.br.getCookies(getHost()), "");
- }
- catch (PluginException e)
- {
- account.clearCookies("");
- throw e;
- }
- }
- }
- public AccountInfo fetchAccountInfo(Account account)
- throws Exception
- {
- AccountInfo ai = new AccountInfo();
- try
- {
- login(account, true);
- }
- catch (PluginException e)
- {
- account.setValid(false);
- throw e;
- }
- if (!this.br.containsHTML("class=\"badge badge\\-success\">(?:PAID USER|USUARIO DE PAGO)</span>"))
- {
- account.setType(Account.AccountType.FREE);
- account.setMaxSimultanDownloads(1);
- account.setConcurrentUsePossible(false);
- ai.setStatus("Registered (free) account");
- }
- else
- {
- this.br.getPage("http://" + getHost() + "/upgrade." + "html");
- String expire = this.br.getRegex("Reverts To Free Account:[\t\n\r ]+</td>[\t\n\r ]+<td>[\t\n\r ]+(\\d{2}/\\d{2}/\\d{4} \\d{2}:\\d{2}:\\d{2})").getMatch(0);
- if (expire == null) {
- expire = this.br.getRegex(">[\t\n\r ]*?(\\d{2}/\\d{2}/\\d{4} \\d{2}:\\d{2}:\\d{2})[\t\n\r ]*?<").getMatch(0);
- }
- if (expire == null)
- {
- account.setValid(false);
- return ai;
- }
- long expire_milliseconds = 0L;
- expire_milliseconds = TimeFormatter.getMilliSeconds(expire, "MM/dd/yyyy hh:mm:ss", Locale.ENGLISH);
- if (expire_milliseconds - System.currentTimeMillis() <= 0L)
- {
- account.setType(Account.AccountType.FREE);
- account.setMaxSimultanDownloads(1);
- account.setConcurrentUsePossible(false);
- ai.setStatus("Registered (free) user");
- }
- else
- {
- ai.setValidUntil(expire_milliseconds);
- account.setType(Account.AccountType.PREMIUM);
- account.setMaxSimultanDownloads(1);
- ai.setStatus("Premium account");
- }
- }
- account.setValid(true);
- ai.setUnlimitedTraffic();
- return ai;
- }
- public void handlePremium(DownloadLink link, Account account)
- throws Exception
- {
- requestFileInformation(link);
- login(account, false);
- if (account.getType() == Account.AccountType.FREE)
- {
- doFree(link, true, 1, "free_acc_directlink");
- }
- else
- {
- String dllink = link.getDownloadURL();
- this.dl = BrowserAdapter.openDownload(this.br, link, dllink, true, 1);
- checkResponseCodeErrors(this.dl.getConnection());
- if (!this.dl.getConnection().isContentDisposition())
- {
- this.logger.warning("The final dllink seems not to be a file, checking for errors...");
- this.br.followConnection();
- handleErrors();
- this.logger.info("Found no errors, let's see if we can find the dllink now...");
- handlePassword(link);
- dllink = getDllink();
- if (dllink == null)
- {
- handleErrors();
- throw new PluginException(4194304);
- }
- this.dl = BrowserAdapter.openDownload(this.br, link, dllink, true, 1);
- checkResponseCodeErrors(this.dl.getConnection());
- }
- if (!this.dl.getConnection().isContentDisposition())
- {
- this.logger.warning("The final dllink seems not to be a file!");
- this.br.followConnection();
- handleErrors();
- throw new PluginException(4194304);
- }
- this.dl.startDownload();
- }
- }
- public int getMaxSimultanPremiumDownloadNum()
- {
- return 1;
- }
- public void reset() {}
- public void resetDownloadlink(DownloadLink link) {}
- public SiteType.SiteTemplate siteTemplateType()
- {
- return SiteType.SiteTemplate.MFScripts_YetiShare;
- }
- }
Add Comment
Please, Sign In to add comment