예제 #1
0
 @SuppressWarnings("deprecation")
 @Override
 public AccountInfo fetchAccountInfo(final Account account) throws Exception {
   final AccountInfo ai = new AccountInfo();
   try {
     login(account, true);
   } catch (PluginException e) {
     account.setValid(false);
     throw e;
   }
   prepBRAjax(account);
   this.br.getPage("https://www." + this.getHost() + "/api/payments?limit=25&offset=0");
   ai.setUnlimitedTraffic();
   final String subscriptioncount = PluginJSonUtils.getJsonValue(this.br, "count");
   if (subscriptioncount == null || subscriptioncount.equals("0")) {
     account.setType(AccountType.FREE);
     /* free accounts can still have captcha */
     account.setMaxSimultanDownloads(ACCOUNT_PREMIUM_MAXDOWNLOADS);
     account.setConcurrentUsePossible(false);
     ai.setStatus("Registered (free) user");
   } else {
     /* TODO: Add expire date */
     // final String expire = null;
     // if (expire != null) {
     // ai.setValidUntil(TimeFormatter.getMilliSeconds(expire, "dd MMMM yyyy", Locale.ENGLISH));
     // }
     account.setType(AccountType.PREMIUM);
     account.setMaxSimultanDownloads(ACCOUNT_PREMIUM_MAXDOWNLOADS);
     account.setConcurrentUsePossible(true);
     ai.setStatus("Premium account");
   }
   account.setValid(true);
   return ai;
 }
예제 #2
0
 public AccountInfo fetchAccountInfoWebsite(final Account account) throws Exception {
   final AccountInfo ai = new AccountInfo();
   synchronized (HotFileCom.LOCK) {
     setBrowserExclusive();
     try {
       loginWebsite(account);
     } catch (final PluginException e) {
       account.setProperty("cookies", null);
       account.setValid(false);
       return ai;
     }
     final String validUntil[] =
         br.getRegex("Premium until.*?>(.*?)<.*?>(\\d+:\\d+:\\d+)").getRow(0);
     if (validUntil == null || validUntil[0] == null || validUntil[1] == null) {
       logger.severe("HotFileDebug(WebsiteAccCheck): " + br.toString());
       account.setProperty("cookies", null);
       account.setValid(false);
     } else {
       final String valid = validUntil[0].trim() + " " + validUntil[1].trim() + " CDT";
       ai.setValidUntil(TimeFormatter.getMilliSeconds(valid, "yyyy-MM-dd HH:mm:ss zzz", null));
       account.setValid(true);
     }
   }
   return ai;
 }
예제 #3
0
 private AccountInfo fetchAccountInfoAPI(final Account account) {
   final AccountInfo ai = new AccountInfo();
   final String type = PluginJSonUtils.getJsonValue(br, "type");
   final String expireTime = PluginJSonUtils.getJsonValue(br, "expireTime");
   final String traffic = PluginJSonUtils.getJsonValue(br, "traffic");
   long expire_long = 0;
   if (expireTime != null) {
     expire_long = Long.parseLong(expireTime) * 1000l;
   }
   if ("Free".equals(type) || expire_long < System.currentTimeMillis()) {
     account.setType(AccountType.FREE);
     account.setMaxSimultanDownloads(1);
     ai.setStatus(getPhrase("FREE"));
   } else {
     account.setType(AccountType.PREMIUM);
     ai.setStatus(getPhrase("PREMIUM"));
   }
   if (traffic != null) {
     ai.setTrafficLeft(Long.parseLong(traffic));
   }
   if (expire_long > System.currentTimeMillis()) {
     ai.setValidUntil(Long.parseLong(expireTime) * 1000l);
   }
   return ai;
 }
 @Override
 protected String getStringValue(Object value) {
   if (value instanceof Account) {
     Account ac = (Account) value;
     AccountInfo ai = ac.getAccountInfo();
     if (ai != null && ai.getFilesNum() >= 0) return String.valueOf(ai.getFilesNum());
   }
   return "";
 }
예제 #5
0
 @Override
 public AccountInfo fetchAccountInfo(final Account account) throws Exception {
   final AccountInfo ai = new AccountInfo();
   try {
     login(account, true);
   } catch (final PluginException e) {
     account.setValid(false);
     return ai;
   }
   ai.setStatus("Registered (free) User");
   return ai;
 }
예제 #6
0
 @Override
 public AccountInfo fetchAccountInfo(Account account) throws Exception {
   AccountInfo ai = new AccountInfo();
   try {
     login(account, true);
   } catch (PluginException e) {
     account.setValid(false);
     return ai;
   }
   String space =
       br.getRegex(
               Pattern.compile(
                   "<td>Used space:</td>.*?<td.*?b>([0-9\\.]+) of [0-9\\.]+ (Mb|GB)</b>",
                   Pattern.DOTALL | Pattern.CASE_INSENSITIVE))
           .getMatch(0);
   if (space != null) {
     ai.setUsedSpace(space.trim() + " Mb");
   }
   account.setValid(true);
   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 (account.getBooleanProperty("nopremium")) {
     ai.setStatus("Registered (free) User");
   } else {
     String expire =
         new Regex(
                 correctedBR,
                 Pattern.compile(
                     "<td>Premium(\\-| )Account expires?:</td>.*?<td>(<b>)?(\\d{1,2} [A-Za-z]+ \\d{4})(</b>)?</td>",
                     Pattern.CASE_INSENSITIVE))
             .getMatch(2);
     if (expire == null) {
       ai.setExpired(true);
       account.setValid(false);
       return ai;
     } else {
       expire = expire.replaceAll("(<b>|</b>)", "");
       ai.setValidUntil(TimeFormatter.getMilliSeconds(expire, "dd MMMM yyyy", null));
     }
     ai.setStatus("Premium User");
   }
   return ai;
 }
