Beispiel #1
0
  public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);

    Element a = request.getElement(AdminConstants.E_ACCOUNT);
    String key = a.getAttribute(AdminConstants.A_BY);
    String value = a.getText();

    long lifetime =
        request.getAttributeLong(AdminConstants.A_DURATION, DEFAULT_AUTH_LIFETIME) * 1000;

    Provisioning prov = Provisioning.getInstance();

    Account account = null;

    if (key.equals(BY_NAME)) {
      account = prov.get(AccountBy.name, value, zsc.getAuthToken());
    } else if (key.equals(BY_ID)) {
      account = prov.get(AccountBy.id, value, zsc.getAuthToken());
    } else {
      throw ServiceException.INVALID_REQUEST("unknown value for by: " + key, null);
    }

    if (account == null) throw AccountServiceException.NO_SUCH_ACCOUNT(value);

    checkAdminLoginAsRight(zsc, prov, account);

    ZimbraLog.security.info(
        ZimbraLog.encodeAttrs(
            new String[] {
              "cmd", "DelegateAuth", "accountId", account.getId(), "accountName", account.getName()
            }));

    Element response = zsc.createElement(AdminConstants.DELEGATE_AUTH_RESPONSE);
    long maxLifetime =
        account.getTimeInterval(
            Provisioning.A_zimbraAuthTokenLifetime, DEFAULT_AUTH_LIFETIME * 1000);

    // take the min of requested lifetime vs maxLifetime
    long expires = System.currentTimeMillis() + Math.min(lifetime, maxLifetime);
    String token;
    Account adminAcct = prov.get(AccountBy.id, zsc.getAuthtokenAccountId(), zsc.getAuthToken());
    if (adminAcct == null)
      throw AccountServiceException.NO_SUCH_ACCOUNT(zsc.getAuthtokenAccountId());

    AuthToken at = AuthProvider.getAuthToken(account, expires, false, adminAcct);
    at.encodeAuthResp(response, true);
    response.addAttribute(AdminConstants.E_LIFETIME, lifetime, Element.Disposition.CONTENT);
    return response;
  }
Beispiel #2
0
  /* (non-Javadoc)
   * @see com.zimbra.soap.DocumentHandler#handle(org.dom4j.Element, java.util.Map)
   */
  public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);

    Element a = request.getElement(AdminConstants.E_ACCOUNT);
    String key = a.getAttribute(AdminConstants.A_BY);
    String value = a.getText();

    Provisioning prov = Provisioning.getInstance();
    Account account = prov.get(AccountBy.fromString(key), value, zsc.getAuthToken());

    if (account == null) throw AccountServiceException.NO_SUCH_ACCOUNT(value);

    if (account.isCalendarResource()) {
      // need a CalendarResource instance for RightChecker
      CalendarResource resource = prov.get(CalendarResourceBy.id, account.getId());
      checkCalendarResourceRight(zsc, resource, Admin.R_getCalendarResourceInfo);
    } else checkAccountRight(zsc, account, Admin.R_getAccountInfo);

    Element response = zsc.createElement(AdminConstants.GET_ACCOUNT_INFO_RESPONSE);
    response.addElement(AdminConstants.E_NAME).setText(account.getName());
    addAttr(response, Provisioning.A_zimbraId, account.getId());
    addAttr(
        response, Provisioning.A_zimbraMailHost, account.getAttr(Provisioning.A_zimbraMailHost));

    doCos(account, response);
    addUrls(response, account);

    return response;
  }
  @Override
  public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);

    Element mreq = request.getElement(AdminConstants.E_MAILBOX);
    String accountId = mreq.getAttribute(AdminConstants.A_ACCOUNTID);

    Provisioning prov = Provisioning.getInstance();
    Account account = prov.get(AccountBy.id, accountId, zsc.getAuthToken());
    if (account == null) {
      throw AccountServiceException.NO_SUCH_ACCOUNT(accountId);
    }
    checkAdminLoginAsRight(zsc, prov, account);

    Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(account, false);
    if (mbox == null) {
      throw MailServiceException.NO_SUCH_MBOX(accountId);
    }

    mbox.recalculateFolderAndTagCounts();

    Element response = zsc.createElement(AdminConstants.RECALCULATE_MAILBOX_COUNTS_RESPONSE);
    response
        .addElement(AdminConstants.E_MAILBOX)
        .addAttribute(AdminConstants.A_ACCOUNTID, accountId)
        .addAttribute(AdminConstants.A_QUOTA_USED, mbox.getSize());
    return response;
  }
