1 /*
2 ** Copyright 2003, Double Precision Inc.
3 **
4 ** See COPYING for distribution information.
5 */
6 #include "nntpfetch.H"
7 #include <sstream>
8
9 using namespace std;
10
FetchTaskBase(mail::callback * callbackArg,nntp & myserverArg,std::string groupNameArg,size_t msgNumArg,std::string uidArg,mail::readMode getTypeArg)11 mail::nntp::FetchTaskBase::FetchTaskBase(mail::callback *callbackArg,
12 nntp &myserverArg,
13 std::string groupNameArg,
14 size_t msgNumArg,
15 std::string uidArg,
16 mail::readMode getTypeArg)
17 : GroupTask(callbackArg, myserverArg, groupNameArg),
18 msgNum(msgNumArg),
19 uid(uidArg),
20 getType(getTypeArg)
21 {
22 }
23
~FetchTaskBase()24 mail::nntp::FetchTaskBase::~FetchTaskBase()
25 {
26 }
27
selectedGroup(msgnum_t estimatedCount,msgnum_t loArticleCount,msgnum_t hiArticleCount)28 void mail::nntp::FetchTaskBase::selectedGroup(msgnum_t estimatedCount,
29 msgnum_t loArticleCount,
30 msgnum_t hiArticleCount)
31 {
32 response_func= &mail::nntp::FetchTaskBase::processStatusResponse;
33
34 if (!myserver->fixGenericMessageNumber(uid, msgNum))
35 {
36 fail("Invalid message number.");
37 return;
38 }
39
40 byteCount=0;
41 ostringstream o;
42
43 switch (getType) {
44 case mail::readContents:
45 o << "BODY ";
46 break;
47 case mail::readBoth:
48 o << "ARTICLE ";
49 break;
50 default:
51 o << "HEAD ";
52 }
53
54 o << myserver->index[msgNum].msgNum << "\r\n";
55
56 myserver->socketWrite(o.str());
57 }
58
processGroup(const char * cmd)59 void mail::nntp::FetchTaskBase::processGroup(const char *cmd)
60 {
61 (this->*response_func)(cmd);
62 }
63
processStatusResponse(const char * msg)64 void mail::nntp::FetchTaskBase::processStatusResponse(const char *msg)
65 {
66 if (msg[0] != '2')
67 {
68 ostringstream o;
69
70 o << "The following error occured while reading this article:\n"
71 "\n"
72 " " << msg << "\n\n";
73
74 fetchedText(o.str());
75 success("Ok");
76 return;
77 }
78
79 response_func= getType == mail::readHeadersFolded
80 ? &mail::nntp::FetchTaskBase::processFetchFoldedResponse:
81 &mail::nntp::FetchTaskBase::processFetchResponse;
82 foldedNewline=false;
83 }
84
processFetchResponse(const char * cmd)85 void mail::nntp::FetchTaskBase::processFetchResponse(const char *cmd)
86 {
87 if (strcmp(cmd, "."))
88 {
89 if (*cmd == '.')
90 ++cmd;
91
92 string s(cmd);
93
94 s += "\n";
95
96 byteCount += s.size();
97 if (callbackPtr)
98 callbackPtr->reportProgress(byteCount, 0, 0, 1);
99 fetchedText(s);
100 return;
101 }
102
103 if (callbackPtr)
104 callbackPtr->reportProgress(byteCount, byteCount, 0, 1);
105 success("Ok\n");
106 }
107
processFetchFoldedResponse(const char * cmd)108 void mail::nntp::FetchTaskBase::processFetchFoldedResponse(const char *cmd)
109 {
110 if (strcmp(cmd, "."))
111 {
112 if (*cmd == '.')
113 ++cmd;
114
115 if (*cmd && unicode_isspace((unsigned char)*cmd) &&
116 foldedNewline)
117 {
118 while (*cmd && unicode_isspace((unsigned char)*cmd))
119 cmd++;
120
121 string s(" ");
122 s += cmd;
123
124 byteCount += s.size();
125
126 if (callbackPtr)
127 callbackPtr->
128 reportProgress(byteCount, 0, 0, 1);
129 fetchedText(s);
130 }
131 else
132 {
133 string s;
134
135 if (foldedNewline)
136 s += "\n";
137 foldedNewline=true;
138 s += cmd;
139
140 byteCount += s.size();
141 if (callbackPtr)
142 callbackPtr->
143 reportProgress(byteCount, 0, 0, 1);
144 fetchedText(s);
145 }
146 return;
147 }
148 ++byteCount;
149
150 if (callbackPtr)
151 callbackPtr->reportProgress(byteCount, byteCount, 0, 1);
152
153 fetchedText("\n");
154 success("Ok");
155 }
156
157 //
158 // TaskBase is recyled by CacheTask, which also fetches a message's contents,
159 // but does not have a callback::message, because it goes into a temporary
160 // file. That's why we separate out callback::message-specific processing
161 // into a subclass.
162 //
163
FetchTask(callback::message * textCallbackArg,nntp & myserverArg,std::string groupNameArg,size_t msgNumArg,std::string uidArg,mail::readMode getType)164 mail::nntp::FetchTask::FetchTask(callback::message *textCallbackArg,
165 nntp &myserverArg,
166 std::string groupNameArg,
167 size_t msgNumArg,
168 std::string uidArg,
169 mail::readMode getType)
170 : FetchTaskBase(textCallbackArg, myserverArg,
171 groupNameArg,
172 msgNumArg,
173 uidArg,
174 getType),
175 textCallback(*textCallbackArg)
176 {
177 }
178
~FetchTask()179 mail::nntp::FetchTask::~FetchTask()
180 {
181 }
182
fetchedText(std::string s)183 void mail::nntp::FetchTask::fetchedText(std::string s)
184 {
185 textCallback.messageTextCallback(msgNum, s);
186 }
187