예제 #7
0
 @Override
 public AccountInfo fetchAccountInfo(Account account) throws Exception {
   AccountInfo ai = new AccountInfo();
   try {
     login(account);
   } catch (PluginException e) {
     account.setValid(false);
     return ai;
   }
   ai.setUnlimitedTraffic();
   ai.setStatus("Registered User");
   return ai;
 }
예제 #8
0
 @Override
 public AccountInfo fetchAccountInfo(Account account) throws Exception {
   AccountInfo ai = new AccountInfo();
   try {
     login(account, true);
   } catch (PluginException e) {
     account.setValid(false);
     return ai;
   }
   account.setValid(true);
   ai.setStatus("Premium User");
   return ai;
 }
예제 #9
0
  @SuppressWarnings("deprecation")
  @Override
  public AccountInfo fetchAccountInfo(final Account account) throws Exception {
    final AccountInfo ai = new AccountInfo();
    try {
      login(account, true);
    } catch (final PluginException e) {
      account.setValid(false);
      throw e;
    }

    account.setValid(true);
    ai.setUnlimitedTraffic();
    final String expire =
        br.getRegex("expire:</span><span class=\"info\">([^<>\"]*?)</span>").getMatch(0);
    ai.setValidUntil(TimeFormatter.getMilliSeconds(expire, "dd MMM yyyy", Locale.ENGLISH));
    ai.setStatus("Premium user");
    return ai;
  }
예제 #10
0
 @Override
 public AccountInfo fetchAccountInfo(Account account) throws Exception {
   AccountInfo ai = new AccountInfo();
   try {
     login(account, true);
   } catch (PluginException e) {
     account.setValid(false);
     return ai;
   }
   String hostedFiles = br.getRegex("<td>Files Hosted:</td>[\t\r\n ]+<td>(\\d+)</td>").getMatch(0);
   if (hostedFiles != null) ai.setFilesNum(Integer.parseInt(hostedFiles));
   String space =
       br.getRegex("<td>Spaced Used:</td>[\t\n\r ]+<td>(.*?) " + PREMIUMLIMIT).getMatch(0);
   if (space != null) ai.setUsedSpace(space.trim());
   account.setValid(true);
   ai.setUnlimitedTraffic();
   ai.setStatus("Premium User");
   return ai;
 }
예제 #11
0
 @Override
 public AccountInfo fetchAccountInfo(final Account account) throws Exception {
   AccountInfo ai = new AccountInfo();
   try {
     login(account);
   } catch (PluginException e) {
     account.setValid(false);
     return ai;
   }
   account.setValid(true);
   ai.setUnlimitedTraffic();
   String expire = br.getRegex("<TD>Premium-Account expire:</TD><TD><b>(.*?)</b>").getMatch(0);
   if (expire != null) {
     expire = expire.replaceAll("(<b>|</b>)", "");
     ai.setValidUntil(TimeFormatter.getMilliSeconds(expire, "dd MMMM yyyy", null));
   }
   ai.setStatus("Premium User");
   return ai;
 }
예제 #12
0
 @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;
   }
   if (account.getBooleanProperty("free", false)) {
     try {
       account.setType(AccountType.FREE);
       account.setMaxSimultanDownloads(ACCOUNT_FREE_MAXDOWNLOADS);
     } catch (final Throwable e) {
       /* Not available in old 0.9.581 Stable */
     }
     maxPrem.set(ACCOUNT_FREE_MAXDOWNLOADS);
     ai.setStatus("Registered (free) user");
   } else {
     br.getPage("http://www." + this.getHost() + "/upgrade." + TYPE);
     final String expire =
         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) {
       ai.setValidUntil(
           TimeFormatter.getMilliSeconds(expire, "dd/MM/yyyy hh:mm:ss", Locale.ENGLISH));
     }
     account.setValid(true);
     try {
       account.setType(AccountType.PREMIUM);
       account.setMaxSimultanDownloads(ACCOUNT_PREMIUM_MAXDOWNLOADS);
     } catch (final Throwable e) {
       /* Not available in old 0.9.581 Stable */
     }
     maxPrem.set(ACCOUNT_PREMIUM_MAXDOWNLOADS);
     ai.setStatus("Premium User");
   }
   ai.setUnlimitedTraffic();
   return ai;
 }
예제 #13
0
  @Override
  public AccountInfo fetchAccountInfo(Account account) throws Exception {
    AccountInfo ac = new AccountInfo();
    br.setConnectTimeout(60 * 1000);
    br.setReadTimeout(60 * 1000);
    String hosts;
    login(account);

    ac.setTrafficLeft(GetTrasferLeft(Info));

    ArrayList<String> supportedHosts = new ArrayList<String>();
    hosts = br.getPage("https://www.twojlimit.pl/clipboard.php");
    if (hosts != null) {
      String hoster[] = new Regex(hosts, "(.*?)(<br />|$)").getColumn(0);
      if (hosts != null) {
        for (String host : hoster) {
          if (hosts == null || host.length() == 0) {
            continue;
          }
          supportedHosts.add(host.trim());
        }
      }
    }
    if (expired) {
      ac.setExpired(true);
      ac.setStatus("Account expired");
      ac.setValidUntil(0);
      return ac;
    } else {
      ac.setExpired(false);
      if (validUntil != null) {
        if (validUntil.trim().equals("expire=00")) {
          ac.setValidUntil(-1);
        } else {
          ac.setValidUntil(TimeFormatter.getMilliSeconds(validUntil));
        }
      }
    }
    ac.setMultiHostSupport(this, supportedHosts);
    ac.setStatus("Account valid");
    return ac;
  }