Beispiel #4
0
  public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    Account account = getRequestedAccount(zsc);

    if (!canModifyOptions(zsc, account))
      throw ServiceException.PERM_DENIED("can not modify options");

    HashMap<String, Object> prefs = new HashMap<String, Object>();
    Map<String, Set<String>> name2uniqueAttrValues = new HashMap<String, Set<String>>();
    for (KeyValuePair kvp :
        request.listKeyValuePairs(AccountConstants.E_PREF, AccountConstants.A_NAME)) {
      String name = kvp.getKey(), value = kvp.getValue();
      char ch = name.length() > 0 ? name.charAt(0) : 0;
      int offset = ch == '+' || ch == '-' ? 1 : 0;
      if (!name.startsWith(PREF_PREFIX, offset))
        throw ServiceException.INVALID_REQUEST("pref name must start with " + PREF_PREFIX, null);

      AttributeInfo attrInfo =
          AttributeManager.getInstance().getAttributeInfo(name.substring(offset));
      if (attrInfo == null) {
        throw ServiceException.INVALID_REQUEST("no such attribute: " + name, null);
      }
      if (attrInfo.isCaseInsensitive()) {
        String valueLowerCase = Strings.nullToEmpty(value).toLowerCase();
        if (name2uniqueAttrValues.get(name) == null) {
          Set<String> set = new HashSet<String>();
          set.add(valueLowerCase);
          name2uniqueAttrValues.put(name, set);
          StringUtil.addToMultiMap(prefs, name, value);
        } else {
          Set<String> set = name2uniqueAttrValues.get(name);
          if (set.add(valueLowerCase)) {
            StringUtil.addToMultiMap(prefs, name, value);
          }
        }
      } else {
        StringUtil.addToMultiMap(prefs, name, value);
      }
    }

    if (prefs.containsKey(Provisioning.A_zimbraPrefMailForwardingAddress)) {
      if (!account.getBooleanAttr(Provisioning.A_zimbraFeatureMailForwardingEnabled, false))
        throw ServiceException.PERM_DENIED("forwarding not enabled");
    }

    // call modifyAttrs and pass true to checkImmutable
    Provisioning.getInstance().modifyAttrs(account, prefs, true, zsc.getAuthToken());

    Element response = zsc.createElement(AccountConstants.MODIFY_PREFS_RESPONSE);
    return response;
  }
  @Override
  public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);

    Element mreq = request.getElement(AdminConstants.E_MAILBOX);
    String accountId = mreq.getAttribute(AdminConstants.A_ACCOUNTID);

    Account account = Provisioning.getInstance().get(AccountBy.id, accountId, zsc.getAuthToken());
    if (account == null) {
      // Note: isDomainAdminOnly *always* returns false for pure ACL based AccessManager
      if (isDomainAdminOnly(zsc)) {
        throw ServiceException.PERM_DENIED(
            "account doesn't exist, unable to determine authorization");
      }

      // still need to check right, since we don't have an account, the
      // last resort is checking the global grant.  Do this for now until
      // there is complain.
      checkRight(zsc, context, null, Admin.R_deleteAccount);

      ZimbraLog.account.warn(
          "DeleteMailbox: account doesn't exist: " + accountId + " (still deleting mailbox)");

    } else {
      checkAccountRight(zsc, account, Admin.R_deleteAccount);
    }

    Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(accountId, false);
    int mailboxId = -1;
    if (mbox != null) {
      mailboxId = mbox.getId();
      mbox.deleteMailbox();
    }

    String idString =
        (mbox == null) ? "<no mailbox for account " + accountId + ">" : Integer.toString(mailboxId);
    ZimbraLog.security.info(
        ZimbraLog.encodeAttrs(new String[] {"cmd", "DeleteMailbox", "id", idString}));

    Element response = zsc.createElement(AdminConstants.DELETE_MAILBOX_RESPONSE);
    if (mbox != null)
      response
          .addElement(AdminConstants.E_MAILBOX)
          .addAttribute(AdminConstants.A_MAILBOXID, mailboxId);
    return response;
  }
