diff options
| author | Sam Varshavchik | 2013-08-19 16:39:41 -0400 | 
|---|---|---|
| committer | Sam Varshavchik | 2013-08-25 14:43:51 -0400 | 
| commit | 9c45d9ad13fdf439d44d7443ae75da15ea0223ed (patch) | |
| tree | 7a81a04cb51efb078ee350859a64be2ebc6b8813 /libmail/addmessageremoveattachments.C | |
| parent | a9520698b770168d1f33d6301463bb70a19655ec (diff) | |
| download | courier-libs-9c45d9ad13fdf439d44d7443ae75da15ea0223ed.tar.bz2 | |
Initial checkin
Imported from subversion report, converted to git. Updated all paths in
scripts and makefiles, reflecting the new directory hierarchy.
Diffstat (limited to 'libmail/addmessageremoveattachments.C')
| -rw-r--r-- | libmail/addmessageremoveattachments.C | 404 | 
1 files changed, 404 insertions, 0 deletions
| diff --git a/libmail/addmessageremoveattachments.C b/libmail/addmessageremoveattachments.C new file mode 100644 index 0000000..650058e --- /dev/null +++ b/libmail/addmessageremoveattachments.C @@ -0,0 +1,404 @@ +/* +** Copyright 2004-2008, Double Precision Inc. +** +** See COPYING for distribution information. +*/ +#include "libmail_config.h" +#include "addmessage.H" +#include "attachments.H" +#include "headers.H" +#include <errno.h> +#include <vector> +#include <cstring> + +using namespace std; + +class mail::addMessage::assembleRemoveAttachmentsHelper +	: public mail::callback::message { + +public: +	void doNextCopy(std::string message); + + +private: +	// Imported from mail::callback: +	void success(std::string message); +	void fail(std::string message); + +	void reportProgress(size_t bytesCompleted, +			    size_t bytesEstimatedTotal, +			    size_t messagesCompleted, +			    size_t messagesEstimatedTotal); +	void messageTextCallback(size_t n, std::string text); + +	size_t &handleRet; +	mail::ptr<mail::account> acct; +	string msgUid; +	size_t msgNum; + +	mail::addMessage *add; +	mail::callback &origCallback; + +	void (assembleRemoveAttachmentsHelper::*success_func)(std::string); +	void doMultiPart(std::string message); + +	string collectedHeaders; + +public: +	assembleRemoveAttachmentsHelper(size_t &handleRetArg, +					mail::account *acctArg, +					string msgUidArg, +					mail::addMessage *addArg, +					mail::callback &origCallbackArg) +		: handleRet(handleRetArg), +		  acct(acctArg), +		  msgUid(msgUidArg), +		  msgNum(0), +		  add(addArg), +		  origCallback(origCallbackArg) +	{ +	} + +	~assembleRemoveAttachmentsHelper() {} + + +	// We get a message's MIME structure, and the MIME ids of attachments +	// to remove.  Create a tree structure for each MIME section with +	// two data points: +	// +	// A) Whether or not either this MIME section should be copied, or +	//    at least one of the MIME subsections should be copied +	// +	// B) Whether or not either this MIME section should not be copied, or +	//    at least one of the MIME subsections should not be copied +	// +	class mimeAction; + +	class mimeAction { +	public: +		const mail::mimestruct §ion; + +		bool somethingCopied; +		bool somethingNotCopied; + +		// +		// The list of MIME actions is built into a list +		// (so we don't need to manually allocate these objects), +		// and the MIME subsections are saved in the following +		// vector of iterators to the subsection of this section + +		vector< list<mimeAction>::iterator > subsections; +		size_t handleId; + +		mimeAction(const mail::mimestruct §ionArg, bool a, bool b) +			: section(sectionArg), somethingCopied(a), +			  somethingNotCopied(b) {} + +		~mimeAction() {} +	}; + +	list<mimeAction> parseTree; + +	list<mimeAction>::iterator +	computeToCopy(const mail::mimestruct §ion, +		      const set<string> &whatNotToCopy); // Compute parseTree + +	// +	// Now, iterate over the parse tree, and create the execution plan +	// of things to copy. +	// + +	class plan { +	public: +		bool multiPartCopy; +		list<mimeAction>::iterator whichPart; + +		plan(bool multipartCopyArg, +		     list<mimeAction>::iterator whichPartArg) +			: multiPartCopy(multipartCopyArg), +			  whichPart(whichPartArg) +		{ +		} + +		~plan() {} +	}; + + +	vector< plan > copyPlan; +	vector< plan >::iterator ToDo; + +	void computePlan( list<mimeAction>::iterator ); +}; + +#define MIMEACTION mail::addMessage::assembleRemoveAttachmentsHelper::mimeAction + +list<MIMEACTION>::iterator +mail::addMessage::assembleRemoveAttachmentsHelper +::computeToCopy(const mail::mimestruct §ion, +		const set<string> &whatNotToCopy) +{ +	list<MIMEACTION>::iterator p; + +	if (whatNotToCopy.count(section.mime_id) > 0) +	{ +		parseTree.push_back(MIMEACTION(section, false, true)); +		p=parseTree.end(); +		return --p; +	} + +	size_t n=section.getNumChildren(); + +	if (n == 0) +	{ +		// Copy this one, by default + +		parseTree.push_back(MIMEACTION(section, true, false)); +		p=parseTree.end(); +		return --p; +	} + +	vector< list<MIMEACTION>::iterator > subsections; + +	size_t i; + +	bool somethingCopied=false; +	bool somethingNotCopied=false; + +	for (i=0; i<n; i++) +	{ +		p=computeToCopy(*section.getChild(i), whatNotToCopy); + +		if (p->somethingNotCopied) +			somethingNotCopied=true; + +		if (!p->somethingCopied) +			continue; + +		somethingCopied=true; +		subsections.push_back(p); +	} + +	parseTree.push_back(MIMEACTION(section, somethingCopied, +				       somethingNotCopied)); + +	p=parseTree.end(); +	--p; + +	p->subsections=subsections; +	return p; +} + + +void mail::addMessage::assembleRemoveAttachmentsHelper +::computePlan(list<MIMEACTION>::iterator nodeArg) +{ +	if (!nodeArg->somethingCopied) +		return; // Skip this entire MIME section + +	if (!nodeArg->somethingNotCopied) +	{ +		copyPlan.push_back(plan(false, nodeArg)); +		// Copy this entire section, multipart or not +		return; +	} + +	size_t i, n= nodeArg->subsections.size(); + +	for (i=0; i<n; i++) +		computePlan(nodeArg->subsections[i]); + +	copyPlan.push_back(plan(true, nodeArg)); +} + +void mail::addMessage +::assembleRemoveAttachmentsFrom(size_t &handleRetArg, +				mail::account *acctArg, +				string msgUidArg, +				const mail::mimestruct &msgStructArg, +				const set<string> &removeUidListArg, +				mail::callback &cbArg) +{ +	assembleRemoveAttachmentsHelper *helper= +		new assembleRemoveAttachmentsHelper(handleRetArg, +						    acctArg, +						    msgUidArg, +						    this, +						    cbArg); + +	if (!helper) +	{ +		cbArg.fail(strerror(errno)); +		return; +	} + +	try { +		list<MIMEACTION>::iterator topNode; + +		topNode=helper->computeToCopy(msgStructArg, removeUidListArg); + +		if (!topNode->somethingCopied) +		{ +			delete helper; +			helper=NULL; +			cbArg.fail("Cannot remove every attachment."); +			return; +		} + +		if (!topNode->somethingNotCopied) +		{ +			delete helper; +			helper=NULL; +			cbArg.fail("No attachments selected for deletion"); +			return; +		} +		helper->computePlan(topNode); +		helper->ToDo=helper->copyPlan.begin(); +		helper->doNextCopy("Ok."); // Kick into action. +	} catch (...) +	{ +		if (helper) +			delete helper; +		cbArg.fail(strerror(errno)); +	} +} + +void mail::addMessage +::assembleRemoveAttachmentsHelper::success(std::string message) +{ +	(this->*success_func)(message); +} + +void mail::addMessage +::assembleRemoveAttachmentsHelper::doNextCopy(std::string message) +{ +	origCallback.reportProgress(0, 0, ToDo-copyPlan.begin()+1, +				    copyPlan.size()); + +	if (ToDo == copyPlan.end()) +	{ +		try { +			--ToDo; +			handleRet=ToDo->whichPart->handleId; + +			origCallback.success(message); +		} catch (...) +		{ +			delete this; +			throw; +		} +		delete this; +		return; +	} + +	if (acct.isDestroyed()) +	{ +		fail("Server connection terminated."); +		return; +	} + +	if (!chkMsgNum(acct, msgUid, msgNum)) +	{ +		fail("Message deleted in the middle of being copied."); +		return; +	} + +	plan &toDoNext= *ToDo; +	mimeAction &toDoInfo= *toDoNext.whichPart; + +	if (toDoNext.multiPartCopy) +	{ +		collectedHeaders=""; +		success_func= &assembleRemoveAttachmentsHelper::doMultiPart; + +		acct->readMessageContent(msgNum, true, +					 toDoInfo.section, +					 readHeaders, *this); +		return; +	} + +	++ToDo; +	success_func= &assembleRemoveAttachmentsHelper::doNextCopy; + +	add->assembleImportAttachment(toDoInfo.handleId, acct, msgUid, +				      toDoInfo.section, +				      *this); +} + +void mail::addMessage +::assembleRemoveAttachmentsHelper::doMultiPart(std::string message) +{ +	if (acct.isDestroyed()) +	{ +		fail("Server connection terminated."); +		return; +	} + +	plan &toDoNext= *ToDo; +	mimeAction &toDoInfo= *toDoNext.whichPart; + +	vector<size_t> parts; + +	vector< list<mimeAction>::iterator >::iterator b, e; + +	for (b=toDoInfo.subsections.begin(), +		     e=toDoInfo.subsections.end(); b != e; ++b) +		parts.push_back( (*b)->handleId ); + +	string::iterator hstart, hend; + +	string encoding= +		mail::Attachment::find_header("CONTENT-TRANSFER-ENCODING:", +					      collectedHeaders, hstart, hend); + +	if (hstart != hend) +		collectedHeaders.erase(hstart, hend); + +	string content_type_header= +		mail::Attachment::find_header("CONTENT-TYPE:", +					      collectedHeaders, hstart, hend); + +	mail::Header::mime ct= +		mail::Header::mime::fromString(string(hstart, hend)); +	if (hstart != hend) +		collectedHeaders.erase(hstart, hend); + +	++ToDo; +	success_func= &assembleRemoveAttachmentsHelper::doNextCopy; + +	add->assembleMultipart(toDoInfo.handleId, collectedHeaders, +			       parts, +			       ct.value, +			       ct.parameters, +			       *this); +} + +void mail::addMessage +::assembleRemoveAttachmentsHelper::fail(std::string message) +{ +	try { +		origCallback.fail(strerror(errno)); +	} catch (...) +	{ +		delete this; +		throw; +	} +	delete this; +} + +void mail::addMessage +::assembleRemoveAttachmentsHelper::reportProgress(size_t bytesCompleted, +						  size_t bytesEstimatedTotal, +						  size_t messagesCompleted, +						  size_t messagesEstimatedTotal) +{ +	origCallback.reportProgress(bytesCompleted, bytesEstimatedTotal, +				    ToDo-copyPlan.begin(), +				    copyPlan.size()); +} + +void mail::addMessage +::assembleRemoveAttachmentsHelper::messageTextCallback(size_t n, +						       std::string text) +{ +	collectedHeaders += text; +} | 
