NS_IMETHODIMP 
nsMailboxService::SaveMessageToDisk(const char *aMessageURI, 
                                    nsIFileSpec *aFile, 
                                    PRBool aAddDummyEnvelope, 
                                    nsIUrlListener *aUrlListener,
                                    nsIURI **aURL,
                                    PRBool canonicalLineEnding,
                                    nsIMsgWindow *aMsgWindow)
{
  nsresult rv = NS_OK;
  nsCOMPtr<nsIMailboxUrl> mailboxurl;
  
  rv = PrepareMessageUrl(aMessageURI, aUrlListener, nsIMailboxUrl::ActionSaveMessageToDisk, getter_AddRefs(mailboxurl), aMsgWindow);
  
  if (NS_SUCCEEDED(rv))
  {
    nsCOMPtr<nsIMsgMessageUrl> msgUrl = do_QueryInterface(mailboxurl);
    if (msgUrl)
    {
      msgUrl->SetMessageFile(aFile);
      msgUrl->SetAddDummyEnvelope(aAddDummyEnvelope);
      msgUrl->SetCanonicalLineEnding(canonicalLineEnding);
    }
    
    nsCOMPtr<nsIURI> url = do_QueryInterface(mailboxurl);
    rv = RunMailboxUrl(url);
  }
  
  if (aURL)
    mailboxurl->QueryInterface(NS_GET_IID(nsIURI), (void **) aURL);
  
  return rv;
}
NS_IMETHODIMP MailEwsMsgMessageService::CopyMessages(uint32_t aNumKeys,
                                                     nsMsgKey*aMsgKeys,
                                                     nsIMsgFolder *srcFolder,
                                                     nsIStreamListener *aMailboxCopyHandler,
                                                     bool moveMessage,
                                                     nsIUrlListener *aUrlListener,
                                                     nsIMsgWindow *aMsgWindow, 
                                                     nsIURI **aURL)
{
  NS_ENSURE_ARG_POINTER(aMailboxCopyHandler);
  NS_ENSURE_ARG_POINTER(aMsgKeys);

  nsresult rv = NS_OK;
  NS_ENSURE_ARG(srcFolder);
  NS_ENSURE_ARG(aMsgKeys);
  nsCOMPtr<nsIMailboxUrl> mailboxurl;

  mailews_logger << "Message Service Copy Messages-------------" << std::endl;

  nsMailboxAction actionToUse = nsIMailboxUrl::ActionMoveMessage;
  if (!moveMessage)
     actionToUse = nsIMailboxUrl::ActionCopyMessage;

  nsCOMPtr <nsIMsgDBHdr> msgHdr;
  nsCOMPtr <nsIMsgDatabase> db;
  srcFolder->GetMsgDatabase(getter_AddRefs(db));
  if (db)
  {
    db->GetMsgHdrForKey(aMsgKeys[0], getter_AddRefs(msgHdr));
    if (msgHdr)
    {
      nsCString uri;
      srcFolder->GetURI(uri);
      mailews_logger << "Src Folder uri:" << uri.get() << std::endl;
      srcFolder->GetUriForMsg(msgHdr, uri);
      mailews_logger << "Msg uri:" << uri.get() << std::endl;
      rv = PrepareMessageUrl(uri.get(), aUrlListener, actionToUse , getter_AddRefs(mailboxurl), aMsgWindow);

      if (NS_SUCCEEDED(rv))
      {
        nsCOMPtr<nsIURI> url = do_QueryInterface(mailboxurl);
        nsCOMPtr<nsIMsgMailNewsUrl> msgUrl (do_QueryInterface(url));
        nsCOMPtr<nsIMailboxUrl> mailboxUrl (do_QueryInterface(url));
        msgUrl->SetMsgWindow(aMsgWindow);

        mailboxUrl->SetMoveCopyMsgKeys(aMsgKeys, aNumKeys);
        rv = RunMailboxUrl(url, aMailboxCopyHandler);
      }
    }
  }
  if (aURL && mailboxurl)
    CallQueryInterface(mailboxurl, aURL);

  return rv;
}
NS_IMETHODIMP nsMailboxService::GetUrlForUri(const char *aMessageURI, nsIURI **aURL, nsIMsgWindow *aMsgWindow)
{
  if (!strncmp(aMessageURI, "file:", 5) || PL_strstr(aMessageURI, "type=application/x-message-display")
    || !strncmp(aMessageURI, "mailbox:", 8))
    return NS_NewURI(aURL, aMessageURI);

  nsresult rv = NS_OK;
  nsCOMPtr<nsIMailboxUrl> mailboxurl;
  rv = PrepareMessageUrl(aMessageURI, nsnull, nsIMailboxUrl::ActionFetchMessage, getter_AddRefs(mailboxurl), aMsgWindow);
  if (NS_SUCCEEDED(rv) && mailboxurl)
    rv = mailboxurl->QueryInterface(NS_GET_IID(nsIURI), (void **) aURL);
  return rv;
}
nsresult nsMailboxService::CopyMessages(nsMsgKeyArray *msgKeys,
                              nsIMsgFolder *srcFolder,
                              nsIStreamListener * aMailboxCopyHandler,
                              PRBool moveMessage,
                              nsIUrlListener * aUrlListener,
                              nsIMsgWindow *aMsgWindow,
                              nsIURI **aURL)
{
  nsresult rv = NS_OK;
  NS_ENSURE_ARG(srcFolder);
  nsCOMPtr<nsIMailboxUrl> mailboxurl;

  nsMailboxAction actionToUse = nsIMailboxUrl::ActionMoveMessage;
  if (!moveMessage)
     actionToUse = nsIMailboxUrl::ActionCopyMessage;

  nsCOMPtr <nsIMsgDBHdr> msgHdr;
  nsCOMPtr <nsIMsgDatabase> db;
  srcFolder->GetMsgDatabase(aMsgWindow, getter_AddRefs(db));
  if (db)
  {
    db->GetMsgHdrForKey(msgKeys->GetAt(0), getter_AddRefs(msgHdr));
    if (msgHdr)
    {
      nsXPIDLCString uri;
      srcFolder->GetUriForMsg(msgHdr, getter_Copies(uri));
      rv = PrepareMessageUrl(uri, aUrlListener, actionToUse , getter_AddRefs(mailboxurl), aMsgWindow);

      if (NS_SUCCEEDED(rv))
      {
        nsCOMPtr<nsIURI> url = do_QueryInterface(mailboxurl);
        nsCOMPtr<nsIMsgMailNewsUrl> msgUrl (do_QueryInterface(url));
        nsCOMPtr<nsIMailboxUrl> mailboxUrl (do_QueryInterface(url));
        msgUrl->SetMsgWindow(aMsgWindow);

        mailboxUrl->SetMoveCopyMsgKeys(msgKeys->GetArray(), msgKeys->GetSize());
        rv = RunMailboxUrl(url, aMailboxCopyHandler); 
      }
    }
  }
  if (aURL)
    mailboxurl->QueryInterface(NS_GET_IID(nsIURI), (void **) aURL);

  return rv;
}
NS_IMETHODIMP MailEwsMsgMessageService::GetUrlForUri(const char *aMessageURI, 
                                                     nsIURI **aURL, 
                                                     nsIMsgWindow *aMsgWindow) 
{
  nsAutoCString messageURI(aMessageURI);

  if (messageURI.Find(NS_LITERAL_CSTRING("&type=application/x-message-display")) != kNotFound)
    return NS_NewURI(aURL, aMessageURI);

  if (!strncmp(aMessageURI, "ews:", 4))
    return NS_NewURI(aURL, aMessageURI);

  nsCOMPtr<nsIMailboxUrl> mailboxurl;
  nsresult rv = PrepareMessageUrl(aMessageURI,
                                  nullptr,
                                  nsIMailboxUrl::ActionFetchMessage,
                                  getter_AddRefs(mailboxurl),
                                  aMsgWindow);
  NS_ENSURE_SUCCESS(rv, rv);

  return CallQueryInterface(mailboxurl, aURL);
}
NS_IMETHODIMP MailEwsMsgMessageService::SaveMessageToDisk(const char *aMessageURI,
                                                          nsIFile *aFile,
                                                          bool aAddDummyEnvelope,
                                                          nsIUrlListener *aUrlListener,
                                                          nsIURI **aURL,
                                                          bool canonicalLineEnding,
                                                          nsIMsgWindow *aMsgWindow)
{
  mailews_logger << "Save message to disk"
            << aMessageURI
            << aFile
            << std::endl;
  nsresult rv = NS_OK;
  nsCOMPtr<nsIMailboxUrl> mailboxurl;

  rv = PrepareMessageUrl(aMessageURI, aUrlListener, nsIMailboxUrl::ActionSaveMessageToDisk, getter_AddRefs(mailboxurl), aMsgWindow);

  if (NS_SUCCEEDED(rv))
  {
    nsCOMPtr<nsIMsgMessageUrl> msgUrl = do_QueryInterface(mailboxurl);
    if (msgUrl)
    {
      msgUrl->SetMessageFile(aFile);
      msgUrl->SetAddDummyEnvelope(aAddDummyEnvelope);
      msgUrl->SetCanonicalLineEnding(canonicalLineEnding);
    }

    nsCOMPtr<nsIURI> url = do_QueryInterface(mailboxurl);
    rv = RunMailboxUrl(url, nullptr);
  }

  if (aURL && mailboxurl)
    CallQueryInterface(mailboxurl, aURL);

  return rv;
}
nsresult nsMailboxService::FetchMessage(const char* aMessageURI,
                                        nsISupports * aDisplayConsumer, 
                                        nsIMsgWindow * aMsgWindow,
                                        nsIUrlListener * aUrlListener,
                                        const char * aFileName, /* only used by open attachment... */
                                        nsMailboxAction mailboxAction,
                                        const char * aCharsetOverride,
                                        nsIURI ** aURL)
{
  nsresult rv = NS_OK;
  nsCOMPtr<nsIMailboxUrl> mailboxurl;
  
  nsMailboxAction actionToUse = mailboxAction;
  
  nsCOMPtr <nsIURI> url;

  nsCAutoString uriString(aMessageURI);

  if (!strncmp(aMessageURI, "file:", 5))
  {
    PRInt64 fileSize;
    nsCOMPtr<nsIURI> fileUri;
    rv = NS_NewURI(getter_AddRefs(fileUri), aMessageURI);
    NS_ENSURE_SUCCESS(rv, rv);
    nsCOMPtr <nsIFileURL> fileUrl = do_QueryInterface(fileUri, &rv);
    NS_ENSURE_SUCCESS(rv, rv);
    nsCOMPtr <nsIFile> file;
    rv = fileUrl->GetFile(getter_AddRefs(file));
    NS_ENSURE_SUCCESS(rv, rv);
    file->GetFileSize(&fileSize);
    nsCAutoString uriString(aMessageURI);
    uriString.ReplaceSubstring(NS_LITERAL_CSTRING("file:"), NS_LITERAL_CSTRING("mailbox:"));
    uriString.Append(NS_LITERAL_CSTRING("&number=0"));
    rv = NS_NewURI(getter_AddRefs(url), uriString);
    NS_ENSURE_SUCCESS(rv, rv);

    nsCOMPtr<nsIMsgMailNewsUrl> msgurl = do_QueryInterface(url);
    if (msgurl)
    {
      msgurl->SetMsgWindow(aMsgWindow);
      nsCOMPtr <nsIMailboxUrl> mailboxUrl = do_QueryInterface(msgurl, &rv);
      mailboxUrl->SetMessageSize((PRUint32) fileSize);
      nsCOMPtr <nsIMsgHeaderSink> headerSink;
       // need to tell the header sink to capture some headers to create a fake db header
       // so we can do reply to a .eml file or a rfc822 msg attachment.
      if (aMsgWindow)
        aMsgWindow->GetMsgHeaderSink(getter_AddRefs(headerSink));
      if (headerSink)
      {
        nsCOMPtr <nsIMsgDBHdr> dummyHeader;
        headerSink->GetDummyMsgHeader(getter_AddRefs(dummyHeader));
        if (dummyHeader)
          dummyHeader->SetMessageSize((PRUint32) fileSize);
      }
    }
  }
  else
  {

    // this happens with forward inline of message/rfc822 attachment
    // opened in a stand-alone msg window.
    PRInt32 typeIndex = typeIndex = uriString.Find("&type=application/x-message-display");
    if (typeIndex != kNotFound)
    {
      uriString.Cut(typeIndex, sizeof("&type=application/x-message-display") - 1);
      rv = NS_NewURI(getter_AddRefs(url), uriString.get());
      mailboxurl = do_QueryInterface(url);
    }
    else
      rv = PrepareMessageUrl(aMessageURI, aUrlListener, actionToUse , getter_AddRefs(mailboxurl), aMsgWindow);
  
    if (NS_SUCCEEDED(rv))
    {
      url = do_QueryInterface(mailboxurl);
      nsCOMPtr<nsIMsgMailNewsUrl> msgUrl (do_QueryInterface(url));
      msgUrl->SetMsgWindow(aMsgWindow);
      nsCOMPtr<nsIMsgI18NUrl> i18nurl (do_QueryInterface(msgUrl));
      i18nurl->SetCharsetOverRide(aCharsetOverride);
      if (aFileName)
        msgUrl->SetFileName(nsDependentCString(aFileName));
    }
  }
    
  // instead of running the mailbox url like we used to, let's try to run the url in the docshell...
  nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aDisplayConsumer, &rv));
  // if we were given a docShell, run the url in the docshell..otherwise just run it normally.
  if (NS_SUCCEEDED(rv) && docShell)
  {
    nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
    // DIRTY LITTLE HACK --> if we are opening an attachment we want the docshell to
    // treat this load as if it were a user click event. Then the dispatching stuff will be much
    // happier.
    if (mailboxAction == nsIMailboxUrl::ActionFetchPart)
    {
      docShell->CreateLoadInfo(getter_AddRefs(loadInfo));
      loadInfo->SetLoadType(nsIDocShellLoadInfo::loadLink);
    }
    rv = docShell->LoadURI(url, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, PR_FALSE);
  }
  else
    rv = RunMailboxUrl(url, aDisplayConsumer); 
 
  if (aURL && mailboxurl)
    mailboxurl->QueryInterface(NS_GET_IID(nsIURI), (void **) aURL);
  
  return rv;
}
static nsresult FetchMessage(const char* aMessageURI,
                             nsISupports * aDisplayConsumer,
                             nsIMsgWindow * aMsgWindow,
                             nsIUrlListener * aUrlListener,
                             const char * aFileName, /* only used by open attachment... */
                             nsMailboxAction mailboxAction,
                             const char * aCharsetOverride,
                             nsIURI ** aURL) {
  nsresult rv;

  nsCOMPtr<nsIMsgFolder> folder;
  nsAutoCString mimePart;
  nsAutoCString folderURI;
  nsAutoCString messageURI(aMessageURI);
  nsCOMPtr <nsIURI> uri;
  nsCOMPtr<nsIMailboxUrl> mailboxurl;
  nsCOMPtr<nsIMsgMailNewsUrl> msgUrl;

  int32_t typeIndex = messageURI.Find("&type=application/x-message-display");
  if (typeIndex != kNotFound)
  {
    // This happens with forward inline of a message/rfc822 attachment opened in
    // a standalone msg window.
    // So, just cut to the chase and call AsyncOpen on a channel.
    messageURI.Cut(typeIndex,
                   sizeof("&type=application/x-message-display") - 1);
    rv = NS_NewURI(getter_AddRefs(uri), messageURI.get());
    mailboxurl = do_QueryInterface(uri);

    mailews_logger << "display message with uri 2:"
              << messageURI.get()
              << std::endl;
  } else {
    rv = PrepareMessageUrl(aMessageURI,
                           aUrlListener,
                           nsIMailboxUrl::ActionFetchMessage,
                           getter_AddRefs(mailboxurl),
                           aMsgWindow);
    NS_ENSURE_SUCCESS(rv, rv);
  }
  
  uri = do_QueryInterface(mailboxurl);
  if (aURL)
    NS_IF_ADDREF(*aURL = uri);
  
  nsCOMPtr<nsIMsgI18NUrl> i18nurl(do_QueryInterface(msgUrl));
  if (i18nurl)
    i18nurl->SetCharsetOverRide(aCharsetOverride);

  nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aDisplayConsumer, &rv));
  
  if (NS_SUCCEEDED(rv) && docShell) {
    rv = docShell->LoadURI(uri,
                           nullptr,
                           nsIWebNavigation::LOAD_FLAGS_NONE,
                           false);
    NS_ENSURE_SUCCESS(rv, rv);
    mailews_logger << "uri loaded"
              << uri
              << std::endl;
  } else {
    mailews_logger << "unable to get doc shell"
              << std::endl;
    rv = RunMailboxUrl(uri, aDisplayConsumer);
  }
  return rv;
}