1 /*
2 ** Copyright 2003, Double Precision Inc.
3 **
4 ** See COPYING for distribution information.
5 */
6 #include "nntpxpat.H"
7 #include <sstream>
8
9 using namespace std;
10
XpatTaskCallback(mail::searchCallback * cb)11 mail::nntp::XpatTaskCallback::XpatTaskCallback(mail::searchCallback *cb)
12 : realCallback(cb)
13 {
14 }
15
~XpatTaskCallback()16 mail::nntp::XpatTaskCallback::~XpatTaskCallback()
17 {
18 }
19
success(std::string message)20 void mail::nntp::XpatTaskCallback::success(std::string message)
21 {
22 // Should NOT happen
23
24 fail(message);
25 }
26
fail(std::string message)27 void mail::nntp::XpatTaskCallback::fail(std::string message)
28 {
29 mail::searchCallback *cb=realCallback;
30
31 realCallback=NULL;
32
33 delete this;
34
35 cb->fail(message);
36 }
37
reportProgress(size_t bytesCompleted,size_t bytesEstimatedTotal,size_t messagesCompleted,size_t messagesEstimatedTotal)38 void mail::nntp::XpatTaskCallback::reportProgress(size_t bytesCompleted,
39 size_t bytesEstimatedTotal,
40
41 size_t messagesCompleted,
42 size_t messagesEstimatedTotal
43 )
44 {
45 realCallback->reportProgress(bytesCompleted, bytesEstimatedTotal,
46 messagesCompleted,
47 messagesEstimatedTotal);
48 }
49
50
XpatTask(XpatTaskCallback * cbArg,nntp & serverArg,string groupName,string hdrArg,string srchArg,bool searchNotArg,searchParams::Scope searchScopeArg,size_t rangeLoArg,size_t rangeHiArg)51 mail::nntp::XpatTask::XpatTask(XpatTaskCallback *cbArg,
52 nntp &serverArg, string groupName,
53 string hdrArg,
54 string srchArg, bool searchNotArg,
55 searchParams::Scope searchScopeArg,
56 size_t rangeLoArg, size_t rangeHiArg)
57 : GroupTask(cbArg, serverArg, groupName),
58 cb(cbArg),
59 hdr(hdrArg),
60 srch(srchArg),
61 searchNot(searchNotArg),
62 searchScope(searchScopeArg),
63 rangeLo(rangeLoArg),
64 rangeHi(rangeHiArg)
65 {
66 }
67
~XpatTask()68 mail::nntp::XpatTask::~XpatTask()
69 {
70 if (cb)
71 delete cb;
72 }
73
selectedGroup(msgnum_t estimatedCount,msgnum_t loArticleCount,msgnum_t hiArticleCount)74 void mail::nntp::XpatTask::selectedGroup(msgnum_t estimatedCount,
75 msgnum_t loArticleCount,
76 msgnum_t hiArticleCount)
77 {
78 response_func= &mail::nntp::XpatTask::processStatusResponse;
79
80 vector<mail::nntp::nntpMessageInfo>::iterator b, e;
81
82 b=myserver->index.begin();
83 e=myserver->index.end();
84
85 while (b != e)
86 {
87 b->msgFlag &= ~IDX_SEARCH;
88
89 ++b;
90 }
91
92 lastIdxMsgNum=myserver->index.begin();
93 ostringstream o;
94
95 o << "XPAT " << hdr << " " <<
96 (myserver->index.size() > 0 ?
97 myserver->index[0].msgNum:1) << "- *" << srch << "*\r\n";
98
99 myserver->socketWrite(o.str());
100
101 }
102
processGroup(const char * line)103 void mail::nntp::XpatTask::processGroup(const char *line)
104 {
105 (this->*response_func)(line);
106 }
107
processStatusResponse(const char * line)108 void mail::nntp::XpatTask::processStatusResponse(const char *line)
109 {
110 if (line[0] != '2')
111 {
112 done(line);
113 return;
114 }
115 response_func= &mail::nntp::XpatTask::processXpatResponse;
116 }
117
processXpatResponse(const char * l)118 void mail::nntp::XpatTask::processXpatResponse(const char *l)
119 {
120 if (*l == '.')
121 done("OK");
122
123 msgnum_t n;
124
125 istringstream i(l);
126
127 i >> n;
128
129 if (i.fail() || myserver->index.size() == 0)
130 return;
131
132 if (lastIdxMsgNum == myserver->index.end())
133 --lastIdxMsgNum;
134
135 for (;;)
136 {
137 if (lastIdxMsgNum->msgNum > n)
138 {
139 if (lastIdxMsgNum == myserver->index.begin())
140 break;
141 --lastIdxMsgNum;
142 if (lastIdxMsgNum->msgNum < n)
143 break;
144 continue;
145 }
146 else if (lastIdxMsgNum->msgNum < n)
147 {
148 if (++lastIdxMsgNum == myserver->index.end())
149 break;
150 if (lastIdxMsgNum->msgNum > n)
151 break;
152 }
153 else
154 {
155 myserver->index[lastIdxMsgNum
156 - myserver->index.begin()].msgFlag
157 |= IDX_SEARCH;
158 break;
159 }
160 }
161 }
162
done(const char * l)163 void mail::nntp::XpatTask::done(const char *l)
164 {
165 unsigned char Xor=0;
166 unsigned char Ror=0;
167
168 if (searchNot)
169 Xor=IDX_SEARCH;
170
171 switch (searchScope) {
172 case searchParams::search_all:
173 Ror=IDX_SEARCH;
174 break;
175
176 case searchParams::search_unmarked:
177 Xor |= IDX_FLAGGED;
178 break;
179
180 case searchParams::search_marked:
181 break;
182
183 case searchParams::search_range:
184 Ror=IDX_FLAGGED;
185 break;
186 }
187
188 vector<size_t> searchResults;
189
190 vector<nntpMessageInfo>::iterator bb,b, e;
191
192 bb=b=myserver->index.begin();
193 e=myserver->index.end();
194
195 if (searchScope == searchParams::search_range)
196 {
197 if (rangeHi > myserver->index.size())
198 rangeHi=myserver->index.size();
199
200 if (rangeLo > rangeHi)
201 rangeLo=rangeHi;
202
203 e= b + rangeHi;
204 b += rangeLo;
205 }
206
207 while (b != e)
208 {
209 unsigned char f= (b->msgFlag ^ Xor) | Ror;
210
211 if ((f & IDX_FLAGGED) && (f & IDX_SEARCH))
212 searchResults.push_back(b - bb);
213
214 ++b;
215
216 }
217
218 searchCallback *cbPat=cb->realCallback;
219
220 delete cb;
221 cb=NULL;
222 callbackPtr=NULL;
223
224 try {
225 Task::done();
226 } catch (...) {
227 cbPat->success(searchResults);
228 throw;
229 }
230 cbPat->success(searchResults);
231 }
232