HRESULT MAPIContact::GetContactImage(wstring &wstrImagePath) { HRESULT hr = S_OK; Zimbra::Util::ScopedInterface<IStream> pSrcStream; { Zimbra::Util::ScopedRowSet pAttachRows; Zimbra::Util::ScopedInterface<IMAPITable> pAttachTable; SizedSPropTagArray(3, attachProps) = { 3, { PR_ATTACH_NUM, PR_ATTACH_SIZE, PR_ATTACH_LONG_FILENAME } }; hr = m_pMessage->GetAttachmentTable(MAPI_UNICODE, pAttachTable.getptr()); if (SUCCEEDED(hr)) { if (FAILED(hr = pAttachTable->SetColumns((LPSPropTagArray) & attachProps, 0))) return hr; ULONG ulRowCount = 0; if (FAILED(hr = pAttachTable->GetRowCount(0, &ulRowCount))) return hr; if (FAILED(hr = pAttachTable->QueryRows(ulRowCount, 0, pAttachRows.getptr()))) return hr; if (SUCCEEDED(hr)) { hr = MAPI_E_NOT_FOUND; for (unsigned int i = 0; i < pAttachRows->cRows; i++) { // if property couldn't be found or returns error, skip it if ((pAttachRows->aRow[i].lpProps[2].ulPropTag == PT_ERROR) || (pAttachRows->aRow[i].lpProps[2].Value.err == MAPI_E_NOT_FOUND)) continue; // Discard the attachmetnt if its not contact picture if (_tcscmp(pAttachRows->aRow[i].lpProps[2].Value.LPSZ, _T( "ContactPicture.jpg"))) continue; Zimbra::Util::ScopedInterface<IAttach> pAttach; if (FAILED(hr = m_pMessage->OpenAttach( pAttachRows->aRow[i].lpProps[0].Value.l, NULL, 0, pAttach.getptr()))) continue; if (FAILED(hr = pAttach->OpenProperty(PR_ATTACH_DATA_BIN, &IID_IStream, STGM_READ, 0, (LPUNKNOWN FAR *)pSrcStream.getptr()))) return hr; break; } } } } if (hr != S_OK) return hr; // copy image to file wstring wstrTempAppDirPath; char *lpszDirName = NULL; char *lpszUniqueName = NULL; Zimbra::Util::ScopedInterface<IStream> pDestStream; if (!Zimbra::MAPI::Util::GetAppTemporaryDirectory(wstrTempAppDirPath)) return MAPI_E_ACCESS_DENIED; WtoA((LPWSTR)wstrTempAppDirPath.c_str(), lpszDirName); string strFQFileName = lpszDirName; WtoA((LPWSTR)Zimbra::MAPI::Util::GetUniqueName().c_str(), lpszUniqueName); strFQFileName += "\\ZmContact_"; strFQFileName += lpszUniqueName; strFQFileName += ".jpg"; SafeDelete(lpszDirName); SafeDelete(lpszUniqueName); // Open stream on file if (FAILED(hr = OpenStreamOnFile(MAPIAllocateBuffer, MAPIFreeBuffer, STGM_CREATE | STGM_READWRITE, (LPTSTR)strFQFileName.c_str(), NULL, pDestStream.getptr()))) return hr; ULARGE_INTEGER liAll = { 0 }; liAll.QuadPart = (ULONGLONG)-1; if (FAILED(hr = pSrcStream->CopyTo(pDestStream.get(), liAll, NULL, NULL))) return hr; if (FAILED(hr = pDestStream->Commit(0))) { return hr; ; } // mime file path LPWSTR lpwstrFQFileName = NULL; AtoW((LPSTR)strFQFileName.c_str(), lpwstrFQFileName); wstrImagePath = lpwstrFQFileName; SafeDelete(lpwstrFQFileName); return hr; }
HRESULT MAPIRfc2445::ExtractAttachments() { // may need to break this up so we can call for exceptions, cancel exceptions LPCWSTR errMsg; Zimbra::Util::ScopedInterface<IStream> pIStream; UINT mimeLen = 0; HRESULT hr = ConvertIt( m_pMessage, pIStream.getptr(), mimeLen ); if (FAILED(hr)) { errMsg = FormatExceptionInfo(hr, L"Mime conversion of message with attachments failed", __FILE__, __LINE__); dlogw(errMsg); return hr; } mimepp::Message mimeMsg; Zimbra::Util::ScopedBuffer<CHAR> pszMimeMsg; // go to the beginning of the stream LARGE_INTEGER li = { 0 }; hr = pIStream->Seek(li, STREAM_SEEK_SET, NULL); if (FAILED(hr)) { errMsg = FormatExceptionInfo(hr, L"Stream seek failed", __FILE__, __LINE__); dlogw(errMsg); return hr; } // +1 for NULL terminator Zimbra::Mapi::Memory::AllocateBuffer(mimeLen + 1, (LPVOID *)pszMimeMsg.getptr()); if (!pszMimeMsg.get()) { errMsg = FormatExceptionInfo(S_OK, L"Mime msg Memory alloc failed", __FILE__, __LINE__); dlogw(errMsg); return hr; } ULONG ulNumRead = 0; hr = pIStream->Read((LPVOID)(pszMimeMsg.get()), mimeLen, &ulNumRead); if (FAILED(hr)) { errMsg = FormatExceptionInfo(hr, L"Mime msg read failed", __FILE__, __LINE__); dlogw(errMsg); return hr; } if (ulNumRead != mimeLen) { errMsg = FormatExceptionInfo(hr, L"Mime msg read error", __FILE__, __LINE__); dlogw(errMsg); return hr; } // terminating string pszMimeMsg.get()[mimeLen] = '\0'; mimeMsg.setString(pszMimeMsg.get()); mimeMsg.parse(); // let's see if this message is a multipart alternative before we continue mimepp::Headers &theHeaders = mimeMsg.headers(); LPSTR pszContentType; GetContentType(theHeaders, &pszContentType); if(strncmp(pszContentType, "multipart/mixed", strlen("multipart/mixed")) != 0) { // not what we are looking for delete[] pszContentType; return S_OK; } const mimepp::Body& theBody = mimeMsg.body(); int numParts = theBody.numBodyParts(); // FBS bug 73682 -- 5/23/12 int numHiddenAttachments = GetNumHiddenAttachments(); int totalAttachments = numParts - 1; if (totalAttachments == numHiddenAttachments) { return S_OK; } // let's look for a multipart mixed and grab the attachments int ctr = numHiddenAttachments; for(int i = 0; i < numParts; i++) { // now look for attachments const mimepp::BodyPart& thePart = theBody.bodyPartAt(i); mimepp::DispositionType& disposition = thePart.headers().contentDisposition(); if(disposition.asEnum() == mimepp::DispositionType::ATTACHMENT) { const mimepp::String& theFilename = disposition.filename(); LPSTR pszAttachContentType; LPSTR pszCD; LPSTR lpszRealName = new char[256]; GetContentType(thePart.headers(), &pszAttachContentType); // FBS bug 73682 -- Exceptions are at the beginning. Don't make attachments for those if (ctr > 0) { if (0 == strcmpi(pszAttachContentType, "message/rfc822")) { ctr--; continue; } } // if((LPSTR)theFilename.length()>0) { GenerateContentDisposition(&pszCD, (LPSTR)theFilename.c_str()); strcpy(lpszRealName, (LPSTR)theFilename.c_str()); } else { char cfilename[64]; sprintf(cfilename,"attachment-%d",i); GenerateContentDisposition(&pszCD, cfilename); strcpy(lpszRealName, cfilename); } // now deal with the encoding LPSTR pContent = NULL; const mimepp::String &theContent = thePart.body().getString(); mimepp::String outputString; UINT size = 0; mimepp::TransferEncodingType& transferEncoding = thePart.headers().contentTransferEncoding(); if(transferEncoding.asEnum() == mimepp::TransferEncodingType::BASE64) { // let's decode the buffer mimepp::Base64Decoder decoder; outputString = decoder.decode(theContent); pContent = (LPSTR)outputString.c_str(); size = (UINT)outputString.size(); } else if(transferEncoding.asEnum() == mimepp::TransferEncodingType::QUOTED_PRINTABLE) { mimepp::QuotedPrintableDecoder decoder; outputString = decoder.decode(theContent); pContent = (LPSTR)outputString.c_str(); size = (UINT)outputString.size(); } else { pContent = (LPSTR)theContent.c_str(); size = (UINT)theContent.size(); } // Save stream to temp file in temp dir. We'll delete in ZimbraAPI // LPCWSTR errMsg; HRESULT hr = S_OK; wstring wstrTempAppDirPath; LPSTR lpszFQFileName = new char[256]; LPSTR lpszDirName = NULL; LPSTR lpszUniqueName = NULL; Zimbra::Util::ScopedInterface<IStream> pStream; if (!Zimbra::MAPI::Util::GetAppTemporaryDirectory(wstrTempAppDirPath)) { errMsg = FormatExceptionInfo(S_OK, L"GetAppTemporaryDirectory Failed", __FILE__, __LINE__); dloge("MAPIRfc2445 -- exception"); dloge(errMsg); return E_FAIL; } WtoA((LPWSTR)wstrTempAppDirPath.c_str(), lpszDirName); WtoA((LPWSTR)Zimbra::MAPI::Util::GetUniqueName().c_str(), lpszUniqueName); strcpy(lpszFQFileName, lpszDirName); strcat(lpszFQFileName, "\\"); strcat(lpszFQFileName, lpszUniqueName); SafeDelete(lpszDirName); SafeDelete(lpszUniqueName); // Open stream on file if (FAILED(hr = OpenStreamOnFile(MAPIAllocateBuffer, MAPIFreeBuffer, STGM_CREATE | STGM_READWRITE, (LPTSTR)lpszFQFileName, NULL, pStream.getptr()))) { errMsg = FormatExceptionInfo(hr, L"Error: OpenStreamOnFile Failed.", __FILE__, __LINE__); dloge("MAPIRfc2445 -- exception"); dloge(errMsg); return hr; } ULONG nBytesToWrite = size; ULONG nBytesWritten = 0; LPBYTE pCur = (LPBYTE)pContent; while (!FAILED(hr) && nBytesToWrite > 0) { hr = pStream->Write(pCur, nBytesToWrite, &nBytesWritten); pCur += nBytesWritten; nBytesToWrite -= nBytesWritten; } if (FAILED(hr = pStream->Commit(0))) { errMsg = FormatExceptionInfo(hr, L"Error: Stream Write Failed.", __FILE__, __LINE__); dloge("MAPIRfc2445 -- exception"); dloge(errMsg); } /////////// // delete all this in MAPIAccessWrap AttachmentInfo* pAttachmentInfo = new AttachmentInfo(); pAttachmentInfo->pszTempFile = lpszFQFileName; pAttachmentInfo->pszRealName = lpszRealName; pAttachmentInfo->pszContentDisposition = pszCD; pAttachmentInfo->pszContentType = pszAttachContentType; m_vAttachments.push_back(pAttachmentInfo); } } delete[] pszContentType; return S_OK; }
HRESULT MAPIContact::GetContactImage(wstring &wstrImagePath,wstring &wstrContentType,wstring &wstrContentDisposition) { HRESULT hr = S_OK; LPSTR strExtension=".jpg"; Zimbra::Util::ScopedInterface<IStream> pSrcStream; { Zimbra::Util::ScopedRowSet pAttachRows; Zimbra::Util::ScopedInterface<IMAPITable> pAttachTable; SizedSPropTagArray(4, attachProps) = { 4, { PR_ATTACH_NUM, PR_ATTACH_SIZE, PR_ATTACH_LONG_FILENAME,PR_ATTACH_EXTENSION } }; hr = m_pMessage->GetAttachmentTable(MAPI_UNICODE, pAttachTable.getptr()); if (SUCCEEDED(hr)) { if (FAILED(hr = pAttachTable->SetColumns((LPSPropTagArray) & attachProps, 0))) return hr; ULONG ulRowCount = 0; if (FAILED(hr = pAttachTable->GetRowCount(0, &ulRowCount))) return hr; if (FAILED(hr = pAttachTable->QueryRows(ulRowCount, 0, pAttachRows.getptr()))) return hr; if (SUCCEEDED(hr)) { hr = MAPI_E_NOT_FOUND; for (unsigned int i = 0; i < pAttachRows->cRows; i++) { // if property couldn't be found or returns error, skip it if ((pAttachRows->aRow[i].lpProps[2].ulPropTag == PT_ERROR) || (pAttachRows->aRow[i].lpProps[2].Value.err == MAPI_E_NOT_FOUND)) continue; // Discard the attachmetnt if its not contact picture if (_tcscmp(pAttachRows->aRow[i].lpProps[2].Value.LPSZ, _T( "ContactPicture.jpg"))) continue; Zimbra::Util::ScopedInterface<IAttach> pAttach; if (FAILED(hr = m_pMessage->OpenAttach( pAttachRows->aRow[i].lpProps[0].Value.l, NULL, 0, pAttach.getptr()))) continue; if (FAILED(hr = pAttach->OpenProperty(PR_ATTACH_DATA_BIN, &IID_IStream, STGM_READ, 0, (LPUNKNOWN FAR *)pSrcStream.getptr()))) return hr; // LPSPropValue pProps = NULL; // ULONG cProps = 0; // hr = pAttach->GetProps((LPSPropTagArray) & attachProps, 0, &cProps, &pProps); if(pAttachRows->aRow[i].lpProps[3].ulPropTag == PR_ATTACH_EXTENSION_A) //if (pProps[PR_ATTACH_EXTENSION].ulPropTag == PR_ATTACH_EXTENSION_A) { // add a custom header for content location to support rfc2557 LPSTR pContentType = NULL; strExtension = pAttachRows->aRow[i].lpProps[3].Value.lpszA; Zimbra::MAPI::Util::GetContentTypeFromExtension(pAttachRows->aRow[i].lpProps[3].Value.lpszA, pContentType); LPWSTR lpwstrContentType = NULL; AtoW((LPSTR)pContentType, lpwstrContentType); wstrContentType = lpwstrContentType; } break; } } } } if (hr != S_OK) return hr; // copy image to file wstring wstrTempAppDirPath; char *lpszDirName = NULL; char *lpszUniqueName = NULL; Zimbra::Util::ScopedInterface<IStream> pDestStream; if (!Zimbra::MAPI::Util::GetAppTemporaryDirectory(wstrTempAppDirPath)) return MAPI_E_ACCESS_DENIED; WtoA((LPWSTR)wstrTempAppDirPath.c_str(), lpszDirName); string strFQFileName = lpszDirName; WtoA((LPWSTR)Zimbra::MAPI::Util::GetUniqueName().c_str(), lpszUniqueName); strFQFileName += "\\ZmContact_"; strFQFileName += lpszUniqueName; //strFQFileName += ".jpg"; strFQFileName += strExtension; SafeDelete(lpszDirName); SafeDelete(lpszUniqueName); // Open stream on file if (FAILED(hr = OpenStreamOnFile(MAPIAllocateBuffer, MAPIFreeBuffer, STGM_CREATE | STGM_READWRITE, (LPTSTR)strFQFileName.c_str(), NULL, pDestStream.getptr()))) return hr; ULARGE_INTEGER liAll = { 0 }; liAll.QuadPart = (ULONGLONG)-1; if (FAILED(hr = pSrcStream->CopyTo(pDestStream.get(), liAll, NULL, NULL))) return hr; if (FAILED(hr = pDestStream->Commit(0))) { return hr; ; } // mime file path LPWSTR lpwstrFQFileName = NULL; AtoW((LPSTR)strFQFileName.c_str(), lpwstrFQFileName); wstrImagePath = lpwstrFQFileName; LPSTR ppszCD; mimepp::String theCD; theCD.append("Content-Disposition: form-data; name=\""); theCD.append(strFQFileName.c_str()); theCD.append("\"; filename=\""); theCD.append(strFQFileName.c_str()); theCD.append("\""); const char *pFinal = theCD.c_str(); Zimbra::Util::CopyString(ppszCD, (LPSTR)pFinal); LPWSTR lpwstrContentDisp = NULL; AtoW((LPSTR)theCD.c_str(), lpwstrContentDisp); wstrContentDisposition = lpwstrContentDisp; /* LPSTR pContentType = NULL; Zimbra::MAPI::Util::GetContentTypeFromExtension(".jpg", pContentType); LPWSTR lpwstrContentType = NULL; AtoW((LPSTR)pContentType, lpwstrContentType); wstrContentType = lpwstrContentType;*/ SafeDelete(lpwstrFQFileName); return hr; }