123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610 |
- /*
- * Copyright 2005 - 2016 Zarafa and its licensors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- #include <kopano/platform.h>
- #include "iCal.h"
- #include "CalDavUtil.h"
- #include <vector>
- #include <kopano/CommonUtil.h>
- #include <kopano/memory.hpp>
- #include <kopano/tie.hpp>
- #include "icaluid.h"
- #include <libxml/tree.h>
- #include <libxml/parser.h>
- #include "PublishFreeBusy.h"
- #include <kopano/mapi_ptr.h>
- using namespace std;
- using namespace KCHL;
- iCal::iCal(Http *lpRequest, IMAPISession *lpSession,
- const std::string &strSrvTz, const std::string &strCharset) :
- ProtocolBase(lpRequest, lpSession, strSrvTz, strCharset)
- {
- }
- HRESULT iCal::HrHandleCommand(const std::string &strMethod)
- {
- HRESULT hr = hrSuccess;
- if (!strMethod.compare("GET") || !strMethod.compare("HEAD"))
- hr = HrHandleIcalGet(strMethod);
- else if (!strMethod.compare("PUT"))
- hr = HrHandleIcalPost();
- else if (!strMethod.compare("DELETE"))
- hr = HrDelFolder();
- else
- hr = MAPI_E_CALL_FAILED;
- return hr;
- }
- /**
- * Handles http GET and HEAD request
- *
- * The GET request could be to retrieve one paticular msg or all calendar entries
- * HEAD is just a GET without the body returned.
- *
- * @return HRESULT
- * @retval MAPI_E_NOT_FOUND Folder or message not found
- */
- HRESULT iCal::HrHandleIcalGet(const std::string &strMethod)
- {
- HRESULT hr = hrSuccess;
- std::string strIcal;
- std::string strMsg;
- std::string strModtime;
- memory_ptr<SPropValue> lpProp;
- object_ptr<IMAPITable> lpContents;
- bool blCensorFlag = 0;
- if ((m_ulFolderFlag & SHARED_FOLDER) && !HasDelegatePerm(m_lpDefStore, m_lpActiveStore))
- blCensorFlag = true;
-
- // retrieve table and restrict as per request
- hr = HrGetContents(&~lpContents);
- if (hr != hrSuccess) {
- ec_log_err("Unable to retrieve contents of folder, error code: 0x%08X", hr);
- goto exit;
- }
- // convert table to ical data
- hr = HrGetIcal(lpContents, blCensorFlag, &strIcal);
- if (hr != hrSuccess) {
- ec_log_warn("Unable to retrieve ical data, error code: 0x%08X", hr);
- goto exit;
- }
- hr = HrGetOneProp(m_lpUsrFld, PR_LOCAL_COMMIT_TIME_MAX, &~lpProp);
- if (hr == hrSuccess)
- strModtime = SPropValToString(lpProp);
-
- exit:
- if (hr == hrSuccess)
- {
- if (!strModtime.empty())
- m_lpRequest->HrResponseHeader("Etag", strModtime);
- m_lpRequest->HrResponseHeader("Content-Type", "text/calendar; charset=\"utf-8\"");
- if (strIcal.empty()) {
- m_lpRequest->HrResponseHeader(204, "No Content");
- } else {
- m_lpRequest->HrResponseHeader(200, "OK");
- strMsg = "attachment; filename=\"" + (m_wstrFldName.empty() ? "Calendar" : W2U(m_wstrFldName.substr(0,10))) + ".ics\"";
- m_lpRequest->HrResponseHeader("Content-Disposition", strMsg);
- }
- if (strMethod.compare("GET") == 0)
- m_lpRequest->HrResponseBody(strIcal);
- // @todo, send Content-Length header? but HrFinalize in HTTP class will also send with size:0
- }
- else if (hr == MAPI_E_NOT_FOUND)
- {
- m_lpRequest->HrResponseHeader(404, "Not Found");
- }
- else
- m_lpRequest->HrResponseHeader(500, "Internal Server Error");
- return hr;
- }
- /**
- * Handles ical requests to add, modify & delete calendar entries
- *
- * @param strServerTZ server timezone string set in ical.cfg
- * @return HRESULT
- * @retval MAPI_E_NO_ACCESS insufficient permissions on folder or message
- * @retval MAPI_E_INVALID_OBJECT no mapi message in ical data
- */
- HRESULT iCal::HrHandleIcalPost()
- {
- HRESULT hr = hrSuccess;
- object_ptr<IMAPITable> lpContTable;
- SBinary sbEid = {0,0};
- SBinary sbUid = {0,0};
- ULONG ulItemCount = 0;
- ULONG ulProptag = 0;
- ICalToMapi *lpICalToMapi = NULL;
- time_t tLastMod = 0;
- bool blCensorPrivate = false;
- std::string strUidString;
- std::string strIcal;
-
- eIcalType etype = VEVENT;
- FILETIME ftModTime;
- time_t tUnixModTime;
- map<std::string, int> mpIcalEntries;
- map<std::string, FILETIME> mpSrvTimes;
- map<std::string,SBinary> mpSrvEntries;
-
- map<std::string, int>::const_iterator mpIterI;
- map<std::string,SBinary>::const_iterator mpIterJ;
- ulProptag = CHANGE_PROP_TYPE(m_lpNamedProps->aulPropTag[PROP_GOID], PT_BINARY);
- SizedSPropTagArray(3, proptags) = {3, {PR_ENTRYID, PR_LAST_MODIFICATION_TIME, ulProptag}};
- //Include PR_ENTRYID,PR_LAST_MODIFICATION_TIME & Named Prop GlobalObjUid.
-
- //retrive entries from ical data.
- CreateICalToMapi(m_lpActiveStore, m_lpAddrBook, false, &lpICalToMapi);
- m_lpRequest->HrGetBody(&strIcal);
- if(!strIcal.empty())
- {
- hr = lpICalToMapi->ParseICal(strIcal, m_strCharset, m_strSrvTz, m_lpLoginUser, 0);
- if (hr!=hrSuccess)
- goto exit;
- }
- ulItemCount = lpICalToMapi->GetItemCount();
- //map of Ical entries.
- //generate map for each entry's UID and Position.
- for (ULONG i = 0; i < ulItemCount; ++i) {
- hr = lpICalToMapi->GetItemInfo(i, &etype, &tLastMod, &sbEid);
- if (hr != hrSuccess || etype != VEVENT)
- continue;
-
- strUidString = bin2hex((ULONG)sbEid.cb,(LPBYTE)sbEid.lpb);
- mpIcalEntries[strUidString] = i;
- }
- if ((m_ulFolderFlag & SHARED_FOLDER) && !HasDelegatePerm(m_lpDefStore, m_lpActiveStore))
- blCensorPrivate = true;
- hr = m_lpUsrFld->GetContentsTable(0, &~lpContTable);
- if(hr != hrSuccess)
- goto exit;
- hr = lpContTable->SetColumns(proptags, 0);
- if (hr != hrSuccess)
- goto exit;
- //Map of server Entries.
- //Generate map of UID : Modification time & UID : ENTRYID.
- while (TRUE)
- {
- rowset_ptr lpRows;
- hr = lpContTable->QueryRows(50, 0, &~lpRows);
- if (hr != hrSuccess)
- goto exit;
- if (lpRows->cRows == 0)
- break;
- for (ULONG i = 0; i < lpRows->cRows; ++i) {
- if (lpRows->aRow[i].lpProps[0].ulPropTag != PR_ENTRYID)
- continue;
- if (lpRows->aRow[i].lpProps[2].ulPropTag == ulProptag)
- sbUid = lpRows->aRow[i].lpProps[2].Value.bin;
- else
- continue; // skip new entries
- sbEid.cb = lpRows->aRow[i].lpProps[0].Value.bin.cb;
- if ((hr = MAPIAllocateBuffer(sbEid.cb, (void **)&sbEid.lpb)) != hrSuccess)
- goto exit;
- memcpy(sbEid.lpb, lpRows->aRow[i].lpProps[0].Value.bin.lpb, sbEid.cb);
- strUidString = bin2hex((ULONG)sbUid.cb, (LPBYTE)sbUid.lpb);
- mpSrvEntries[strUidString] = sbEid;
- if (lpRows->aRow[i].lpProps[1].ulPropTag == PR_LAST_MODIFICATION_TIME)
- mpSrvTimes[strUidString] = lpRows->aRow[i].lpProps[1].Value.ft;
- }
- }
- mpIterI = mpIcalEntries.cbegin();
- mpIterJ = mpSrvEntries.cbegin();
- //Iterate through entries and perform ADD, DELETE, Modify.
- while(1)
- {
- if (mpIterJ == mpSrvEntries.cend() && mpIterI == mpIcalEntries.cend())
- break;
-
- if (mpIcalEntries.cend() == mpIterI && mpSrvEntries.cend() != mpIterJ) {
- hr = HrDelMessage(mpIterJ->second, blCensorPrivate);
- if(hr != hrSuccess)
- {
- ec_log_err("Unable to Delete Message: 0x%08X", hr);
- goto exit;
- }
- ++mpIterJ;
- } else if (mpIcalEntries.cend() != mpIterI && mpSrvEntries.cend() == mpIterJ) {
- hr = HrAddMessage(lpICalToMapi, mpIterI->second);
- if(hr != hrSuccess)
- {
- ec_log_err("Unable to Add New Message: 0x%08X", hr);
- goto exit;
- }
- ++mpIterI;
- } else if (mpSrvEntries.cend() != mpIterJ && mpIcalEntries.cend() != mpIterI) {
- if(!mpIterI->first.compare(mpIterJ->first))
- {
- lpICalToMapi->GetItemInfo(mpIterI->second, &etype, &tLastMod, &sbEid);
- ftModTime = mpSrvTimes[mpIterJ->first];
- FileTimeToUnixTime(ftModTime, &tUnixModTime);
- if(tUnixModTime != tLastMod && etype == VEVENT)
- {
- hr = HrModify(lpICalToMapi, mpIterJ->second, mpIterI->second, blCensorPrivate);
- if(hr != hrSuccess)
- {
- ec_log_err("Unable to Modify Message: 0x%08X", hr);
- goto exit;
- }
- }
- ++mpIterI;
- ++mpIterJ;
- }
- else if( mpIterI->first.compare(mpIterJ->first) < 0 )
- {
- hr = HrAddMessage(lpICalToMapi, mpIterI->second);
- if(hr != hrSuccess)
- {
- ec_log_err("Unable to Add New Message: 0x%08X", hr);
- goto exit;
- }
- ++mpIterI;
- }
- else if(mpIterI->first.compare(mpIterJ->first) > 0 )
- {
- hr = HrDelMessage(mpIterJ->second, blCensorPrivate);
- if(hr != hrSuccess)
- {
- ec_log_err("Unable to Delete Message: 0x%08X", hr);
- goto exit;
- }
- ++mpIterJ;
- }
- }//else if
- }//while
- if(m_ulFolderFlag & DEFAULT_FOLDER)
- hr = HrPublishDefaultCalendar(m_lpSession, m_lpDefStore, time(NULL), FB_PUBLISH_DURATION);
- if(hr != hrSuccess) {
- hr = hrSuccess;
- ec_log_err("Error publishing freebusy for user %ls", m_wstrUser.c_str());
- }
- exit:
- if(hr == hrSuccess || hr == MAPI_E_INVALID_OBJECT)
- m_lpRequest->HrResponseHeader(200,"OK");
- else if (hr == MAPI_E_NO_ACCESS)
- m_lpRequest->HrResponseHeader(403,"Forbidden");
- else
- m_lpRequest->HrResponseHeader(500,"Internal Server Error");
- for (mpIterJ = mpSrvEntries.cbegin(); mpIterJ != mpSrvEntries.cend(); ++mpIterJ)
- MAPIFreeBuffer(mpIterJ->second.lpb);
- if(lpICalToMapi)
- delete lpICalToMapi;
- mpSrvEntries.clear();
- mpIcalEntries.clear();
- mpSrvTimes.clear();
- return hr;
- }
- /**
- * Edits the existing message in the folder
- *
- * @param[in] lpIcal2Mapi ical to mapi conversion object
- * @param[in] sbSrvEid EntryID of the message to be edited
- * @param[in] ulPos Position in the list of messages in conversion object
- * @param[in] blCensor boolean to block edit of private items
- * @return HRESULT
- * @retval MAPI_E_NO_ACCESS unable to edit private item
- */
- HRESULT iCal::HrModify( ICalToMapi *lpIcal2Mapi, SBinary sbSrvEid, ULONG ulPos, bool blCensor)
- {
- object_ptr<IMessage> lpMessage;
- ULONG ulObjType=0;
- ULONG ulTagPrivate = 0;
- ulTagPrivate = CHANGE_PROP_TYPE(m_lpNamedProps->aulPropTag[PROP_PRIVATE], PT_BOOLEAN);
- HRESULT hr = m_lpUsrFld->OpenEntry(sbSrvEid.cb, reinterpret_cast<ENTRYID *>(sbSrvEid.lpb),
- nullptr, MAPI_BEST_ACCESS, &ulObjType, &~lpMessage);
- if(hr != hrSuccess)
- return hr;
- if (blCensor && IsPrivate(lpMessage, ulTagPrivate))
- return MAPI_E_NO_ACCESS;
- hr = lpIcal2Mapi->GetItem(ulPos, 0, lpMessage);
- if(hr != hrSuccess)
- return hr;
- return lpMessage->SaveChanges(0);
- }
- /**
- * Creates a new message in the folder and sets its properties
- *
- * @param[in] lpIcal2Mapi ical to mapi conversion object
- * @param[in] ulPos the possition of the messasge in list
- * @return HRESULT
- */
- HRESULT iCal::HrAddMessage(ICalToMapi *lpIcal2Mapi, ULONG ulPos)
- {
- object_ptr<IMessage> lpMessage;
- HRESULT hr = m_lpUsrFld->CreateMessage(nullptr, 0, &~lpMessage);
- if (hr != hrSuccess)
- return hr;
- hr = lpIcal2Mapi->GetItem(ulPos, 0, lpMessage);
- if (hr != hrSuccess) {
- ec_log_err("Error creating a new calendar entry, error code: 0x%08X",hr);
- return hr;
- }
- hr = lpMessage->SaveChanges(0);
- if (hr != hrSuccess)
- ec_log_err("Error saving a new calendar entry, error code: 0x%08X",hr);
- return hr;
- }
- /**
- * Deletes the mapi message
- *
- * The message is moved to wastebasket(deleted items folder)
- *
- * @param[in] sbEid EntryID of the message to be deleted
- * @param[in] blCensor boolean to block delete of private messages
- *
- * @return HRESULT
- */
- HRESULT iCal::HrDelMessage(SBinary sbEid, bool blCensor)
- {
- memory_ptr<ENTRYLIST> lpEntryList;
- object_ptr<IMessage> lpMessage;
- ULONG ulObjType = 0;
- ULONG ulTagPrivate = 0;
-
- ulTagPrivate = CHANGE_PROP_TYPE(m_lpNamedProps->aulPropTag[PROP_PRIVATE], PT_BOOLEAN);
- HRESULT hr = MAPIAllocateBuffer(sizeof(ENTRYLIST), &~lpEntryList);
- if (hr != hrSuccess)
- {
- ec_log_err("Error allocating memory, error code: 0x%08X",hr);
- return hr;
- }
- lpEntryList->cValues = 1;
- hr = MAPIAllocateMore(sizeof(SBinary), lpEntryList, (void**)&lpEntryList->lpbin);
- if(hr != hrSuccess)
- {
- ec_log_err("Error allocating memory, error code: 0x%08X",hr);
- return hr;
- }
- hr = m_lpUsrFld->OpenEntry(sbEid.cb, reinterpret_cast<ENTRYID *>(sbEid.lpb), nullptr, MAPI_BEST_ACCESS, &ulObjType, &~lpMessage);
- if(hr != hrSuccess)
- return hr;
-
- if(blCensor && IsPrivate(lpMessage, ulTagPrivate))
- return hrSuccess; /* ignoring private items */
- lpEntryList->lpbin[0].cb = sbEid.cb;
- if ((hr = MAPIAllocateMore(sbEid.cb, lpEntryList, (void**)&lpEntryList->lpbin[0].lpb)) != hrSuccess)
- return hr;
- memcpy(lpEntryList->lpbin[0].lpb, sbEid.lpb, sbEid.cb);
-
- hr = m_lpUsrFld->DeleteMessages(lpEntryList, 0, NULL, MESSAGE_DIALOG);
- if(hr != hrSuccess)
- ec_log_err("Error while deleting a calendar entry, error code: 0x%08X",hr);
- return hr;
- }
- /**
- * Returns Table according to the entries requested.
- *
- * Restction is applied on table only when single calendar entry is requested
- * using http GET request, else all the calendar entries are sent.
- *
- * @param[out] lppTable Table containing rows of calendar entries as requested in URL.
- *
- * @return HRESULT
- * @retval MAPI_E_NOT_FOUND user's folder is not set in m_lpUsrFld
- */
- HRESULT iCal::HrGetContents(LPMAPITABLE *lppTable)
- {
- HRESULT hr = hrSuccess;
- std::string strUid;
- std::string strUrl;
- memory_ptr<SRestriction> lpsRestriction;
- MAPITablePtr ptrContents;
- static constexpr const SizedSPropTagArray(1, sPropEntryIdcol) = {1, {PR_ENTRYID}};
- ULONG ulRows = 0;
- if (m_lpUsrFld == nullptr)
- return MAPI_E_NOT_FOUND;
- hr = m_lpUsrFld->GetContentsTable(0, &~ptrContents);
- if (hr != hrSuccess) {
- ec_log_err("Error retrieving calendar entries, error code: 0x%08X",hr);
- return hr;
- }
- hr = ptrContents->SetColumns(sPropEntryIdcol, 0);
- if (hr != hrSuccess)
- return hr;
- m_lpRequest->HrGetUrl(&strUrl);
- strUid = StripGuid(strUrl);
- if (!strUid.empty()) {
- // single item requested
- hr = HrMakeRestriction(strUid, m_lpNamedProps, &~lpsRestriction);
- if (hr != hrSuccess)
- return hr;
- hr = ptrContents->Restrict(lpsRestriction, TBL_BATCH);
- if (hr != hrSuccess) {
- ec_log_err("Error restricting calendar entries, error code: 0x%08X",hr);
- return hr;
- }
- // single item not present, return 404
- hr = ptrContents->GetRowCount(0, &ulRows);
- if (hr != hrSuccess || ulRows != 1)
- return MAPI_E_NOT_FOUND;
- }
- return ptrContents->QueryInterface(IID_IMAPITable, (LPVOID*)lppTable);
- }
- /**
- * Converts mapi messages of the table into ical data
- *
- * @param[in] lpTable Table containing mapi messages
- * @param[in] blCensorPrivate Flag to censor private items while accessing shared folders
- * @param[out] lpstrIcal Pointer to string containing ical data of the mapi messages
- * @return HRESULT
- * @retval E_FAIL Error creating MapiToICal object
- */
- HRESULT iCal::HrGetIcal(IMAPITable *lpTable, bool blCensorPrivate, std::string *lpstrIcal)
- {
- HRESULT hr = hrSuccess;
- SBinary sbEid = {0,0};
- ULONG ulObjType = 0;
- ULONG ulTagPrivate = 0;
- ULONG ulFlag = 0;
- bool blCensor = false;
- std::unique_ptr<MapiToICal> lpMtIcal;
- std::string strical;
-
- ulTagPrivate = CHANGE_PROP_TYPE(m_lpNamedProps->aulPropTag[PROP_PRIVATE], PT_BOOLEAN);
-
- CreateMapiToICal(m_lpAddrBook, "utf-8", &unique_tie(lpMtIcal));
- if (lpMtIcal == NULL) {
- ec_log_err("Error Creating MapiToIcal object, error code: 0x%08X",hr);
- return E_FAIL;
- }
- while (TRUE)
- {
- rowset_ptr lpRows;
- hr = lpTable->QueryRows(50, 0, &~lpRows);
- if (hr != hrSuccess)
- {
- ec_log_err("Error retrieving table rows, error code: 0x%08X", hr);
- return hr;
- }
- if (lpRows->cRows == 0)
- break;
- for (ULONG i = 0; i < lpRows->cRows; ++i) {
- blCensor = blCensorPrivate; // reset censor flag for next message
- ulFlag = 0;
- if (lpRows->aRow[i].lpProps[0].ulPropTag != PR_ENTRYID)
- continue;
- sbEid = lpRows->aRow[i].lpProps[0].Value.bin;
- object_ptr<IMessage> lpMessage;
- hr = m_lpUsrFld->OpenEntry(sbEid.cb, (LPENTRYID)sbEid.lpb,
- nullptr, MAPI_BEST_ACCESS, &ulObjType, &~lpMessage);
- if (hr != hrSuccess)
- {
- ec_log_debug("Error opening message for ical conversion, error code: 0x%08X", hr);
- ec_log_debug("%d \n %s", sbEid.cb, bin2hex(sbEid.cb,sbEid.lpb).c_str());
- // Ignore error, just skip the message
- hr = hrSuccess;
- continue;
- }
-
- if(blCensor && IsPrivate(lpMessage, ulTagPrivate))
- ulFlag = M2IC_CENSOR_PRIVATE;
- else
- ulFlag = 0;
- hr = lpMtIcal->AddMessage(lpMessage, m_strSrvTz, ulFlag);
- if (hr != hrSuccess)
- {
- ec_log_debug("Error converting mapi message to ical, error code: 0x%08X", hr);
- // Ignore broken message
- hr = hrSuccess;
- }
- }
- }
-
- hr = lpMtIcal->Finalize(0, NULL, lpstrIcal);
- if (hr != hrSuccess)
- ec_log_debug("Unable to create ical output of calendar, error code 0x%08X", hr);
- return hr;
- }
- /**
- * Deletes the current selected folder (m_lpUsrFld)
- *
- * Used to delete folders created during publish operation in iCal.app,
- * the folder is moved to wastebasket(Deleted items folder)
- * Only user created folders can be deleted. Special folders which are
- * required by the model may not be deleted.
- *
- * @return HRESULT
- * @retval MAPI_E_NO_ACCESS insufficient permissions to delete folder
- */
- HRESULT iCal::HrDelFolder()
- {
- HRESULT hr = hrSuccess;
- memory_ptr<SPropValue> lpWstBoxEid, lpFldEid;
- object_ptr<IMAPIFolder> lpWasteBoxFld;
- ULONG ulObjType = 0;
- if (m_blFolderAccess == false) {
- hr = MAPI_E_NO_ACCESS;
- goto exit;
- }
- // Folder is not protected, so now we can move it to the wastebasket folder
- hr = HrGetOneProp(m_lpActiveStore, PR_IPM_WASTEBASKET_ENTRYID, &~lpWstBoxEid);
- if (hr != hrSuccess)
- goto exit;
- hr = m_lpActiveStore->OpenEntry(lpWstBoxEid->Value.bin.cb, reinterpret_cast<ENTRYID *>(lpWstBoxEid->Value.bin.lpb), nullptr, MAPI_MODIFY, &ulObjType, &~lpWasteBoxFld);
- if (hr != hrSuccess)
- {
- ec_log_err("Error opening \"Deleted items\" folder, error code: 0x%08X", hr);
- goto exit;
- }
- hr = HrGetOneProp(m_lpUsrFld, PR_ENTRYID, &~lpFldEid);
- if (hr != hrSuccess)
- goto exit;
- hr = m_lpIPMSubtree->CopyFolder(lpFldEid->Value.bin.cb, (LPENTRYID)lpFldEid->Value.bin.lpb, NULL, lpWasteBoxFld, NULL, 0, NULL, MAPI_MOVE);
- if (hr != hrSuccess)
- goto exit;
- exit:
- if (hr == hrSuccess)
- m_lpRequest->HrResponseHeader(200,"OK");
- else if (hr == MAPI_E_NO_ACCESS)
- m_lpRequest->HrResponseHeader(403,"Forbidden");
- else
- m_lpRequest->HrResponseHeader(500,"Internal Server Error");
- return hr;
- }
|