예제 #14
0
 public boolean canHandle(DownloadLink link) {
   if (plugin == null) {
     return false;
   }
   final PluginForHost linkPlugin = link.getDefaultPlugin();
   boolean canHandle = linkPlugin == null ? true : linkPlugin.allowHandle(link, plugin);
   if (canHandle) {
     canHandle = plugin.canHandle(link, account) && plugin.enoughTrafficFor(link, account);
   }
   if (canHandle && ACCOUNTTYPE.MULTI.equals(getType()) && getAccount() != null) {
     final AccountInfo ai = getAccount().getAccountInfo();
     /* verify again because plugins can modify list on runtime */
     if (ai != null) {
       Object multiHostSupport = ai.getProperty("multiHostSupport", null);
       if (multiHostSupport != null && multiHostSupport instanceof List) {
         canHandle = ((List<Object>) multiHostSupport).contains(link.getHost());
       }
     }
   }
   return canHandle;
 }
예제 #15
0
 @Override
 public AccountInfo fetchAccountInfo(final Account account) throws Exception {
   AccountInfo ai = new AccountInfo();
   try {
     login(account);
   } catch (final PluginException e) {
     account.setValid(false);
     throw e;
   }
   account.setValid(true);
   ai.setUnlimitedTraffic();
   if (!nopremium) {
     String expire = br.getRegex("You have <b>premium</b> account till(.*?)</p>").getMatch(0);
     if (expire == null) {
       ai.setExpired(true);
       account.setValid(false);
       return ai;
     } else {
       ai.setValidUntil(TimeFormatter.getMilliSeconds(expire.trim(), "dd.MM.yyyy HH:mm", null));
     }
     ai.setStatus("Premium Account");
   } else {
     ai.setStatus("Registered (free) User");
   }
   return ai;
 }
예제 #16
0
 /**
  * Returns configuration from for the specified Account/Hoster combination.
  *
  * @param account Account for which the configuration should be retrieved.
  * @param link Link (used to extract the hoster) for which the configuration should be extracted.
  *     If null, a global setting will be returned instead of a hoster specific one.
  * @param key Name of the setting which should be retrieved.
  * @return retrieved configuration value
  */
 private Object getHosterSetting(Account account, DownloadLink link, String key) {
   AccountInfo ai = account.getAccountInfo();
   Map<String, Object> clientConfiguration =
       (Map<String, Object>) ai.getProperty(CLIENT_CONFIGURATION_KEY);
   if (clientConfiguration == null) {
     return null;
   }
   if (link == null) {
     return clientConfiguration.get(key);
   } else {
     Map<String, Object> allHostersSettings =
         (Map<String, Object>) clientConfiguration.get("supported_hosters");
     if (allHostersSettings != null) {
       Map<String, Object> hosterSettings =
           (Map<String, Object>) allHostersSettings.get(link.getHost());
       if (hosterSettings != null) {
         return hosterSettings.get(key);
       }
     }
   }
   return null;
 }
예제 #17
0
 @Override
 public AccountInfo fetchAccountInfo(final Account account) throws Exception {
   AccountInfo ai = new AccountInfo();
   /* reset maxPrem workaround on every fetchaccount info */
   try {
     synchronized (account) {
       String token = api_getAccessToken(account, false);
       String tokenType = null;
       try {
         tokenType = api_getTokenType(account, token, true);
       } catch (final PluginException e) {
         token = api_getAccessToken(account, false);
         tokenType = api_getTokenType(account, token, true);
       }
       if ("free".equals(tokenType)) {
         /* free user */
         ai.setStatus("Free accounts are not supported");
         account.setValid(false);
         account.setProperty("token", null);
         account.setProperty("tokenType", null);
       } else if ("premium".equals(tokenType)) {
         String traffic = br.getRegex("traffic_left\":\\s*?\"?(\\d+)").getMatch(0);
         long max = 100 * 1024 * 1024 * 1024l;
         long current = Long.parseLong(traffic);
         ai.setTrafficMax(Math.max(max, current));
         ai.setTrafficLeft(current);
         String expireDate = br.getRegex("account_premium\":\\s*?\"?(\\d+)").getMatch(0);
         ai.setValidUntil(Long.parseLong(expireDate) * 1000);
         if (current <= 0 || br.containsHTML("download_available\":false")) {
           String refreshIn = br.getRegex("traffic_reset\":\\s*?(\\d+)").getMatch(0);
           if (refreshIn != null) {
             account.setProperty(
                 "PROPERTY_TEMP_DISABLED_TIMEOUT", Long.parseLong(refreshIn) * 1000);
           } else {
             account.setProperty("PROPERTY_TEMP_DISABLED_TIMEOUT", Property.NULL);
           }
           logger.info("Download_available: " + br.containsHTML("download_available\":true"));
           throw new PluginException(
               LinkStatus.ERROR_PREMIUM, PluginException.VALUE_ID_PREMIUM_TEMP_DISABLE);
         }
         ai.setStatus("Premium account");
         if (!ai.isExpired()) account.setValid(true);
       } else {
         throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
       }
     }
   } catch (final PluginException e) {
     account.setProperty("token", null);
     account.setProperty("tokenType", null);
     throw e;
   }
   return ai;
 }