Beispiel #6
0
  private static void searchRemoteAccountCalendars(
      Element parent,
      SearchParams params,
      ZimbraSoapContext zsc,
      Account authAcct,
      Map<String, List<Integer>> accountFolders)
      throws ServiceException {
    String nominalTargetAcctId = null; // mail service soap requests want to see a target account
    StringBuilder queryStr = new StringBuilder();
    for (Map.Entry<String, List<Integer>> entry : accountFolders.entrySet()) {
      String acctId = entry.getKey();
      if (nominalTargetAcctId == null) nominalTargetAcctId = acctId;
      ItemIdFormatter ifmt = new ItemIdFormatter(authAcct.getId(), acctId, false);
      List<Integer> folderIds = entry.getValue();
      for (int folderId : folderIds) {
        if (queryStr.length() > 0) queryStr.append(" OR ");
        // must quote the qualified folder id
        queryStr.append("inid:\"").append(ifmt.formatItemId(folderId)).append("\"");
      }
    }
    Element req = zsc.createElement(MailConstants.SEARCH_REQUEST);
    req.addAttribute(MailConstants.A_SEARCH_TYPES, MailItem.Type.toString(params.getTypes()));
    if (params.getSortBy() != null) {
      req.addAttribute(MailConstants.A_SORTBY, params.getSortBy().toString());
    }
    req.addAttribute(MailConstants.A_QUERY_OFFSET, params.getOffset());
    if (params.getLimit() != 0) req.addAttribute(MailConstants.A_QUERY_LIMIT, params.getLimit());
    req.addAttribute(MailConstants.A_CAL_EXPAND_INST_START, params.getCalItemExpandStart());
    req.addAttribute(MailConstants.A_CAL_EXPAND_INST_END, params.getCalItemExpandEnd());
    req.addAttribute(MailConstants.E_QUERY, queryStr.toString(), Element.Disposition.CONTENT);

    Account target = Provisioning.getInstance().get(Key.AccountBy.id, nominalTargetAcctId);
    String pxyAuthToken = zsc.getAuthToken().getProxyAuthToken();
    ZAuthToken zat = pxyAuthToken == null ? zsc.getRawAuthToken() : new ZAuthToken(pxyAuthToken);
    ZMailbox.Options zoptions = new ZMailbox.Options(zat, AccountUtil.getSoapUri(target));
    zoptions.setTargetAccount(nominalTargetAcctId);
    zoptions.setTargetAccountBy(AccountBy.id);
    zoptions.setNoSession(true);
    ZMailbox zmbx = ZMailbox.getMailbox(zoptions);

    Element resp = zmbx.invoke(req);
    for (Element hit : resp.listElements()) {
      hit.detach();
      parent.addElement(hit);
    }
  }
  private void deploy(
      ZimbraSoapContext lc, String aid, ZAuthToken auth, boolean flushCache, boolean synchronous)
      throws ServiceException {
    Upload up = FileUploadServlet.fetchUpload(lc.getAuthtokenAccountId(), aid, lc.getAuthToken());
    if (up == null) throw MailServiceException.NO_SUCH_UPLOAD(aid);

    Progress pr = new Progress((auth != null));
    mProgressMap.put(aid, pr);
    Runnable action = new DeployThread(up, pr, auth, flushCache);
    Thread t = new Thread(action);
    t.start();
    if (synchronous) {
      try {
        t.join(DEPLOY_TIMEOUT);
      } catch (InterruptedException e) {
        ZimbraLog.zimlet.warn("error while deploying Zimlet", e);
      }
    }
  }
  @Override
  protected Element proxyIfNecessary(Element request, Map<String, Object> context)
      throws ServiceException {
    // if we've explicitly been told to execute here, don't proxy
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    if (zsc.getProxyTarget() != null) return null;

    // check whether we need to proxy to the home server of a target account
    Provisioning prov = Provisioning.getInstance();
    String[] xpath = getProxiedAccountPath();
    String acctId = (xpath != null ? getXPath(request, xpath) : null);
    if (acctId != null) {
      Account acct = getAccount(prov, AccountBy.id, acctId, zsc.getAuthToken());
      if (acct != null && !Provisioning.onLocalServer(acct))
        return proxyRequest(request, context, acctId);
    }

    return null;
  }
