Esempio n. 1
0
bool CMapiMessage::CopyBinAttachToFile(LPATTACH lpAttach,
                                       nsIFile **tmp_file)
{
  nsCOMPtr<nsIFile> _tmp_file;
  nsresult rv = GetSpecialDirectoryWithFileName(NS_OS_TEMP_DIR,
    "mapiattach.tmp",
    getter_AddRefs(_tmp_file));
  NS_ENSURE_SUCCESS(rv, false);

  rv = _tmp_file->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 00600);
  NS_ENSURE_SUCCESS(rv, false);

  nsCString tmpPath;
  _tmp_file->GetNativePath(tmpPath);
  LPSTREAM lpStreamFile;
  HRESULT hr = CMapiApi::OpenStreamOnFile(gpMapiAllocateBuffer, gpMapiFreeBuffer, STGM_READWRITE | STGM_CREATE,
    const_cast<char*>(tmpPath.get()), NULL, &lpStreamFile);
  if (HR_FAILED(hr)) {
    MAPI_TRACE1("~~ERROR~~ OpenStreamOnFile failed - temp path: %s\r\n",
                tmpPath.get());
    return false;
  }

  bool bResult = true;
  LPSTREAM lpAttachStream;
  hr = lpAttach->OpenProperty(PR_ATTACH_DATA_BIN, &IID_IStream, 0, 0, (LPUNKNOWN *)&lpAttachStream);

  if (HR_FAILED(hr)) {
    MAPI_TRACE0("~~ERROR~~ OpenProperty failed for PR_ATTACH_DATA_BIN.\r\n");
    lpAttachStream = NULL;
    bResult = false;
  }
  else {
    STATSTG st;
    hr = lpAttachStream->Stat(&st, STATFLAG_NONAME);
    if (HR_FAILED(hr)) {
      MAPI_TRACE0("~~ERROR~~ Stat failed for attachment stream\r\n");
      bResult = false;
    }
    else {
      hr = lpAttachStream->CopyTo(lpStreamFile, st.cbSize, NULL, NULL);
      if (HR_FAILED(hr)) {
        MAPI_TRACE0("~~ERROR~~ Attach Stream CopyTo temp file failed.\r\n");
        bResult = false;
      }
    }
  }

  if (lpAttachStream)
    lpAttachStream->Release();
  lpStreamFile->Release();
  if (!bResult)
    _tmp_file->Remove(false);
  else
    CallQueryInterface(_tmp_file, tmp_file);

  return bResult;
}
Esempio n. 2
0
bool CMapiMessage::CopyMsgAttachToFile(LPATTACH lpAttach, /*out*/ nsIFile **tmp_file)
{
  bool bResult = true;
  LPMESSAGE  lpMsg;
  HRESULT hr = lpAttach->OpenProperty(PR_ATTACH_DATA_OBJ, &IID_IMessage, 0, 0,
                                      reinterpret_cast<LPUNKNOWN *>(&lpMsg));
  NS_ENSURE_SUCCESS(hr, false);

  if (!GetTmpFile(tmp_file))
    return false;

  nsCOMPtr<nsIOutputStream> destOutputStream;
  nsresult rv = MsgNewBufferedFileOutputStream(getter_AddRefs(destOutputStream), *tmp_file, -1, 0600);
  if (NS_SUCCEEDED(rv))
    rv = nsOutlookMail::ImportMessage(lpMsg, destOutputStream, nsIMsgSend::nsMsgSaveAsDraft);

  if (NS_FAILED(rv)) {
    (*tmp_file)->Remove(false);
    (*tmp_file)->Release();
    *tmp_file = 0;
  }

  return NS_SUCCEEDED(rv);
}
Esempio n. 3
0
BOOL CMapiMessage::GetAttachmentInfo( int idx)
{
  ClearTempAttachFile();

  BOOL bResult = TRUE;
  if ((idx < 0) || (idx >= (int)m_attachNums.Length())) {
    return( FALSE);
  }

  DWORD aNum = m_attachNums[idx];
  LPATTACH lpAttach = NULL;
  HRESULT hr = m_lpMsg->OpenAttach( aNum, NULL, 0, &lpAttach);
  if (HR_FAILED( hr)) {
    MAPI_TRACE2( "\t\t****Attachment error, unable to open attachment: %d, 0x%lx\r\n", idx, hr);
    return( FALSE);
  }

  LPSPropValue pVal;
  pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_MIME_TAG);
  if (pVal)
    CMapiApi::GetStringFromProp( pVal, m_attachMimeType);
  else
    m_attachMimeType.Truncate();

  pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_METHOD);
  if (pVal) {
    LONG aMethod = CMapiApi::GetLongFromProp( pVal);
    if ((aMethod == ATTACH_BY_REF_ONLY) || (aMethod == ATTACH_BY_REFERENCE) || (aMethod == ATTACH_BY_REF_RESOLVE)) {
      m_attachPath.Truncate();
      pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_PATHNAME);
      if (pVal)
        CMapiApi::GetStringFromProp( pVal, m_attachPath);
      MAPI_TRACE2("\t\t** Attachment #%d by ref: %s\r\n",
                  idx, m_attachPath.get());
      m_ownsAttachFile = FALSE;
    }
    else if (aMethod == ATTACH_BY_VALUE) {
      MAPI_TRACE1( "\t\t** Attachment #%d by value.\r\n", idx);
      bResult = CopyBinAttachToFile( lpAttach);
    }
    else if (aMethod == ATTACH_OLE) {
      MAPI_TRACE1( "\t\t** Attachment #%d by OLE - yuck!!!\r\n", idx);
    }
    else if (aMethod == ATTACH_EMBEDDED_MSG) {
      MAPI_TRACE1( "\t\t** Attachment #%d by Embedded Message??\r\n", idx);
    }
    else {
      MAPI_TRACE2( "\t\t** Attachment #%d unknown attachment method - 0x%lx\r\n", idx, aMethod);
      bResult = FALSE;
    }
  }
  else
    bResult = FALSE;

  nsCString fName, fExt;
  pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_LONG_FILENAME);
  if (pVal)
    CMapiApi::GetStringFromProp( pVal, fName);
  pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_EXTENSION);
  if (pVal)
    CMapiApi::GetStringFromProp( pVal, fExt);
  pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_SIZE);
  long sz = 0;
  if (pVal)
    sz = CMapiApi::GetLongFromProp( pVal);

  /*
    // I have no idea how this tag is used, how to interpret it's value, etc.
    // Fortunately, the Microsoft documentation is ABSOLUTELY NO HELP AT ALL.  In fact,
    // if one goes by the docs and sample code, this tag is completely 100% useless.  I'm
    // sure it has some important meaning which will one day be obvious, but for now,
    // it is ignored.
        pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_TAG);
       if (pVal) {
        ::MAPIFreeBuffer( pVal);
      }
  */

  MAPI_TRACE1("\t\t\t--- Mime type: %s\r\n", m_attachMimeType.get());
  MAPI_TRACE2("\t\t\t--- File name: %s, extension: %s\r\n",
              fName.get(), fExt.get());
  MAPI_TRACE1("\t\t\t--- Size: %ld\r\n", sz);

  if (fExt.IsEmpty()) {
    int idx = fName.RFindChar( '.');
    if (idx != -1)
      fName.Right( fExt, fName.Length() - idx);
  }

  if ((fName.RFindChar( '.') == -1) && !fExt.IsEmpty()) {
    fName += ".";
    fName += fExt;
  }

  m_attachFileName = fName;

  if (m_attachMimeType.IsEmpty()) {
    PRUint8 *pType = NULL;
    if (!fExt.IsEmpty()) {
      pType = CMimeTypes::GetMimeType( fExt);
    }
    if (pType)
      m_attachMimeType = (PC_S8)pType;
    else
      m_attachMimeType = "application/octet-stream";
  }

  pVal = CMapiApi::GetMapiProperty( lpAttach, PR_ATTACH_TRANSPORT_NAME);
  if (pVal) {
    CMapiApi::GetStringFromProp( pVal, fName);
    MAPI_TRACE1("\t\t\t--- Transport name: %s\r\n", fName.get());
  }

  lpAttach->Release();

  return( bResult);
}
Esempio n. 4
0
BOOL CMapiMessage::CopyBinAttachToFile( LPATTACH lpAttach)
{
  LPSTREAM lpStreamFile;

  m_ownsAttachFile = FALSE;
  m_attachPath.Truncate();

  nsCOMPtr<nsIFile> tmpFile;
  nsresult rv = GetSpecialDirectoryWithFileName(NS_OS_TEMP_DIR,
    "mapiattach.tmp",
    getter_AddRefs(tmpFile));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = tmpFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 00600);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCString tmpPath;
  tmpFile->GetNativePath(tmpPath);
  HRESULT hr = CMapiApi::OpenStreamOnFile( gpMapiAllocateBuffer, gpMapiFreeBuffer, STGM_READWRITE | STGM_CREATE,
    (char *) tmpPath.get(), NULL, &lpStreamFile);
  if (HR_FAILED(hr)) {
    MAPI_TRACE1("~~ERROR~~ OpenStreamOnFile failed - temp path: %s\r\n",
                tmpPath.get());
    return( FALSE);
  }
  MAPI_TRACE1("\t\t** Attachment extracted to temp file: %s\r\n",
              m_attachPath.get());

  BOOL bResult = TRUE;
  LPSTREAM lpAttachStream;
  hr = lpAttach->OpenProperty( PR_ATTACH_DATA_BIN, &IID_IStream, 0, 0, (LPUNKNOWN *)&lpAttachStream);

  if (HR_FAILED( hr)) {
    MAPI_TRACE0( "~~ERROR~~ OpenProperty failed for PR_ATTACH_DATA_BIN.\r\n");
    lpAttachStream = NULL;
    bResult = FALSE;
  }
  else {
    STATSTG st;
    hr = lpAttachStream->Stat( &st, STATFLAG_NONAME);
    if (HR_FAILED( hr)) {
      MAPI_TRACE0( "~~ERROR~~ Stat failed for attachment stream\r\n");
      bResult = FALSE;
    }
    else {
      hr = lpAttachStream->CopyTo( lpStreamFile, st.cbSize, NULL, NULL);
      if (HR_FAILED( hr)) {
        MAPI_TRACE0( "~~ERROR~~ Attach Stream CopyTo temp file failed.\r\n");
        bResult = FALSE;
      }
    }
  }

  m_attachPath = tmpPath;
  if (lpAttachStream)
    lpAttachStream->Release();
  lpStreamFile->Release();
  if (!bResult)
    tmpFile->Remove(PR_FALSE);
  else
    m_ownsAttachFile = TRUE;

  return( bResult);
}
Esempio n. 5
0
/* This seems to be called if one clicks on Save in the context menu.
   And also sometimes before an Open click. */