예제 #18
0
 @SuppressWarnings("deprecation")
 @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;
   }
   if (!br.containsHTML("class=\"badge badge\\-success\">(?:PAID USER|USUARIO DE PAGO)</span>")) {
     account.setType(AccountType.FREE);
     account.setMaxSimultanDownloads(account_FREE_MAXDOWNLOADS);
     /* All accounts get the same (IP-based) downloadlimits --> Simultan free account usage makes no sense! */
     account.setConcurrentUsePossible(false);
     MAXPREM.set(account_FREE_MAXDOWNLOADS);
     ai.setStatus("Registered (free) account");
   } else {
     br.getPage("http://" + this.getHost() + "/upgrade." + type);
     /* If the premium account is expired we'll simply accept it as a free account. */
     String expire =
         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) {
       /* More wide RegEx to be more language independant */
       expire =
           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 = 0;
     expire_milliseconds =
         TimeFormatter.getMilliSeconds(expire, "MM/dd/yyyy hh:mm:ss", Locale.ENGLISH);
     if ((expire_milliseconds - System.currentTimeMillis()) <= 0) {
       account.setType(AccountType.FREE);
       account.setMaxSimultanDownloads(account_FREE_MAXDOWNLOADS);
       /* All accounts get the same (IP-based) downloadlimits --> Simultan free account usage makes no sense! */
       account.setConcurrentUsePossible(false);
       MAXPREM.set(account_FREE_MAXDOWNLOADS);
       ai.setStatus("Registered (free) user");
     } else {
       ai.setValidUntil(expire_milliseconds);
       account.setType(AccountType.PREMIUM);
       account.setMaxSimultanDownloads(account_PREMIUM_MAXDOWNLOADS);
       MAXPREM.set(account_PREMIUM_MAXDOWNLOADS);
       ai.setStatus("Premium account");
     }
   }
   account.setValid(true);
   ai.setUnlimitedTraffic();
   return ai;
 }
  @Override
  public AccountInfo fetchAccountInfo(Account account) throws Exception {
    AccountInfo ai = new AccountInfo();
    setBrowserExclusive();
    HashMap<String, String> infos = null;
    try {
      infos = loginAPI(account, true);
    } catch (final PluginException e) {
      account.setValid(false);
      throw e;
    }
    /* evaluate expire date */
    final Long validUntil = Long.parseLong(infos.get("expire_date"));
    account.setValid(true);
    if (validUntil > 0) {
      ai.setValidUntil(validUntil * 1000);
    } else {
      ai.setValidUntil(-1);
    }
    if (infos.containsKey("points")) {
      ai.setPremiumPoints(Long.parseLong(infos.get("points")));
    }
    if (infos.containsKey("money")) {
      ai.setAccountBalance(infos.get("money"));
    }
    /* set account type */
    ai.setStatus(infos.get("group"));

    if (userTrafficWorkaround()) {
      long max = 100 * 1024 * 1024 * 1024l; // 100 GB per day - 420 GB per week
      String traffic = infos.get("traffic_1d"); // traffic_7d = week
      String trafficdata[] = traffic.split(";");
      long current = Long.parseLong(trafficdata[0].trim());
      ai.setTrafficMax(Math.max(max, current));
      ai.setTrafficLeft((max - current));
    }

    return ai;
  }
예제 #20
0
 @Override
 public AccountInfo fetchAccountInfo(final Account account) throws Exception {
   final AccountInfo ai = new AccountInfo();
   if (account.getUser().trim().equalsIgnoreCase("cookie")) {
     account.setValid(false);
     ai.setStatus("Cookie login no longer possible! API does not support it!");
     return ai;
   }
   if (getPluginConfig().getBooleanProperty(HotFileCom.TRY_IWL_BYPASS, false)) {
     return fetchAccountInfoWebsite(account);
   }
   final HashMap<String, String> info;
   try {
     info = callAPI(null, "getuserinfo", account, null);
   } catch (PluginException e) {
     account.setValid(false);
     return ai;
   }
   final String rawAnswer = info.get("httpresponse");
   logger.severe("HotFileDebug(ApiAccountCheck): " + rawAnswer);
   if (rawAnswer != null && rawAnswer.startsWith(".too many failed")) {
     /* fallback to normal website */
     logger.severe("api reports: too many failed logins(check logins)! using website fallback!");
     return fetchAccountInfoWebsite(account);
   }
   if (!info.containsKey("is_premium") || !"1".equalsIgnoreCase(info.get("is_premium"))) {
     account.setValid(false);
     if (info.get("httpresponse").contains("invalid username")) {
       ai.setStatus("invalid username or password");
     } else {
       ai.setStatus("No Premium Account");
     }
     return ai;
   }
   String validUntil = info.get("premium_until");
   if (validUntil == null) {
     account.setValid(false);
   } else {
     account.setValid(true);
     validUntil = validUntil.replaceAll(":|T", "");
     validUntil = validUntil.replaceFirst("-", "");
     validUntil = validUntil.replaceFirst("-", "");
     ai.setValidUntil(TimeFormatter.getMilliSeconds(validUntil, "yyyyMMddHHmmssZ", null));
     ai.setStatus("Premium");
   }
   return ai;
 }
예제 #21
0
  @SuppressWarnings({"deprecation"})
  @Override
  public AccountInfo fetchAccountInfo(final Account account) throws Exception {
    this.setConstants(account, null);
    this.br = newBrowser();
    final AccountInfo ai = new AccountInfo();
    br.setFollowRedirects(true);

    this.login(account, true);

    this.getAPISafe("/user_dashboard.php");

    final String accounttype = br.getRegex(">Status</td>.*?value=([^<>\"]*?)>").getMatch(0);
    final String validuntil = br.getRegex(">Expire Date</td>.*?value=([^<>\"]*?)>").getMatch(0);

    if (accounttype.equalsIgnoreCase("Premium")) {
      if (validuntil != null) {
        ai.setValidUntil(
            TimeFormatter.getMilliSeconds(validuntil, "yyyy-MM-dd HH:mm:ss", Locale.ENGLISH));
      }
      account.setType(AccountType.PREMIUM);
      ai.setStatus("Premium Account");
      ai.setUnlimitedTraffic();
    } else {
      account.setType(AccountType.FREE);
      ai.setStatus("Free Account");
      /* It's impossible to download anything with free accounts of this service. */
      ai.setTrafficLeft(0);
    }
    this.getAPISafe("/user_download.php");
    final String[] supportedHosts =
        br.getRegex("\\s+<img src=\"images/hosts/.*?\\.png\" title=\"(.*?)\"").getColumn(0);
    final List<String> list = Arrays.asList(supportedHosts);
    account.setValid(true);
    account.setConcurrentUsePossible(true);

    hostMaxchunksMap.clear();
    hostMaxdlsMap.clear();
    ai.setMultiHostSupport(this, list);
    return ai;
  }