Beispiel #9
0
 public AuthToken getAuthToken() {
   if (mSoapContext == null) return null;
   else return mSoapContext.getAuthToken();
 }
Beispiel #10
0
  @Override
  public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    if (true) throw WikiServiceException.ERROR("Deprecated");
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    OperationContext octxt = getOperationContext(zsc, context);

    Element msgElem = request.getElement(MailConstants.E_WIKIWORD);
    String subject = msgElem.getAttribute(MailConstants.A_NAME, null);
    String id = msgElem.getAttribute(MailConstants.A_ID, null);
    int ver = (int) msgElem.getAttributeLong(MailConstants.A_VERSION, 0);
    int itemId;
    if (id == null) {
      itemId = 0;
    } else {
      ItemId iid = new ItemId(id, zsc);
      itemId = iid.getId();
    }

    ItemId fid = getRequestedFolder(request, zsc);
    ByteArrayInputStream is = null;
    try {
      byte[] rawData = msgElem.getText().getBytes("UTF-8");
      is = new ByteArrayInputStream(rawData);
    } catch (IOException ioe) {
      throw ServiceException.FAILURE("can't get the content", ioe);
    }
    Mailbox mbox = MailboxManager.getInstance().getMailboxByAccountId(zsc.getRequestedAccountId());
    Document wikiItem = null;
    WikiPage.WikiContext ctxt = new WikiPage.WikiContext(octxt, zsc.getAuthToken());
    if (itemId == 0) {
      // create a new page
      wikiItem =
          mbox.createDocument(
              octxt,
              fid.getId(),
              subject,
              WikiItem.WIKI_CONTENT_TYPE,
              getAuthor(zsc),
              null,
              true,
              is,
              MailItem.TYPE_WIKI);
    } else {
      // add a new revision
      WikiPage oldPage = WikiPage.findPage(ctxt, zsc.getRequestedAccountId(), itemId);
      if (oldPage == null)
        throw new WikiServiceException.NoSuchWikiException("page id=" + id + " not found");
      if (oldPage.getLastVersion() != ver) {
        throw MailServiceException.MODIFY_CONFLICT(
            new Argument(MailConstants.A_NAME, subject, Argument.Type.STR),
            new Argument(MailConstants.A_ID, oldPage.getId(), Argument.Type.IID),
            new Argument(MailConstants.A_VERSION, oldPage.getLastVersion(), Argument.Type.NUM));
      }
      wikiItem = mbox.addDocumentRevision(octxt, itemId, getAuthor(zsc), subject, null, true, is);
    }

    Element response = zsc.createElement(MailConstants.SAVE_WIKI_RESPONSE);
    Element m = response.addElement(MailConstants.E_WIKIWORD);
    m.addAttribute(MailConstants.A_ID, new ItemIdFormatter(zsc).formatItemId(wikiItem));
    m.addAttribute(MailConstants.A_VERSION, wikiItem.getVersion());
    return response;
  }
  public Element handle(Element request, Map<String, Object> context) throws ServiceException {
    ZimbraSoapContext zsc = getZimbraSoapContext(context);
    Server localServer = Provisioning.getInstance().getLocalServer();
    checkRight(zsc, context, localServer, Admin.R_createMigrationTask);
    String op = request.getAttribute(AdminExtConstants.A_op);
    Element response = zsc.createElement(AdminExtConstants.BULK_IMAP_DATA_IMPORT_RESPONSE);
    Map<accountState, List<ExternalIMAPAccount>> IMAPAccounts = null;
    String IMAPhost = null,
        IMAPport = null,
        adminLogin = null,
        adminPassword = null,
        connectionType = null,
        sourceServerType = null;
    String sourceType = request.getElement(AdminExtConstants.A_sourceType).getTextTrim();
    String indexBatchSize = ZimbraBulkProvisionExt.DEFAULT_INDEX_BATCH_SIZE;
    boolean useAdminLogin = false;
    if (sourceType.equalsIgnoreCase(AdminFileDownload.FILE_FORMAT_BULK_XML)) {
      String aid = request.getElement(AdminExtConstants.E_attachmentID).getTextTrim();
      ZimbraLog.extensions.debug("Uploaded XML file id = " + aid);
      FileUploadServlet.Upload up =
          FileUploadServlet.fetchUpload(zsc.getAuthtokenAccountId(), aid, zsc.getAuthToken());
      if (up == null) {
        throw ServiceException.FAILURE(
            "Uploaded XML file with id " + aid + " was not found.", null);
      }

      try {
        SAXReader reader = new SAXReader();
        Document doc = reader.read(up.getInputStream());
        org.dom4j.Element root = doc.getRootElement();

        if (!root.getName().equals(AdminExtConstants.E_ZCSImport)) {
          throw new DocumentException(
              "Bulk provisioning XML file's root element must be " + AdminExtConstants.E_ZCSImport);
        }
        Iterator rootIter = root.elementIterator(AdminExtConstants.E_ImportUsers);
        if (!rootIter.hasNext()) {
          throw new DocumentException(
              "Cannot find element "
                  + AdminExtConstants.E_ImportUsers
                  + " in uploaded bulk provisioning XML file");
        }
        org.dom4j.Element elImportUsers = (org.dom4j.Element) rootIter.next();

        IMAPAccounts = parseExternalIMAPAccounts(elImportUsers, zsc);

        Iterator connectionTypeIter = root.elementIterator(AdminExtConstants.E_connectionType);
        if (connectionTypeIter.hasNext()) {
          org.dom4j.Element elConnectionType = (org.dom4j.Element) connectionTypeIter.next();
          connectionType = elConnectionType.getTextTrim();
        }
        Iterator sourceServerTypeIter = root.elementIterator(AdminExtConstants.E_sourceServerType);
        if (sourceServerTypeIter.hasNext()) {
          org.dom4j.Element elSourceServerType = (org.dom4j.Element) sourceServerTypeIter.next();
          sourceServerType = elSourceServerType.getTextTrim();
        }
        Iterator IMAPHostIter = root.elementIterator(AdminExtConstants.E_IMAPHost);
        if (IMAPHostIter.hasNext()) {
          org.dom4j.Element elIMAPHost = (org.dom4j.Element) IMAPHostIter.next();
          IMAPhost = elIMAPHost.getTextTrim();
        }

        Iterator IMAPPortIter = root.elementIterator(AdminExtConstants.E_IMAPPort);
        if (IMAPPortIter.hasNext()) {
          org.dom4j.Element elIMAPPort = (org.dom4j.Element) IMAPPortIter.next();
          IMAPport = elIMAPPort.getTextTrim();
        }

        Iterator IndexBatchSizeIter = root.elementIterator(AdminExtConstants.E_indexBatchSize);
        if (IndexBatchSizeIter.hasNext()) {
          org.dom4j.Element elIxBatchSize = (org.dom4j.Element) IndexBatchSizeIter.next();
          indexBatchSize = elIxBatchSize.getTextTrim();
        }

        Iterator useAdminLoginIter = root.elementIterator(AdminExtConstants.E_useAdminLogin);
        if (useAdminLoginIter.hasNext()) {
          org.dom4j.Element elUseAdminLogin = (org.dom4j.Element) useAdminLoginIter.next();
          useAdminLogin = "******".equalsIgnoreCase(elUseAdminLogin.getTextTrim());
          if (useAdminLogin) {
            Iterator adminLoginIter = root.elementIterator(AdminExtConstants.E_IMAPAdminLogin);
            if (adminLoginIter.hasNext()) {
              org.dom4j.Element elAdminLogin = (org.dom4j.Element) adminLoginIter.next();
              adminLogin = elAdminLogin.getTextTrim();
            }

            Iterator adminPassIter = root.elementIterator(AdminExtConstants.E_IMAPAdminPassword);
            if (adminPassIter.hasNext()) {
              org.dom4j.Element elAdminPassword = (org.dom4j.Element) adminPassIter.next();
              adminPassword = elAdminPassword.getTextTrim();
            }
          }
        }

      } catch (DocumentException e) {
        throw ServiceException.FAILURE(
            "Bulk provisioning failed to read uploaded XML document.", e);
      } catch (IOException e) {
        throw ServiceException.FAILURE(
            "Bulk provisioning failed to read uploaded XML document.", e);
      }
    } else if (sourceType.equalsIgnoreCase(ZimbraBulkProvisionExt.FILE_FORMAT_ZIMBRA)) {
      IMAPAccounts = getZimbraAccounts(request, zsc);
    } else {
      throw ServiceException.INVALID_REQUEST(
          String.format(
              "Invalid value of %s parameter: %s. Allowed values: %s, %s",
              AdminExtConstants.A_sourceType,
              sourceType,
              ZimbraBulkProvisionExt.FILE_FORMAT_ZIMBRA,
              AdminFileDownload.FILE_FORMAT_BULK_XML),
          null);
    }

    /*
     * Process the list of accounts. Find existing datasources and check their states.
     */
    int numIdleAccounts = 0;
    int numRunningAccounts = 0;
    int numFinishedAccounts = 0;
    List<ExternalIMAPAccount> idleAccounts = null;
    if (IMAPAccounts.containsKey(accountState.idle)) {
      idleAccounts = IMAPAccounts.get(accountState.idle);
      if (idleAccounts != null) {
        numIdleAccounts = idleAccounts.size();
      }
    }
    List<ExternalIMAPAccount> runningAccounts;
    if (IMAPAccounts.containsKey(accountState.running)) {
      runningAccounts = IMAPAccounts.get(accountState.running);
      if (runningAccounts != null) {
        Element elRunningAccounts = response.addElement(AdminExtConstants.E_runningAccounts);
        numRunningAccounts = runningAccounts.size();
        Iterator<ExternalIMAPAccount> accountsIter = runningAccounts.iterator();
        while (accountsIter.hasNext()) {
          ExternalIMAPAccount acct = accountsIter.next();
          Element elAccount = elRunningAccounts.addElement(AdminConstants.E_ACCOUNT);
          elAccount.addAttribute(AdminConstants.A_NAME, acct.getAccount().getName());
          elAccount.addAttribute(AdminConstants.A_ID, acct.getAccount().getId());
        }
      }
    }

    if (IMAPAccounts.containsKey(accountState.finished)) {
      List accounts = IMAPAccounts.get(accountState.finished);
      if (accounts != null) {
        numFinishedAccounts = accounts.size();
      }
    }

    /*
     * Check for overwritten options
     */
    Element elConnectionType = request.getOptionalElement(AdminExtConstants.E_connectionType);
    if (elConnectionType != null) {
      connectionType = elConnectionType.getTextTrim();
    }
    Element elSourceServerType = request.getOptionalElement(AdminExtConstants.E_sourceServerType);
    if (elSourceServerType != null) {
      sourceServerType = elSourceServerType.getTextTrim();
    }
    Element elIMAPHost = request.getOptionalElement(AdminExtConstants.E_IMAPHost);
    if (elIMAPHost != null) {
      IMAPhost = elIMAPHost.getTextTrim();
    }

    Element elIMAPPort = request.getOptionalElement(AdminExtConstants.E_IMAPPort);
    if (elIMAPPort != null) {
      IMAPport = elIMAPPort.getTextTrim();
    }

    Element elBatchSize = request.getOptionalElement(AdminExtConstants.E_indexBatchSize);
    if (elBatchSize != null) {
      indexBatchSize = elBatchSize.getTextTrim();
    }

    Element elUseAdminLogin = request.getOptionalElement(AdminExtConstants.E_useAdminLogin);
    if (elUseAdminLogin != null) {
      useAdminLogin = "******".equalsIgnoreCase(elUseAdminLogin.getTextTrim());
    }

    if (useAdminLogin) {
      Element elAdminLogin = request.getOptionalElement(AdminExtConstants.E_IMAPAdminLogin);
      if (elAdminLogin != null) {
        adminLogin = elAdminLogin.getTextTrim();
      }
      Element elAdminPassword = request.getOptionalElement(AdminExtConstants.E_IMAPAdminPassword);
      if (elAdminPassword != null) {
        adminPassword = elAdminPassword.getTextTrim();
      }
    }

    if (ZimbraBulkProvisionExt.OP_PREVIEW.equalsIgnoreCase(op)) {
      /*
       * Do not start the import. Just generate a preview. We will count
       * idle and non-idle accounts.
       */
      response
          .addElement(AdminExtConstants.E_totalCount)
          .setText(Integer.toString(numIdleAccounts + numRunningAccounts + numFinishedAccounts));
      response.addElement(AdminExtConstants.E_idleCount).setText(Integer.toString(numIdleAccounts));
      response
          .addElement(AdminExtConstants.E_runningCount)
          .setText(Integer.toString(numRunningAccounts));
      response
          .addElement(AdminExtConstants.E_finishedCount)
          .setText(Integer.toString(numFinishedAccounts));

      response.addElement(AdminExtConstants.E_connectionType).setText(connectionType);
      response.addElement(AdminExtConstants.E_IMAPHost).setText(IMAPhost);
      response.addElement(AdminExtConstants.E_IMAPPort).setText(IMAPport);
      response.addElement(AdminExtConstants.E_indexBatchSize).setText(indexBatchSize);
      if (useAdminLogin) {
        response.addElement(AdminExtConstants.E_useAdminLogin).setText("1");
        response.addElement(AdminExtConstants.E_IMAPAdminLogin).setText(adminLogin);
        response.addElement(AdminExtConstants.E_IMAPAdminPassword).setText(adminPassword);
      } else {
        response.addElement(AdminExtConstants.E_useAdminLogin).setText("0");
      }
    } else if (ZimbraBulkProvisionExt.OP_START_IMPORT.equalsIgnoreCase(op)) {
      if (idleAccounts == null) {
        throw ServiceException.INVALID_REQUEST(
            "None of the specified accounts are available to start import right now.", null);
      }
      if (IMAPhost == null) {
        throw ServiceException.INVALID_REQUEST("Must specify IMAP server address!", null);
      }

      if (IMAPport == null) {
        throw ServiceException.INVALID_REQUEST("Must specify IMAP server port number!", null);
      }

      if (useAdminLogin) {
        /*
         * We must have admin login/password if we are going to connect
         * to IMAP server with admin credentials
         */
        if (adminPassword == null || adminLogin == null) {
          throw ServiceException.INVALID_REQUEST(
              "Must specify admin credentials in order to log in as admin to IMAP server if "
                  + AdminExtConstants.E_useAdminLogin
                  + " option is selected!",
              null);
        }
      }
      /*
       * Create the import queue
       */
      Queue<HashMap<taskKeys, String>> queue =
          BulkIMAPImportTaskManager.createQueue(zsc.getAuthtokenAccountId());
      Queue<HashMap<taskKeys, String>> runningQ =
          BulkIMAPImportTaskManager.createRunningQueue(zsc.getAuthtokenAccountId());
      Iterator<ExternalIMAPAccount> idleAccIter = idleAccounts.iterator();
      try {
        int size = Integer.parseInt(indexBatchSize);
        if (size <= 0) indexBatchSize = ZimbraBulkProvisionExt.DEFAULT_INDEX_BATCH_SIZE;
      } catch (Exception e) {
        indexBatchSize = ZimbraBulkProvisionExt.DEFAULT_INDEX_BATCH_SIZE;
      }
      while (idleAccIter.hasNext()) {
        ExternalIMAPAccount acct = idleAccIter.next();
        HashMap<taskKeys, String> task = new HashMap<taskKeys, String>();
        String dataSourceID =
            createIMAPDataSource(
                    acct.getAccount(),
                    IMAPhost,
                    IMAPport,
                    connectionType,
                    sourceServerType,
                    acct.getUserEmail(),
                    useAdminLogin ? adminLogin : acct.getUserLogin(),
                    useAdminLogin ? adminPassword : acct.getUserPassword(),
                    indexBatchSize,
                    useAdminLogin)
                .getId();
        String acctID = acct.getAccount().getId();
        task.put(taskKeys.accountID, acctID);
        task.put(taskKeys.dataSourceID, dataSourceID);

        synchronized (queue) {
          queue.add(task);
        }
        synchronized (runningQ) {
          runningQ.add(task);
        }
      }
      /*
       * Start the import process
       */
      BulkIMAPImportTaskManager.startImport(zsc.getAuthtokenAccountId());
    } else if (ZimbraBulkProvisionExt.OP_DISMISS_IMPORT.equalsIgnoreCase(op)) {

    }
    return response;
  }
  /**
   * Collects data about external IMAP accounts from XML
   *
   * @param is
   * @return ExternalIMAPAccount list of account data containers
   * @throws DocumentException
   * @throws IOException
   * @throws ServiceException
   */
  private Map<accountState, List<ExternalIMAPAccount>> parseExternalIMAPAccounts(
      org.dom4j.Element root, ZimbraSoapContext zsc)
      throws DocumentException, IOException, ServiceException {
    List<ExternalIMAPAccount> idleAccts = new ArrayList<ExternalIMAPAccount>();
    List<ExternalIMAPAccount> runningAccts = new ArrayList<ExternalIMAPAccount>();
    List<ExternalIMAPAccount> finishedAccts = new ArrayList<ExternalIMAPAccount>();
    Map<accountState, List<ExternalIMAPAccount>> accts =
        new HashMap<accountState, List<ExternalIMAPAccount>>();
    Provisioning prov = Provisioning.getInstance();

    for (Iterator userIter = root.elementIterator(AdminExtConstants.E_User); userIter.hasNext(); ) {
      org.dom4j.Element elUser = (org.dom4j.Element) userIter.next();
      String userEmail = "";
      String userLogin = "";
      String userPassword = "";

      for (Iterator userPropsIter = elUser.elementIterator(); userPropsIter.hasNext(); ) {
        org.dom4j.Element el = (org.dom4j.Element) userPropsIter.next();
        /*
         * We support <ExchangeMail> element for compatibility with
         * desktop based Exchange Migration utility <RemoteEmailAddress>
         * takes prevalence over <ExchangeMail> element
         */
        if (AdminExtConstants.E_ExchangeMail.equalsIgnoreCase(el.getName())) {
          userEmail = el.getTextTrim();
        }
        if (AdminExtConstants.E_remoteEmail.equalsIgnoreCase(el.getName())) {
          userEmail = el.getTextTrim();
        }
        if (AdminExtConstants.E_remoteIMAPLogin.equalsIgnoreCase(el.getName())) {
          userLogin = el.getTextTrim();
        }
        if (AdminExtConstants.E_remoteIMAPPassword.equalsIgnoreCase(el.getName())) {
          userPassword = el.getTextTrim();
        }
      }

      Account localAccount = null;
      try {
        localAccount = prov.get(AccountBy.name, userEmail, zsc.getAuthToken());
      } catch (ServiceException se) {
        ZimbraLog.gal.warn("error looking up account", se);
      }

      if (localAccount == null) {
        throw AccountServiceException.NO_SUCH_ACCOUNT(userEmail);
      }
      checkAdminLoginAsRight(zsc, prov, localAccount);

      if (userLogin.length() == 0) {
        userLogin = userEmail;
      }
      // Check if an import is running on this account already
      boolean isRunning = false;
      boolean hasRun = false;
      List<DataSource> sources = Provisioning.getInstance().getAllDataSources(localAccount);
      for (DataSource ds : sources) {
        if (ZimbraBulkProvisionExt.IMAP_IMPORT_DS_NAME.equalsIgnoreCase(ds.getName())
            && ds.getType() == DataSourceType.imap
            && ds.isImportOnly()
            && "1".equalsIgnoreCase(ds.getAttr(Provisioning.A_zimbraDataSourceFolderId))) {
          ImportStatus importStatus = DataSourceManager.getImportStatus(localAccount, ds);
          if (!isRunning) {
            synchronized (importStatus) {
              isRunning = importStatus.isRunning();
              hasRun = importStatus.hasRun();
            }
          }

          if (!hasRun) {
            synchronized (importStatus) {
              hasRun = importStatus.hasRun();
            }
          }

          if (!isRunning) {
            runningAccts.add(
                new ExternalIMAPAccount(userEmail, userLogin, userPassword, localAccount));
            break;
          } else if (hasRun) {
            finishedAccts.add(
                new ExternalIMAPAccount(userEmail, userLogin, userPassword, localAccount));
            break;
          }
        }
      }
      if (!isRunning && !hasRun) {
        idleAccts.add(new ExternalIMAPAccount(userEmail, userLogin, userPassword, localAccount));
      }
    }
    accts.put(accountState.idle, idleAccts);
    accts.put(accountState.running, runningAccts);
    accts.put(accountState.finished, finishedAccts);
    return accts;
  }