private boolean hasSameBareAddress(String account) {
   String bareAddress = Jid.getBareAddress(account);
   for (AccountItem check : accountItems.values())
     if (!check.getAccount().equals(account)
         && Jid.getBareAddress(check.getAccount()).equals(bareAddress)) return true;
   return false;
 }
 /** Creates new account and starts connection. */
 private AccountItem addAccount(
     AccountProtocol protocol,
     boolean custom,
     String host,
     int port,
     String serverName,
     String userName,
     boolean storePassword,
     String password,
     String resource,
     int color,
     int priority,
     StatusMode statusMode,
     String statusText,
     boolean enabled,
     boolean saslEnabled,
     TLSMode tlsMode,
     boolean compression,
     ProxyType proxyType,
     String proxyHost,
     int proxyPort,
     String proxyUser,
     String proxyPassword,
     boolean syncable,
     KeyPair keyPair,
     Date lastSync,
     ArchiveMode archiveMode) {
   AccountItem accountItem =
       new AccountItem(
           protocol,
           custom,
           host,
           port,
           serverName,
           userName,
           resource,
           storePassword,
           password,
           color,
           priority,
           statusMode,
           statusText,
           enabled,
           saslEnabled,
           tlsMode,
           compression,
           proxyType,
           proxyHost,
           proxyPort,
           proxyUser,
           proxyPassword,
           syncable,
           keyPair,
           lastSync,
           archiveMode);
   requestToWriteAccount(accountItem);
   addAccount(accountItem);
   accountItem.updateConnection(true);
   return accountItem;
 }
 private boolean hasSameProtocol(String account) {
   AccountProtocol protocol = getAccount(account).getConnectionSettings().getProtocol();
   for (AccountItem check : accountItems.values())
     if (!check.getAccount().equals(account)
         && check.getConnectionSettings().getProtocol() == protocol) return true;
   return false;
 }
 /** Sends new presence information for all accounts. */
 public void resendPresence() {
   for (AccountItem accountItem : accountItems.values())
     try {
       PresenceManager.getInstance().resendPresence(accountItem.getAccount());
     } catch (NetworkException e) {
     }
 }
  public CommonState getCommonState() {
    boolean disabled = false;
    boolean offline = false;
    boolean waiting = false;
    boolean connecting = false;
    boolean roster = false;
    boolean online = false;

    for (AccountItem accountItem : accountItems.values()) {
      ConnectionState state = accountItem.getState();
      if (state == ConnectionState.connected) online = true;
      if (RosterManager.getInstance().isRosterReceived(accountItem.getAccount())) roster = true;
      if (state == ConnectionState.connecting || state == ConnectionState.authentication)
        connecting = true;
      if (state == ConnectionState.waiting) waiting = true;
      if (accountItem.isEnabled()) offline = true;
      disabled = true;
    }
    if (online) return CommonState.online;
    else if (roster) return CommonState.roster;
    else if (connecting) return CommonState.connecting;
    if (waiting) return CommonState.waiting;
    else if (offline) return CommonState.offline;
    else if (disabled) return CommonState.disabled;
    else return CommonState.empty;
  }
 /**
  * @param account
  * @return Color drawable level or default colors if account was not found.
  */
 public int getColorLevel(String account) {
   AccountItem accountItem = getAccount(account);
   int colorIndex;
   if (accountItem == null) return 0;
   else colorIndex = accountItem.getColorIndex() % colors;
   if (colorIndex < 0) colorIndex += colors;
   return colorIndex;
 }
 /** @return Next color index for the next account. */
 int getNextColorIndex() {
   int[] count = new int[colors];
   for (AccountItem accountItem : accountItems.values())
     count[accountItem.getColorIndex() % colors] += 1;
   int result = 0;
   int value = count[0];
   for (int index = 0; index < count.length; index++) if (count[index] < value) result = index;
   return result;
 }
 /**
  * Sets status for account.
  *
  * @param account
  * @param statusMode
  * @param statusText
  */
 private void setStatus(AccountItem accountItem, StatusMode statusMode, String statusText) {
   boolean changed =
       accountItem.isEnabled()
           && accountItem.getRawStatusMode().isOnline() != statusMode.isOnline();
   accountItem.setStatus(statusMode, statusText);
   if (changed && statusMode.isOnline()) onAccountOnline(accountItem);
   accountItem.updateConnection(true);
   if (changed && !statusMode.isOnline()) onAccountOffline(accountItem);
   requestToWriteAccount(accountItem);
 }
 /**
  * Sets status for all accounts.
  *
  * @param statusMode
  * @param statusText can be <code>null</code> if value was not changed.
  */
 public void setStatus(StatusMode statusMode, String statusText) {
   SettingsManager.setStatusMode(statusMode);
   if (statusText != null) {
     addSavedStatus(statusMode, statusText);
     SettingsManager.setStatusText(statusText);
   }
   for (AccountItem accountItem : accountItems.values()) {
     setStatus(
         accountItem, statusMode, statusText == null ? accountItem.getStatusText() : statusText);
   }
   resendPresence();
   onAccountsChanged(new ArrayList<String>(AccountManager.getInstance().getAllAccounts()));
 }
  /**
   * @param account
   * @return Verbose account name.
   */
  public String getVerboseName(String account) {
    AccountItem accountItem = getAccount(account);
    if (accountItem == null) return account;
    if (accountItem.getConnectionSettings().getProtocol().isOAuth()) {
      String jid = OAuthManager.getInstance().getAssignedJid(account);
      AccountProtocol accountProtocol = accountItem.getConnectionSettings().getProtocol();
      String name;
      if (jid == null) {
        if (hasSameProtocol(account)) name = accountItem.getConnectionSettings().getUserName();
        else return application.getString(accountProtocol.getNameResource());

      } else {
        name = Jid.getBareAddress(jid);
        if (!hasSameBareAddress(jid)) return name;
      }
      return application.getString(accountProtocol.getShortResource()) + " - " + name;
    } else {
      if (hasSameBareAddress(account)) return account;
      else return Jid.getBareAddress(account);
    }
  }
 /**
  * Remove user`s account. Don't call any callbacks.
  *
  * @param account
  */
 private void removeAccountWithoutCallback(final String account) {
   final AccountItem accountItem = getAccount(account);
   boolean wasEnabled = accountItem.isEnabled();
   accountItem.setEnabled(false);
   accountItem.updateConnection(true);
   if (wasEnabled) {
     if (accountItem.getRawStatusMode().isOnline()) onAccountOffline(accountItem);
     onAccountDisabled(accountItem);
   }
   Application.getInstance()
       .runInBackground(
           new Runnable() {
             @Override
             public void run() {
               AccountTable.getInstance().remove(account, accountItem.getId());
             }
           });
   accountItems.remove(account);
   enabledAccounts.remove(account);
   for (OnAccountRemovedListener listener :
       application.getManagers(OnAccountRemovedListener.class))
     listener.onAccountRemoved(accountItem);
   removeAuthorizationError(account);
 }
 private void addAccount(AccountItem accountItem) {
   accountItems.put(accountItem.getAccount(), accountItem);
   if (accountItem.isEnabled()) enabledAccounts.add(accountItem.getAccount());
   for (OnAccountAddedListener listener : application.getManagers(OnAccountAddedListener.class))
     listener.onAccountAdded(accountItem);
   if (accountItem.isEnabled()) {
     onAccountEnabled(accountItem);
     if (accountItem.getRawStatusMode().isOnline()) onAccountOnline(accountItem);
   }
   onAccountChanged(accountItem.getAccount());
 }
 /**
  * Sets status for account.
  *
  * @param account
  * @param statusMode
  * @param statusText
  */
 public void setStatus(String account, StatusMode statusMode, String statusText) {
   addSavedStatus(statusMode, statusText);
   AccountItem accountItem = getAccount(account);
   setStatus(accountItem, statusMode, statusText);
   try {
     PresenceManager.getInstance().resendPresence(account);
   } catch (NetworkException e) {
   }
   boolean found = false;
   for (AccountItem check : accountItems.values())
     if (check.isEnabled() && SettingsManager.statusMode() == check.getRawStatusMode()) {
       found = true;
       break;
     }
   if (!found) SettingsManager.setStatusMode(statusMode);
   found = false;
   for (AccountItem check : accountItems.values())
     if (check.isEnabled() && SettingsManager.statusText().equals(check.getStatusText())) {
       found = true;
       break;
     }
   if (!found) SettingsManager.setStatusText(statusText);
   onAccountChanged(account);
 }
 public void setLastSync(String account, Date lastSync) {
   AccountItem accountItem = getAccount(account);
   accountItem.setLastSync(lastSync);
   requestToWriteAccount(accountItem);
 }
  @Override
  public void onLoad() {
    final Collection<SavedStatus> savedStatuses = new ArrayList<SavedStatus>();
    final Collection<AccountItem> accountItems = new ArrayList<AccountItem>();
    Cursor cursor = StatusTable.getInstance().list();
    try {
      if (cursor.moveToFirst()) {
        do {
          savedStatuses.add(
              new SavedStatus(
                  StatusTable.getStatusMode(cursor), StatusTable.getStatusText(cursor)));
        } while (cursor.moveToNext());
      }
    } finally {
      cursor.close();
    }

    cursor = AccountTable.getInstance().list();
    try {
      if (cursor.moveToFirst()) {
        do {
          AccountItem accountItem =
              new AccountItem(
                  AccountTable.getProtocol(cursor),
                  AccountTable.isCustom(cursor),
                  AccountTable.getHost(cursor),
                  AccountTable.getPort(cursor),
                  AccountTable.getServerName(cursor),
                  AccountTable.getUserName(cursor),
                  AccountTable.getResource(cursor),
                  AccountTable.isStorePassword(cursor),
                  AccountTable.getPassword(cursor),
                  AccountTable.getColorIndex(cursor),
                  AccountTable.getPriority(cursor),
                  AccountTable.getStatusMode(cursor),
                  AccountTable.getStatusText(cursor),
                  AccountTable.isEnabled(cursor),
                  AccountTable.isSaslEnabled(cursor),
                  AccountTable.getTLSMode(cursor),
                  AccountTable.isCompression(cursor),
                  AccountTable.getProxyType(cursor),
                  AccountTable.getProxyHost(cursor),
                  AccountTable.getProxyPort(cursor),
                  AccountTable.getProxyUser(cursor),
                  AccountTable.getProxyPassword(cursor),
                  AccountTable.isSyncable(cursor),
                  AccountTable.getKeyPair(cursor),
                  AccountTable.getLastSync(cursor),
                  AccountTable.getArchiveMode(cursor));
          accountItem.setId(AccountTable.getId(cursor));
          accountItems.add(accountItem);
        } while (cursor.moveToNext());
      }
    } finally {
      cursor.close();
    }

    Application.getInstance()
        .runOnUiThread(
            new Runnable() {
              @Override
              public void run() {
                onLoaded(savedStatuses, accountItems);
              }
            });
  }
 /**
  * Save account item to database.
  *
  * @param accountItem
  */
 void requestToWriteAccount(final AccountItem accountItem) {
   final AccountProtocol protocol = accountItem.getConnectionSettings().getProtocol();
   final boolean custom = accountItem.getConnectionSettings().isCustom();
   final String host = accountItem.getConnectionSettings().getHost();
   final int port = accountItem.getConnectionSettings().getPort();
   final String serverName = accountItem.getConnectionSettings().getServerName();
   final String userName = accountItem.getConnectionSettings().getUserName();
   final String resource = accountItem.getConnectionSettings().getResource();
   final boolean storePassword = accountItem.isStorePassword();
   final String password = accountItem.getConnectionSettings().getPassword();
   final int colorIndex = accountItem.getColorIndex();
   final int priority = accountItem.getPriority();
   final StatusMode statusMode = accountItem.getRawStatusMode();
   final String statusText = accountItem.getStatusText();
   final boolean enabled = accountItem.isEnabled();
   final boolean saslEnabled = accountItem.getConnectionSettings().isSaslEnabled();
   final TLSMode tlsMode = accountItem.getConnectionSettings().getTlsMode();
   final boolean compression = accountItem.getConnectionSettings().useCompression();
   final ProxyType proxyType = accountItem.getConnectionSettings().getProxyType();
   final String proxyHost = accountItem.getConnectionSettings().getProxyHost();
   final int proxyPort = accountItem.getConnectionSettings().getProxyPort();
   final String proxyUser = accountItem.getConnectionSettings().getProxyUser();
   final String proxyPassword = accountItem.getConnectionSettings().getProxyPassword();
   final boolean syncable = accountItem.isSyncable();
   final KeyPair keyPair = accountItem.getKeyPair();
   final Date lastSync = accountItem.getLastSync();
   final ArchiveMode archiveMode = accountItem.getArchiveMode();
   Application.getInstance()
       .runInBackground(
           new Runnable() {
             @Override
             public void run() {
               accountItem.setId(
                   AccountTable.getInstance()
                       .write(
                           accountItem.getId(),
                           protocol,
                           custom,
                           host,
                           port,
                           serverName,
                           userName,
                           resource,
                           storePassword,
                           password,
                           colorIndex,
                           priority,
                           statusMode,
                           statusText,
                           enabled,
                           saslEnabled,
                           tlsMode,
                           compression,
                           proxyType,
                           proxyHost,
                           proxyPort,
                           proxyUser,
                           proxyPassword,
                           syncable,
                           keyPair,
                           lastSync,
                           archiveMode));
             }
           });
 }
  /**
   * Creates new account.
   *
   * @param user full or bare jid.
   * @param password
   * @param accountType xmpp account type can be replaced depend on server part.
   * @param syncable
   * @param storePassword
   * @param useOrbot
   * @return assigned account name.
   * @throws NetworkException if user or server part are invalid.
   */
  public String addAccount(
      String user,
      String password,
      AccountType accountType,
      boolean syncable,
      boolean storePassword,
      boolean useOrbot)
      throws NetworkException {
    if (accountType.getProtocol().isOAuth()) {
      int index = 1;
      while (true) {
        user = String.valueOf(index);
        boolean found = false;
        for (AccountItem accountItem : accountItems.values())
          if (accountItem
                  .getConnectionSettings()
                  .getServerName()
                  .equals(accountType.getFirstServer())
              && accountItem.getConnectionSettings().getUserName().equals(user)) {
            found = true;
            break;
          }
        if (!found) break;
        index++;
      }
    }

    if (user == null) throw new NetworkException(R.string.EMPTY_USER_NAME);

    if (user.indexOf("@") == -1) {
      if ("".equals(accountType.getFirstServer()))
        throw new NetworkException(R.string.EMPTY_SERVER_NAME);
      else user += "@" + accountType.getFirstServer();
    }

    String serverName = StringUtils.parseServer(user);
    String userName = StringUtils.parseName(user);
    String resource = StringUtils.parseResource(user);
    String host = accountType.getHost();
    int port = accountType.getPort();
    boolean tlsRequired = accountType.isTLSRequired();
    if (useOrbot) tlsRequired = true;

    if ("".equals(serverName)) {
      throw new NetworkException(R.string.EMPTY_SERVER_NAME);
    } else if (!accountType.isAllowServer() && !serverName.equals(accountType.getFirstServer()))
      throw new NetworkException(R.string.INCORRECT_USER_NAME);

    if ("".equals(userName)) throw new NetworkException(R.string.EMPTY_USER_NAME);
    if ("".equals(resource)) resource = "android" + StringUtils.randomString(8);

    if (accountType.getId() == R.array.account_type_xmpp) {
      host = serverName;
      for (AccountType check : accountTypes)
        if (check.getServers().contains(serverName)) {
          accountType = check;
          host = check.getHost();
          port = check.getPort();
          tlsRequired = check.isTLSRequired();
          break;
        }
    }

    AccountItem accountItem;
    for (; ; ) {
      if (getAccount(userName + '@' + serverName + '/' + resource) == null) break;
      resource = "android" + StringUtils.randomString(8);
    }

    accountItem =
        addAccount(
            accountType.getProtocol(),
            true,
            host,
            port,
            serverName,
            userName,
            storePassword,
            password,
            resource,
            getNextColorIndex(),
            0,
            StatusMode.available,
            SettingsManager.statusText(),
            true,
            true,
            tlsRequired ? TLSMode.required : TLSMode.enabled,
            false,
            useOrbot ? ProxyType.orbot : ProxyType.none,
            "localhost",
            8080,
            "",
            "",
            syncable,
            null,
            null,
            ArchiveMode.available);
    onAccountChanged(accountItem.getAccount());
    if (accountItems.size() > 1 && SettingsManager.contactsEnableShowAccounts())
      SettingsManager.enableContactsShowAccount();
    return accountItem.getAccount();
  }
 public ArchiveMode getArchiveMode(String account) {
   AccountItem accountItem = getAccount(account);
   if (accountItem == null) return ArchiveMode.available;
   return accountItem.getArchiveMode();
 }
 public void setArchiveMode(String account, ArchiveMode archiveMode) {
   AccountItem accountItem = AccountManager.getInstance().getAccount(account);
   AccountManager.getInstance()
       .updateAccount(
           account,
           accountItem.getConnectionSettings().isCustom(),
           accountItem.getConnectionSettings().getHost(),
           accountItem.getConnectionSettings().getPort(),
           accountItem.getConnectionSettings().getServerName(),
           accountItem.getConnectionSettings().getUserName(),
           accountItem.isStorePassword(),
           accountItem.getConnectionSettings().getPassword(),
           accountItem.getConnectionSettings().getResource(),
           accountItem.getPriority(),
           accountItem.isEnabled(),
           accountItem.getConnectionSettings().isSaslEnabled(),
           accountItem.getConnectionSettings().getTlsMode(),
           accountItem.getConnectionSettings().useCompression(),
           accountItem.getConnectionSettings().getProxyType(),
           accountItem.getConnectionSettings().getProxyHost(),
           accountItem.getConnectionSettings().getProxyPort(),
           accountItem.getConnectionSettings().getProxyUser(),
           accountItem.getConnectionSettings().getProxyPassword(),
           accountItem.isSyncable(),
           archiveMode);
 }
 public void setPassword(String account, boolean storePassword, String password) {
   AccountItem accountItem = getAccount(account);
   updateAccount(
       account,
       accountItem.getConnectionSettings().isCustom(),
       accountItem.getConnectionSettings().getHost(),
       accountItem.getConnectionSettings().getPort(),
       accountItem.getConnectionSettings().getServerName(),
       accountItem.getConnectionSettings().getUserName(),
       storePassword,
       password,
       accountItem.getConnectionSettings().getResource(),
       accountItem.getPriority(),
       accountItem.isEnabled(),
       accountItem.getConnectionSettings().isSaslEnabled(),
       accountItem.getConnectionSettings().getTlsMode(),
       accountItem.getConnectionSettings().useCompression(),
       accountItem.getConnectionSettings().getProxyType(),
       accountItem.getConnectionSettings().getProxyHost(),
       accountItem.getConnectionSettings().getProxyPort(),
       accountItem.getConnectionSettings().getProxyUser(),
       accountItem.getConnectionSettings().getProxyPassword(),
       accountItem.isSyncable(),
       accountItem.getArchiveMode());
 }
 public void onAccountOffline(AccountItem accountItem) {
   accountItem.clearPassword();
   for (OnAccountOfflineListener listener :
       application.getManagers(OnAccountOfflineListener.class))
     listener.onAccountOffline(accountItem);
 }
 public void setKeyPair(String account, KeyPair keyPair) {
   AccountItem accountItem = getAccount(account);
   accountItem.setKeyPair(keyPair);
   requestToWriteAccount(accountItem);
 }
 /**
  * Update user`s account.
  *
  * <p>It will reconnect to the server if changes was made.
  *
  * <p>It will remove old account and create new one if full jid was changed.
  *
  * @param account full source jid
  * @param host
  * @param port
  * @param serverName
  * @param userName
  * @param storePassword
  * @param password
  * @param resource
  * @param priority
  * @param enabled
  * @param saslEnabled
  * @param tlsMode
  * @param compression
  * @param syncable
  * @param archiveMode
  */
 public void updateAccount(
     String account,
     boolean custom,
     String host,
     int port,
     String serverName,
     String userName,
     boolean storePassword,
     String password,
     String resource,
     int priority,
     boolean enabled,
     boolean saslEnabled,
     TLSMode tlsMode,
     boolean compression,
     ProxyType proxyType,
     String proxyHost,
     int proxyPort,
     String proxyUser,
     String proxyPassword,
     boolean syncable,
     ArchiveMode archiveMode) {
   AccountItem result;
   AccountItem accountItem = getAccount(account);
   if (accountItem.getConnectionSettings().getServerName().equals(serverName)
       && accountItem.getConnectionSettings().getUserName().equals(userName)
       && accountItem.getConnectionSettings().getResource().equals(resource)) {
     result = accountItem;
     boolean reconnect = false;
     if (accountItem.getConnectionSettings().isCustom() != custom
         || !accountItem.getConnectionSettings().getHost().equals(host)
         || accountItem.getConnectionSettings().getPort() != port
         || !accountItem.getConnectionSettings().getPassword().equals(password)
         || accountItem.getConnectionSettings().getTlsMode() != tlsMode
         || accountItem.getConnectionSettings().isSaslEnabled() != saslEnabled
         || accountItem.getConnectionSettings().useCompression() != compression
         || accountItem.getConnectionSettings().getProxyType() != proxyType
         || !accountItem.getConnectionSettings().getProxyHost().equals(proxyHost)
         || accountItem.getConnectionSettings().getProxyPort() != proxyPort
         || !accountItem.getConnectionSettings().getProxyUser().equals(proxyUser)
         || !accountItem.getConnectionSettings().getProxyPassword().equals(proxyPassword)) {
       result.updateConnectionSettings(
           custom,
           host,
           port,
           password,
           saslEnabled,
           tlsMode,
           compression,
           proxyType,
           proxyHost,
           proxyPort,
           proxyUser,
           proxyPassword);
       reconnect = true;
     }
     if (result.isSyncable() != syncable) {
       result.setSyncable(syncable);
       for (OnAccountSyncableChangedListener listener :
           application.getManagers(OnAccountSyncableChangedListener.class))
         listener.onAccountSyncableChanged(result);
     }
     result.setStorePassword(storePassword);
     boolean changed = result.isEnabled() != enabled;
     result.setEnabled(enabled);
     if (result.getPriority() != priority) {
       result.setPriority(priority);
       try {
         PresenceManager.getInstance().resendPresence(account);
       } catch (NetworkException e) {
       }
     }
     if (result.getArchiveMode() != archiveMode) {
       reconnect =
           (result.getArchiveMode() == ArchiveMode.server) != (archiveMode == ArchiveMode.server);
       result.setArchiveMode(archiveMode);
       for (OnAccountArchiveModeChangedListener listener :
           application.getManagers(OnAccountArchiveModeChangedListener.class))
         listener.onAccountArchiveModeChanged(result);
     }
     if (changed && enabled) {
       enabledAccounts.add(account);
       onAccountEnabled(result);
       if (result.getRawStatusMode().isOnline()) onAccountOnline(result);
     }
     if (changed || reconnect) {
       result.updateConnection(true);
       result.forceReconnect();
     }
     if (changed && !enabled) {
       enabledAccounts.remove(account);
       if (result.getRawStatusMode().isOnline()) onAccountOffline(result);
       onAccountDisabled(result);
     }
     requestToWriteAccount(result);
   } else {
     int colorIndex = accountItem.getColorIndex();
     StatusMode statusMode = accountItem.getRawStatusMode();
     String statusText = accountItem.getStatusText();
     AccountProtocol protocol = accountItem.getConnectionSettings().getProtocol();
     KeyPair keyPair = accountItem.getKeyPair();
     Date lastSync = accountItem.getLastSync();
     removeAccountWithoutCallback(account);
     result =
         addAccount(
             protocol,
             custom,
             host,
             port,
             serverName,
             userName,
             storePassword,
             password,
             resource,
             colorIndex,
             priority,
             statusMode,
             statusText,
             enabled,
             saslEnabled,
             tlsMode,
             compression,
             proxyType,
             proxyHost,
             proxyPort,
             proxyUser,
             proxyPassword,
             syncable,
             keyPair,
             lastSync,
             archiveMode);
   }
   onAccountChanged(result.getAccount());
 }