예제 #22
0
  @Override
  public AccountInfo fetchAccountInfo(Account account) throws Exception {
    AccountInfo ai = new AccountInfo();
    try {
      login(account, true);
    } catch (PluginException e) {
      account.setValid(false);
      return ai;
    }
    if (!br.getURL().endsWith("/members.php")) br.getPage(COOKIE_HOST + "/members.php");
    String expired = getData("Expired\\?");
    if (expired != null) {
      expired = expired.trim();
      if (expired.equalsIgnoreCase("No")) ai.setExpired(false);
      else if (expired.equalsIgnoreCase("Yes")) ai.setExpired(true);
    }
    String expires = getData("Package Expire Date");
    if (expires != null) {
      String[] e = expires.split("/");
      Calendar cal =
          new GregorianCalendar(
              Integer.parseInt("20" + e[2]), Integer.parseInt(e[0]) - 1, Integer.parseInt(e[1]));
      ai.setValidUntil(cal.getTimeInMillis());
    }
    String create = getData("Register Date");
    if (create != null) {
      String[] c = create.split("/");
      Calendar cal =
          new GregorianCalendar(
              Integer.parseInt("20" + c[2]), Integer.parseInt(c[0]) - 1, Integer.parseInt(c[1]));
      ai.setCreateTime(cal.getTimeInMillis());
    }
    String files = getData("Hosted Files");
    if (files != null) {
      ai.setFilesNum(Integer.parseInt(files.trim()));
    }
    ai.setStatus("Premium User");
    account.setValid(true);

    return ai;
  }