STDMETHODIMP
GpgolAttachedFileEvents::OnWritePattToSzFile
  (LPATTACH att, LPTSTR file, ULONG flags)
{
  HRESULT hr;
  ULONG tag;
  char *iv;
  size_t ivlen;
  symenc_t symenc;
  LPSTREAM stream;
  char tmpbuf[16];
  ULONG nread;
  int rc;

  log_debug ("%s:%s: att=%p file=`%s' flags=%lx\n",
	     SRCNAME, __func__, att, file, flags);
  if (!att)
    return E_FAIL;

  if (get_gpgolprotectiv_tag ((LPMESSAGE)att, &tag) )
    return E_ABORT;
  iv = mapi_get_binary_prop ((LPMESSAGE)att, tag, &ivlen);
  if (!iv)
    return S_FALSE; /* Not encrypted by us - Let OL continue as usual.  */

  symenc = symenc_open (get_128bit_session_key (), 16, iv, ivlen);
  xfree (iv);
  if (!symenc)
    {
      log_error ("%s:%s: can't open encryption context", SRCNAME, __func__);
      return E_ABORT;
    }

  hr = att->OpenProperty (PR_ATTACH_DATA_BIN, &IID_IStream,
                          0, 0, (LPUNKNOWN*) &stream);
  if (FAILED (hr))
    {
      log_error ("%s:%s: can't open data stream of attachment: hr=%#lx",
                 SRCNAME, __func__, hr);
      symenc_close (symenc);
      return E_ABORT;
    }

  hr = stream->Read (tmpbuf, 16, &nread);
  if (hr)
    {
      log_debug ("%s:%s: Read failed: hr=%#lx", SRCNAME, __func__, hr);
      stream->Release ();
      symenc_close (symenc);
      return E_ABORT;
    }
  symenc_cfb_decrypt (symenc, tmpbuf, tmpbuf, 16);
  if (memcmp (tmpbuf, "GpgOL attachment", 16))
    {
      MessageBox (NULL,
                  _("Sorry, we are not able to decrypt this attachment.\n\n"
                    "Please use the decrypt/verify button to decrypt the\n"
                    "entire message again.  Then open this attachment."),
                  "GpgOL", MB_ICONERROR|MB_OK);
      stream->Release ();
      symenc_close (symenc);
      return E_ABORT;
    }

  rc = decrypt_and_write_file (stream, file, symenc);

  stream->Release ();
  symenc_close (symenc);
  return rc;
}
Esempio n. 6
0
bool CMapiMessage::AddAttachment(DWORD aNum)
{
  LPATTACH lpAttach = NULL;
  HRESULT hr = m_lpMsg->OpenAttach(aNum, NULL, 0, &lpAttach);
  if (HR_FAILED(hr)) {
    MAPI_TRACE2("\t\t****Attachment error, unable to open attachment: %d, 0x%lx\r\n", idx, hr);
    return false;
  }

  bool bResult = false;
  attach_data *data = new attach_data;
  ULONG aMethod;
  if (data) {
    bResult = true;

    // 1. Get the file that contains the attachment data
    LPSPropValue pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_METHOD);
    if (pVal) {
      aMethod = CMapiApi::GetLongFromProp(pVal);
      switch (aMethod) {
      case ATTACH_BY_VALUE:
        MAPI_TRACE1("\t\t** Attachment #%d by value.\r\n", aNum);
        bResult = CopyBinAttachToFile(lpAttach, getter_AddRefs(data->tmp_file));
        data->delete_file = true;
        break;
      case ATTACH_BY_REFERENCE:
      case ATTACH_BY_REF_RESOLVE:
      case ATTACH_BY_REF_ONLY:
        pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_PATHNAME_W);
        if (pVal) {
          nsCString path;
          CMapiApi::GetStringFromProp(pVal, path);
          nsresult rv;
          data->tmp_file = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
          if (NS_FAILED(rv) || !data->tmp_file) {
            MAPI_TRACE0("*** Error creating file spec for attachment\n");
            bResult = false;
          }
          else data->tmp_file->InitWithNativePath(path);
        }
        MAPI_TRACE2("\t\t** Attachment #%d by ref: %s\r\n",
          aNum, m_attachPath.get());
        break;
      case ATTACH_EMBEDDED_MSG:
        MAPI_TRACE1("\t\t** Attachment #%d by Embedded Message??\r\n", aNum);
        // Convert the embedded IMessage from PR_ATTACH_DATA_OBJ to rfc822 attachment
        // (see http://msdn.microsoft.com/en-us/library/cc842329.aspx)
        // This is a recursive call.
        bResult = CopyMsgAttachToFile(lpAttach, getter_AddRefs(data->tmp_file));
        data->delete_file = true;
        break;
      case ATTACH_OLE:
        MAPI_TRACE1("\t\t** Attachment #%d by OLE - yuck!!!\r\n", aNum);
        break;
      default:
        MAPI_TRACE2("\t\t** Attachment #%d unknown attachment method - 0x%lx\r\n", aNum, aMethod);
        bResult = false;
      }
    }
    else
      bResult = false;

    if (bResult)
      bResult = data->tmp_file;

    if (bResult) {
      bool isFile = false;
      bool exists = false;
      data->tmp_file->Exists(&exists);
      data->tmp_file->IsFile(&isFile);

      if (!exists || !isFile) {
        bResult = false;
        MAPI_TRACE0("Attachment file does not exist\n");
      }
    }

    if (bResult)
      bResult = GetURL(data->tmp_file, getter_AddRefs(data->orig_url));

    if (bResult) {
      // Now we have the file; proceed to the other properties

      data->encoding = NS_strdup(ENCODING_BINARY);

      nsString fname, fext;
      pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_LONG_FILENAME_W);
      if (!pVal)
        pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_FILENAME_W);
      CMapiApi::GetStringFromProp(pVal, fname);
      pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_EXTENSION_W);
      CMapiApi::GetStringFromProp(pVal, fext);
      MAPI_TRACE2("\t\t\t--- File name: %s, extension: %s\r\n",
        fname.get(), fext.get());

      if (fext.IsEmpty()) {
        int idx = fname.RFindChar(L'.');
        if (idx != -1)
          fext = Substring(fname, idx);
      }
      else if (fname.RFindChar(L'.') == -1) {
        fname += L".";
        fname += fext;
      }
      if (fname.IsEmpty()) {
        // If no description use "Attachment i" format.
        fname = L"Attachment ";
        fname.AppendInt(static_cast<uint32_t>(aNum));
      }
      data->real_name = ToNewUTF8String(fname);

      nsCString tmp;
       // We have converted it to the rfc822 document
      if (aMethod == ATTACH_EMBEDDED_MSG) {
        data->type = NS_strdup(MESSAGE_RFC822);
      } else {
        pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_MIME_TAG_A);
        CMapiApi::GetStringFromProp(pVal, tmp);
        MAPI_TRACE1("\t\t\t--- Mime type: %s\r\n", tmp.get());
        if (tmp.IsEmpty()) {
          uint8_t *pType = NULL;
          if (!fext.IsEmpty()) {
            pType = CMimeTypes::GetMimeType(fext);
          }
          if (pType)
            data->type = NS_strdup((PC_S8)pType);
          else
            data->type = NS_strdup(APPLICATION_OCTET_STREAM);
        }
        else
          data->type = ToNewCString(tmp);
      }

      pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_CONTENT_ID_A);
      CMapiApi::GetStringFromProp(pVal, tmp);
      if (!tmp.IsEmpty())
        data->cid = ToNewCString(tmp);
    }
    if (bResult) {
      // Now we need to decide if this attachment is embedded or not.
      // At first, I tried to simply check for the presence of the Content-Id.
      // But it turned out that this method is unreliable, since there exist cases
      // when an attachment has a Content-Id while isn't embedded (even in a message
      // with a plain-text body!). So next I tried to look for <img> tags that contain
      // the found Content-Id. But this is unreliable, too, because there exist cases
      // where other places of HTML reference the embedded messages (e.g. it may be
      // a background of a table cell, or some CSS; further, it is possible that the
      // reference to an embedded object is not in the main body, but in another
      // embedded object - like body references a CSS attachment that in turn references
      // a picture as a background of its element). From the other hand, it's unreliable
      // to relax the search criteria to any occurence of the Content-Id string in the body -
      // partly because the string may be simply in a text or other non-referencing part,
      // partly because of the abovementioned possibility that the reference is outside
      // the body at all.
      // There exist the PR_ATTACH_FLAGS property of the attachment. The MS documentation
      // tells about two possible flags in it: ATT_INVISIBLE_IN_HTML and ATT_INVISIBLE_IN_RTF.
      // There is at least one more undocumented flag: ATT_MHTML_REF. Some sources in Internet
      // suggest simply check for the latter flag to distinguish between the embedded
      // and ordinary attachments. But my observations indicate that even if the flags
      // don't include ATT_MHTML_REF, the attachment is still may be embedded.
      // However, my observations always show that the message is embedded if the flags
      // is not 0.
      // So now I will simply test for the non-zero flags to decide whether the attachment
      // is embedded or not. Possible advantage is reliability (I hope).
      // Another advantage is that it's much faster than search the body for Content-Id.

      DWORD flags = 0;

      pVal = CMapiApi::GetMapiProperty(lpAttach, PR_ATTACH_FLAGS);
      if (pVal)
        flags = CMapiApi::GetLongFromProp(pVal);
      if (m_bodyIsHtml && data->cid && (flags != 0)) // this is the embedded attachment
        m_embattachments.push_back(data);
      else // this is ordinary attachment
        m_stdattachments.push_back(data);
    }
    else {
      delete data;
    }
  }

  lpAttach->Release();
  return bResult;
}