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