예제 #23
0
 @Override
 public AccountInfo fetchAccountInfo(Account account) throws Exception {
   AccountInfo ac = new AccountInfo();
   br.setConnectTimeout(60 * 1000);
   br.setReadTimeout(60 * 1000);
   String username = Encoding.urlEncode(account.getUser());
   String pass = Encoding.urlEncode(account.getPass());
   String page = null;
   String hosts = null;
   try {
     page =
         br.getPage(
             "http://www."
                 + hostPublicDomain
                 + "/api/get_pa_info.php?login="******"&password="******"http://www." + hostPublicDomain + "/api/get_filehosters.php");
   } catch (Exception e) {
     account.setTempDisabled(true);
     account.setValid(true);
     ac.setProperty("multiHostSupport", Property.NULL);
     return ac;
   }
   if (page.startsWith("ERROR: Auth")) {
     account.setValid(false);
     ac.setProperty("multiHostSupport", Property.NULL);
     ac.setStatus(page);
     return ac;
   }
   /* parse api response in easy2handle hashmap */
   String info[] = new Regex(page, "(\\d+)($|\\|)").getColumn(0);
   boolean isunlimited = "1".equalsIgnoreCase(info[1]);
   long validUntil = Long.parseLong(info[2]);
   long inC = Long.parseLong(info[0]) * 1024 * 1024l;
   long outC = Long.parseLong(info[3]) * 1024 * 1024l;
   if (validUntil == 0) {
     account.setValid(false);
     ac.setProperty("multiHostSupport", Property.NULL);
     return ac;
   }
   ac.setValidUntil(validUntil * 1000);
   if (!isunlimited) {
     ac.setTrafficLeft(Math.min(inC, outC));
   } else {
     ac.setUnlimitedTraffic();
   }
   ArrayList<String> supportedHosts = new ArrayList<String>();
   if (hosts != null) {
     String hoster[] = new Regex(hosts, "(.+?)($|\\|)").getColumn(0);
     for (String host : hoster) {
       if (hosts != null) {
         supportedHosts.add(host.trim());
       }
     }
   }
   if (account.isValid()) {
     ac.setMultiHostSupport(this, supportedHosts);
   } else {
     account.setValid(false);
     ac.setProperty("multiHostSupport", Property.NULL);
     ac.setStatus("Account invalid");
   }
   return ac;
 }
  @Override
  public AccountInfo fetchAccountInfo(Account account) throws Exception {
    final AccountInfo ac = new AccountInfo();
    br.setConnectTimeout(60 * 1000);
    br.setReadTimeout(60 * 1000);
    ac.setProperty("multiHostSupport", Property.NULL);
    // check if account is valid
    if (!login(account, true)) {
      final String lang = System.getProperty("user.language");
      if ("de".equalsIgnoreCase(lang)) {
        throw new PluginException(
            LinkStatus.ERROR_PREMIUM,
            "\r\nUngültiger Benutzername/Passwort oder Login Captcha falsch eingegeben!\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 or wrong login captcha input!\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);
      }
    }
    br.getPage("http://www.premiumax.net/profile/");
    boolean is_freeaccount = false;
    final String expire =
        br.getRegex("<span>Premium until: </span><strong>([^<>\"]*?)</strong>").getMatch(0);
    if (expire != null) {
      ac.setValidUntil(TimeFormatter.getMilliSeconds(expire, "dd.MM.yyyy hh:mm", Locale.ENGLISH));
      ac.setStatus("Premium User");
    } else {
      ac.setStatus("Registered (free) user");
      is_freeaccount = true;
    }
    ac.setUnlimitedTraffic();
    // now let's get a list of all supported hosts:
    final ArrayList<String> supportedHosts = new ArrayList<String>();

    br.getPage("http://www.premiumax.net/hosts.html");
    /* Apply supported hosts depending on account type */
    for (final String[] filehost : HOSTS) {
      final String crippledHost = filehost[0];
      final String realHost = filehost[1];
      final String hostText =
          br.getRegex("<span>" + crippledHost + "</span>(.*?)</tr>").getMatch(0);
      if (hostText != null) {
        final String[] imgs = new Regex(hostText, "src=\"(tmpl/images/[^<>\"]*?)\"").getColumn(0);
        if (imgs != null
            && imgs.length >= 4
            && imgs[3].equals("tmpl/images/ico_yes.png")
            && (!is_freeaccount && imgs[2].equals("tmpl/images/ico_yes.png")
                || is_freeaccount && imgs[1].equals("tmpl/images/ico_yes.png"))) {
          supportedHosts.add(realHost);
        }
      }
    }
    if (supportedHosts.contains("uploaded.net")
        || supportedHosts.contains("ul.to")
        || supportedHosts.contains("uploaded.to")) {
      if (!supportedHosts.contains("uploaded.net")) {
        supportedHosts.add("uploaded.net");
      }
      if (!supportedHosts.contains("ul.to")) {
        supportedHosts.add("ul.to");
      }
      if (!supportedHosts.contains("uploaded.to")) {
        supportedHosts.add("uploaded.to");
      }
    }
    ac.setProperty("multiHostSupport", supportedHosts);
    return ac;
  }
예제 #25
0
  private void loginAPI(Account account, AccountInfo ai) throws IOException, PluginException {
    synchronized (LOGINLOCK) {
      workAroundTimeOut(br);
      if (ai == null) {
        ai = account.getAccountInfo();
        if (ai == null) {
          ai = new AccountInfo();
          account.setAccountInfo(ai);
        }
      }
      br.getPage("http://www.zevera.com/");
      String res =
          br.getPage(
              "http://www.zevera.com/jDownloader.ashx?cmd=accountinfo&login="******"&pass="******"user.language");
      if ("No trafic".equals(res) || res == null || res.trim().length() == 0) {
        if ("de".equalsIgnoreCase(lang)) {
          throw new PluginException(
              LinkStatus.ERROR_PREMIUM,
              "\r\nUngültiger Benutzername/Passwort oder Traffic aufgebraucht!\r\nSchnellhilfe: \r\nDu bist dir sicher, dass dein eingegebener Benutzername und Passwort stimmen?\r\nFalls dein Passwort Sonderzeichen enthält, ändere es und versuche es erneut!",
              PluginException.VALUE_ID_PREMIUM_DISABLE);
        } else {
          throw new PluginException(
              LinkStatus.ERROR_PREMIUM,
              "\r\nInvalid username/password or no traffic left!\r\nQuick help:\r\nYou're sure that the username and password you entered are correct?\r\nIf your password contains special characters, change it (remove them) and try again!",
              PluginException.VALUE_ID_PREMIUM_DISABLE);
        }
      }
      res = res.trim();
      account.setValid(true);
      if ("Login Error".equalsIgnoreCase(res)) {
        ai.setStatus("Unknown user");
        if ("de".equalsIgnoreCase(lang)) {
          throw new PluginException(
              LinkStatus.ERROR_PREMIUM,
              "\r\nUngültiger Benutzername oder ungültiges Passwort!\r\nSchnellhilfe: \r\nDu bist dir sicher, dass dein eingegebener Benutzername und Passwort stimmen?\r\nFalls dein Passwort Sonderzeichen enthält, ändere es und versuche es erneut!",
              PluginException.VALUE_ID_PREMIUM_DISABLE);
        } else {
          throw new PluginException(
              LinkStatus.ERROR_PREMIUM,
              "\r\nInvalid username/password!\r\nQuick help:\r\nYou're sure that the username and password you entered are correct?\r\nIf your password contains special characters, change it (remove them) and try again!",
              PluginException.VALUE_ID_PREMIUM_DISABLE);
        }
      } else {
        /* normal premium */
        // 0 DayTrafficLimit:5120,
        // 1 EndSubscriptionDate:2012/6/29 0:0:0,
        // 2 TrafficUsedToday:0,
        // 3 AvailableTodayTraffic5120,
        // 4 OronDayTrafficLimit:5120
        ai.setStatus("Premium");
        String infos[] = br.getRegex("(.*?)(,|$)").getColumn(0);
        if (infos == null || infos.length != 6) {
          logger.info(br.toString());
        }
        String EndSubscriptionDate = new Regex(infos[1], "EndSubscriptionDate:(.+)").getMatch(0);
        ai.setValidUntil(
            TimeFormatter.getMilliSeconds(EndSubscriptionDate, "yyyy/MM/dd HH:mm:ss", null));

        /* Traffic balance not working in Zevera JD API */
        // Integer DayTraffic = Integer.parseInt(new
        // Regex(infos[0],"DayTrafficLimit:(.+)").getMatch(0).trim());
        // Integer TrafficUsedToday = Integer.parseInt(new
        // Regex(infos[0],"TrafficUsedToday:(.+)").getMatch(0).trim());
        // Integer Balance = DayTraffic - TrafficUsedToday;
        // ai.setAccountBalance(Balance * 1024);
        String AvailableTodayTraffic =
            new Regex(infos[3], "AvailableTodayTraffic:(\\d+)").getMatch(0);
        logger.info("Zevera: AvailableTodayTraffic=" + AvailableTodayTraffic);
        ai.setTrafficLeft(SizeFormatter.getSize(AvailableTodayTraffic + "mb"));
        if (ai.isExpired()) {
          if ("de".equalsIgnoreCase(lang)) {
            throw new PluginException(
                LinkStatus.ERROR_PREMIUM,
                "\r\nAccount abgelaufen!",
                PluginException.VALUE_ID_PREMIUM_DISABLE);
          } else {
            throw new PluginException(
                LinkStatus.ERROR_PREMIUM,
                "\r\nAccount expired!",
                PluginException.VALUE_ID_PREMIUM_DISABLE);
          }
        }
      }
    }
  }
예제 #26
0
 @Override
 public AccountInfo fetchAccountInfo(Account account) throws Exception {
   AccountInfo ac = new AccountInfo();
   br.setConnectTimeout(60 * 1000);
   br.setReadTimeout(60 * 1000);
   String page = null;
   String hosts = null;
   // check if account is valid
   page =
       br.getPage(
           "http://multidown.co.il/api.php?user="******"&pass="******"&link={stupid_workaround_to_get_pw_ok}");
   String error = "";
   try {
     error = getRegexTag(page, "error").getMatch(0);
   } catch (Exception e) {
     throw new PluginException(
         LinkStatus.ERROR_HOSTER_TEMPORARILY_UNAVAILABLE,
         "server error. Please try later.",
         10 * 60 * 1000l);
   }
   if (!error.equalsIgnoreCase("Host not supported")
       && !error.equalsIgnoreCase("Host not supported or under maintenance")
       && !error.equalsIgnoreCase("\u05e9\u05e8\u05ea \u05dc\u05d0 \u05d6\u05de\u05d9\u05df")) {
     // wrong pass
     account.setValid(false);
     ac.setStatus("account invalid. Wrong password?");
     return ac;
   }
   // account is valid, check if expired:
   page =
       br.getPage(
           "http://multidown.co.il/api.php?user="******"&pass="******"daysleft").getMatch(0));
   } catch (Exception e) {
   }
   account.setValid(true);
   long validuntil = System.currentTimeMillis() + (daysLeft * 1000 * 60 * 60 * 24);
   ac.setValidUntil(validuntil);
   ArrayList<String> supportedHosts = new ArrayList<String>();
   hosts = br.getPage("http://multidown.co.il/api.php?hosts=1");
   if (hosts == null || hosts.isEmpty()) {
     account.setValid(false);
     ac.setStatus("cn not get supported hosters.");
     return ac;
   }
   String hosters[] = new Regex(hosts, "'([^,]*)'").getColumn(0);
   for (String host : hosters) {
     supportedHosts.add(host.trim());
   }
   ac.setStatus("Account valid");
   ac.setMultiHostSupport(this, supportedHosts);
   return ac;
 }
