1 /*
2 ** Copyright 2002-2008, Double Precision Inc.
3 **
4 ** See COPYING for distribution information.
5 */
6 #include "libmail_config.h"
7 #include "addmessage.H"
8 #include "attachments.H"
9 #include <errno.h>
10 #include <cstring>
11 
12 using namespace std;
13 
14 class mail::addMessage::assembleImportHelper : public callback::message {
15 
16 	mail::addMessage *addMessagePtr;
17 	size_t &handleRet;
18 	mail::ptr<mail::account> acct;
19 	string msgUid;
20 	size_t msgNum;
21 	const mail::mimestruct &attachment;
22 	mail::callback &cb;
23 	FILE *tmpfp;
24 
25 	string headers;
26 
27 	// Imported from mail::callback::message:
28 	void messageTextCallback(size_t n, std::string text);
29 
30 	// Imported from mail::callback:
31 	void success(std::string message);
32 	void fail(std::string message);
33 
34 	void reportProgress(size_t bytesCompleted,
35 			    size_t bytesEstimatedTotal,
36 			    size_t messagesCompleted,
37 			    size_t messagesEstimatedTotal);
38 
39 public:
40 	assembleImportHelper(mail::addMessage *addMessagePtr,
41 			     size_t &handleRetArg,
42 			     mail::account *acctArg,
43 			     std::string msgUidArg,
44 			     size_t msgNumArg,
45 			     const mail::mimestruct &attachmentArg,
46 			     mail::callback &cbArg);
47 	~assembleImportHelper();
48 	void go();
49 };
50 
assembleImportAttachment(size_t & handleRet,mail::account * acct,std::string msgUid,const mail::mimestruct & attachment,mail::callback & cb)51 void mail::addMessage::assembleImportAttachment(size_t &handleRet,
52 						mail::account *acct,
53 						std::string msgUid,
54 						const mail::mimestruct &attachment,
55 						mail::callback &cb)
56 {
57 	size_t n=0;
58 	mail::addMessage::assembleImportHelper *h;
59 
60 	if (!mail::addMessage::chkMsgNum(acct, msgUid, n))
61 	{
62 		cb.fail("Message not found.");
63 		return;
64 	}
65 
66 	h=new mail::addMessage::assembleImportHelper(this,
67 						     handleRet, acct,
68 						     msgUid, n, attachment,
69 						     cb);
70 
71 	if (!h)
72 	{
73 		cb.fail(strerror(errno));
74 		return;
75 	}
76 
77 	try
78 	{
79 		h->go();
80 	} catch (...) {
81 		delete h;
82 		cb.fail(strerror(errno));
83 	}
84 }
85 
86 mail::addMessage::assembleImportHelper
assembleImportHelper(mail::addMessage * addMessagePtrArg,size_t & handleRetArg,mail::account * acctArg,std::string msgUidArg,size_t msgNumArg,const mail::mimestruct & attachmentArg,mail::callback & cbArg)87 ::assembleImportHelper(mail::addMessage *addMessagePtrArg,
88 		       size_t &handleRetArg,
89 		       mail::account *acctArg,
90 		       std::string msgUidArg,
91 		       size_t msgNumArg,
92 		       const mail::mimestruct &attachmentArg,
93 		       mail::callback &cbArg)
94 	: addMessagePtr(addMessagePtrArg),
95 	  handleRet(handleRetArg),
96 	  acct(acctArg),
97 	  msgUid(msgUidArg),
98 	  msgNum(msgNumArg),
99 	  attachment(attachmentArg),
100 	  cb(cbArg),
101 	  tmpfp(NULL)
102 {
103 }
104 
~assembleImportHelper()105 mail::addMessage::assembleImportHelper::~assembleImportHelper()
106 {
107 	if (tmpfp)
108 		fclose(tmpfp);
109 }
110 
go()111 void mail::addMessage::assembleImportHelper::go()
112 {
113 	acct->readMessageContent(msgNum, true, attachment,
114 				 mail::readHeaders,
115 				 *this);
116 
117 }
118 
messageTextCallback(size_t n,string text)119 void mail::addMessage::assembleImportHelper::messageTextCallback(size_t n,
120 								 string text)
121 {
122 	if (tmpfp == NULL)
123 	{
124 		// Reading headers.
125 		headers += text;
126 	}
127 	else
128 	{
129 		// Reading content
130 		if (fwrite(text.c_str(), text.size(), 1, tmpfp) != 1)
131 			; // Supress warning
132 	}
133 }
134 
success(string message)135 void mail::addMessage::assembleImportHelper::success(string message)
136 {
137 	if (tmpfp == NULL) // Just read headers, check for error, read body.
138 	{
139 		if (acct.isDestroyed() || !chkMsgNum(acct, msgUid, msgNum))
140 		{
141 			fail("Message not found.");
142 			return;
143 		}
144 		if ((tmpfp=tmpfile()) == NULL)
145 		{
146 			fail(strerror(errno));
147 			return;
148 		}
149 
150 		acct->readMessageContentDecoded(msgNum, true, attachment,
151 					       *this);
152 		return;
153 	}
154 
155 	// Just read the content.
156 
157 	if (fseek(tmpfp, 0L, SEEK_SET) < 0 || ferror(tmpfp))
158 	{
159 		fail(strerror(errno));
160 		return;
161 	}
162 
163 	string::iterator hstart, hend;
164 
165 	string encoding=
166 		mail::Attachment::find_header("CONTENT-TRANSFER-ENCODING:",
167 					      headers, hstart, hend);
168 
169 	if (hstart != hend)
170 		headers.erase(hstart, hend);
171 
172 	addMessagePtr->
173 		assembleContent(handleRet,
174 				mail::Attachment(headers, fileno(tmpfp), "",
175 						 encoding), cb);
176 	delete this;
177 }
178 
fail(string message)179 void mail::addMessage::assembleImportHelper::fail(string message)
180 {
181 	cb.fail(message);
182 	delete this;
183 }
184 
reportProgress(size_t bytesCompleted,size_t bytesEstimatedTotal,size_t messagesCompleted,size_t messagesEstimatedTotal)185 void mail::addMessage::assembleImportHelper::reportProgress(size_t bytesCompleted,
186 							    size_t bytesEstimatedTotal,
187 							    size_t messagesCompleted,
188 							    size_t messagesEstimatedTotal)
189 {
190 	cb.reportProgress(bytesCompleted,
191 			  bytesEstimatedTotal,
192 			  messagesCompleted,
193 			  messagesEstimatedTotal);
194 }
195