예제 #27
0
 @Override
 public AccountInfo fetchAccountInfo(Account account) throws Exception {
   AccountInfo ai = new AccountInfo();
   /* reset maxPrem workaround on every fetchaccount info */
   maxPrem.set(1);
   try {
     login(account, true);
   } catch (PluginException e) {
     account.setValid(false);
     return ai;
   }
   String space[][] =
       new Regex(
               correctedBR,
               "<td>Used space:</td>.*?<td.*?b>([0-9\\.]+) of [0-9\\.]+ (KB|MB|GB|TB)</b>")
           .getMatches();
   if ((space != null && space.length != 0) && (space[0][0] != null && space[0][1] != null))
     ai.setUsedSpace(space[0][0] + " " + space[0][1]);
   account.setValid(true);
   String availabletraffic =
       new Regex(correctedBR, "Traffic available.*?:</TD><TD><b>([^<>\"\\']+)</b>").getMatch(0);
   if (availabletraffic != null
       && !availabletraffic.contains("nlimited")
       && !availabletraffic.equalsIgnoreCase(" Mb")) {
     ai.setTrafficLeft(SizeFormatter.getSize(availabletraffic));
   } else {
     ai.setUnlimitedTraffic();
   }
   if (account.getBooleanProperty("nopremium")) {
     ai.setStatus("Registered (free) User");
     try {
       maxPrem.set(4);
       // free accounts can still have captcha.
       totalMaxSimultanFreeDownload.set(maxPrem.get());
       account.setMaxSimultanDownloads(4);
       account.setConcurrentUsePossible(false);
     } catch (final Throwable e) {
     }
   } else {
     String expire =
         new Regex(
                 correctedBR,
                 "<td>Premium(\\-| )Account expires?:</td>.*?<td>(<b>)?(\\d{1,2} [A-Za-z]+ \\d{4})(</b>)?</td>")
             .getMatch(2);
     if (expire == null)
       expire = new Regex(correctedBR, "(\\d{1,2} [A-Za-z]+ \\d{4})").getMatch(0);
     if (expire == null) {
       ai.setExpired(true);
       account.setValid(false);
       return ai;
     } else {
       expire = expire.replaceAll("(<b>|</b>)", "");
       ai.setValidUntil(TimeFormatter.getMilliSeconds(expire, "dd MMMM yyyy", null));
       try {
         maxPrem.set(-1);
         account.setMaxSimultanDownloads(-1);
         account.setConcurrentUsePossible(true);
       } catch (final Throwable e) {
       }
     }
     ai.setStatus("Premium User");
   }
   return ai;
 }
예제 #28
0
 @Override
 public AccountInfo fetchAccountInfo(Account account) throws Exception {
   AccountInfo ai = new AccountInfo();
   try {
     login(account, true);
   } catch (PluginException e) {
     account.setValid(false);
     return ai;
   }
   String space =
       br.getRegex(
               Pattern.compile(
                   "<td>Used space:</td>.*?<td.*?b>([0-9\\.]+) of [0-9\\.]+ (Mb|GB)</b>",
                   Pattern.DOTALL | Pattern.CASE_INSENSITIVE))
           .getMatch(0);
   if (space != null) ai.setUsedSpace(space.trim() + " Mb");
   String points =
       br.getRegex(
               Pattern.compile(
                   "<td>You have collected:</td.*?b>([^<>\"\\']+)premium points",
                   Pattern.CASE_INSENSITIVE))
           .getMatch(0);
   if (points != null) {
     /** Who needs half points ? If we have a dot in the points, just remove it */
     if (points.contains(".")) {
       String dot = new Regex(points, ".*?(\\.(\\d+))").getMatch(0);
       points = points.replace(dot, "");
     }
     ai.setPremiumPoints(Long.parseLong(points.trim()));
   }
   account.setValid(true);
   String availabletraffic =
       new Regex(correctedBR, "Traffic available.*?:</TD><TD><b>([^<>\"\\']+)</b>").getMatch(0);
   if (availabletraffic != null
       && !availabletraffic.contains("nlimited")
       && !availabletraffic.equalsIgnoreCase(" Mb")) {
     ai.setTrafficLeft(SizeFormatter.getSize(availabletraffic));
   } else {
     ai.setUnlimitedTraffic();
   }
   if (account.getBooleanProperty("nopremium")) {
     ai.setStatus("Registered (free) User");
   } else {
     String expire =
         new Regex(
                 correctedBR,
                 Pattern.compile(
                     "<td>Premium(\\-| )Account expires?:</td>.*?<td>(<b>)?(\\d{1,2} [A-Za-z]+ \\d{4})(</b>)?</td>",
                     Pattern.CASE_INSENSITIVE))
             .getMatch(2);
     if (expire == null) {
       ai.setExpired(true);
       account.setValid(false);
       return ai;
     } else {
       expire = expire.replaceAll("(<b>|</b>)", "");
       ai.setValidUntil(TimeFormatter.getMilliSeconds(expire, "dd MMMM yyyy", null));
     }
     ai.setStatus("Premium User");
   }
   return ai;
 }
예제 #29
0
 @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 (account.getBooleanProperty("nopremium")) {
     ai.setStatus("Registered (free) User");
     try {
       maxPrem.set(1);
       // 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
     }
   } else {
     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);
     if (expire == null) {
       ai.setExpired(true);
       account.setValid(false);
       return ai;
     } else {
       ai.setValidUntil(TimeFormatter.getMilliSeconds(expire, "dd MMMM yyyy", Locale.ENGLISH));
       try {
         maxPrem.set(20);
         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;
 }
예제 #30
0
  private AccountInfo fetchAccountInfoWebsite(final Account account) {
    final AccountInfo ai = new AccountInfo();
    boolean hours = false;

    if (account.getType() == AccountType.PREMIUM) {
      final String dailyLimitLeft =
          br.getRegex("<li><a href=\"/premium\">([^<>\"\\']+)</a></li>").getMatch(0);
      if (dailyLimitLeft != null) {
        ai.setTrafficMax(SizeFormatter.getSize("20 GB"));
        ai.setTrafficLeft(SizeFormatter.getSize(dailyLimitLeft, true, true));
      } else {
        ai.setUnlimitedTraffic();
      }

      String expire =
          br.getRegex(
                  ">Konto premium ważne do : <strong>(\\d{4}\\-\\d+{2}\\-\\d{2} \\d{2}:\\d{2}:\\d{2})<")
              .getMatch(0);
      if (expire == null) {
        expire = br.getRegex("(\\d{4}\\-\\d+{2}\\-\\d{2} \\d{2}:\\d{2}:\\d{2})").getMatch(0);
        if (expire == null) {
          // for the last day of the premium period
          if (br.containsHTML("Konto premium ważne do : <strong>-</strong></span>")) {
            // 0 days left
            expire =
                br.getRegex(
                        "<a href=\"/premium\">(Konto:[\t\n\r ]+)*Premium \\(<b>(\\d) dni</b>\\)+[ \t\n\r]+</a>")
                    .getMatch(1);
            if (expire == null) {
              expire =
                  br.getRegex(
                          "(Konto:[\r\t\n ]+)+Premium \\(<b><span style=\"color: red\">(\\d+) godzin</span></b>\\)")
                      .getMatch(1);
              hours = true;
            }
          }
          if (expire == null) {
            ai.setExpired(true);
            return ai;
          }
        }
      }
      if (expire.equals("0") && (dailyLimitLeft != null)) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        String dateNow = formatter.format(Calendar.getInstance().getTime());
        dateNow = dateNow + " 23:59:59";
        ai.setValidUntil(
            TimeFormatter.getMilliSeconds(dateNow, "yyyy-MM-dd HH:mm:ss", Locale.ENGLISH));
      } else {
        if (hours) {
          SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
          Calendar cal = Calendar.getInstance();
          cal.setTime(new Date());
          cal.add(Calendar.HOUR_OF_DAY, Integer.parseInt(expire));
          String dateExpire = formatter.format(cal.getTime());

          ai.setValidUntil(
              TimeFormatter.getMilliSeconds(dateExpire, "yyyy-MM-dd HH:mm:ss", Locale.ENGLISH));

        } else {
          ai.setValidUntil(
              TimeFormatter.getMilliSeconds(expire, "yyyy-MM-dd HH:mm:ss", Locale.ENGLISH));
        }
      }
      account.setMaxSimultanDownloads(-1);
      account.setConcurrentUsePossible(true);

      ai.setStatus(getPhrase("PREMIUM"));
    } else {
      account.setMaxSimultanDownloads(1);
      ai.setStatus(getPhrase("FREE"));
    }

    return ai;
  }