ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/trunk/WinXPFAQPoll/Poller.cpp
Revision: 219
Committed: 2003-07-23T19:09:16-07:00 (21 years, 11 months ago) by douglas
File size: 13261 byte(s)
Log Message:
Separated the ballot counting and approval to decrease lossage.

File Contents

# Content
1 // Windows XP FAQ Poll
2 //
3 // Douglas Thrift
4 //
5 // Poller.cpp
6
7 #include "Poller.h"
8
9 Poller::Poller()
10 {
11 string mailbox = session->list("\"\" \"" + account.getMailbox() + "\"");
12
13 if (mailbox.find(account.getMailbox()) == string::npos)
14 {
15 cerr << program << ": Mailbox does not exist: " << account.getMailbox()
16 << "\n";
17
18 exit(1);
19 }
20 }
21
22 Poller::~Poller()
23 {
24 if (!nodelete)
25 {
26 session->expunge();
27 }
28 }
29
30 void Poller::poll(bool nodelete, const string& file, bool approve)
31 {
32 this->nodelete = nodelete;
33 this->file = file;
34
35 load();
36
37 session->select('\"' + account.getMailbox() + '\"');
38
39 if (!approve)
40 {
41 ballots();
42 }
43 else
44 {
45 approvals();
46 }
47
48 save();
49 }
50
51 void Poller::load()
52 {
53 ifstream fin(file.c_str());
54 if (!fin.is_open())
55 {
56 fin.clear();
57
58 ofstream fout(file.c_str());
59
60 fout << "_find_\n"
61 << "reply=0\n"
62 << "news=0\n"
63 << "sig=0\n"
64 << "search=0\n"
65 << "link=0\n"
66 << "browse=0\n"
67 << "other=0\n"
68 << "_help_\n"
69 << "solved=0\n"
70 << "note=0\n"
71 << "link=0\n"
72 << "news=0\n"
73 << "lazy=0\n"
74 << "_improve_\n"
75 << "nothing=0\n"
76 << "links=0\n"
77 << "suggest=0\n";
78
79 fout.close();
80
81 fin.open(file.c_str());
82 }
83
84 while (fin.good())
85 {
86 enum { FIND, HELP, IMPROVE } type;
87 string vote;
88 unsigned count;
89 string text;
90
91 fin.peek() != '_' ? getline(fin, vote, '=') : getline(fin, vote);
92 if (debug) cerr << "vote = " << vote << "\n";
93
94 if (vote == "_find_")
95 {
96 type = FIND;
97 continue;
98 }
99 else if (vote == "_help_")
100 {
101 type = HELP;
102 continue;
103 }
104 else if (vote == "_improve_")
105 {
106 type = IMPROVE;
107 continue;
108 }
109 else if (vote == "approved" || vote == "approve")
110 {
111 getline(fin, text);
112 }
113 else
114 {
115 fin >> count;
116 fin.get();
117 }
118
119 if (fin.peek() == EOF) fin.get();
120
121 switch (type)
122 {
123 case FIND:
124 if (vote == "reply")
125 {
126 find.reply = count;
127 }
128 else if (vote == "news")
129 {
130 find.news = count;
131 }
132 else if (vote == "sig")
133 {
134 find.sig = count;
135 }
136 else if (vote == "search")
137 {
138 find.search = count;
139 }
140 else if (vote == "link")
141 {
142 find.link = count;
143 }
144 else if (vote == "browse")
145 {
146 find.browse = count;
147 }
148 else if (vote == "other")
149 {
150 find.other = count;
151 }
152 else if (vote == "approved")
153 {
154 find.approved.push_back(text);
155 }
156 else if (vote == "approve")
157 {
158 find.approve.push_back(text);
159 }
160 break;
161 case HELP:
162 if (vote == "solved")
163 {
164 help.solved = count;
165 }
166 else if (vote == "note")
167 {
168 help.note = count;
169 }
170 else if (vote == "link")
171 {
172 help.link = count;
173 }
174 else if (vote == "news")
175 {
176 help.news = count;
177 }
178 else if (vote == "lazy")
179 {
180 help.lazy = count;
181 }
182 break;
183 case IMPROVE:
184 if (vote == "nothing")
185 {
186 improve.nothing = count;
187 }
188 else if (vote == "links")
189 {
190 improve.links = count;
191 }
192 else if (vote == "suggest")
193 {
194 improve.suggest = count;
195 }
196 else if (vote == "approved")
197 {
198 improve.approved.push_back(text);
199 }
200 else if (vote == "approve")
201 {
202 improve.approve.push_back(text);
203 }
204 break;
205 }
206 }
207
208 fin.close();
209 }
210
211 void Poller::save()
212 {
213 unsigned index;
214 ofstream fout(file.c_str());
215
216 fout << "_find_\n"
217 << "reply=" << find.reply << "\n"
218 << "news=" << find.news << "\n"
219 << "sig=" << find.sig << "\n"
220 << "search=" << find.search << "\n"
221 << "link=" << find.link << "\n"
222 << "browse=" << find.browse << "\n"
223 << "other=" << find.other << "\n";
224
225 for (index = 0; index < find.approved.size(); index++)
226 {
227 fout << "approved=" << find.approved[index] << "\n";
228 }
229
230 for (index = 0; index < find.approve.size(); index++)
231 {
232 fout << "approve=" << find.approve[index] << "\n";
233 }
234
235 fout << "_help_\n"
236 << "solved=" << help.solved << "\n"
237 << "note=" << help.note << "\n"
238 << "link=" << help.link << "\n"
239 << "news=" << help.news << "\n"
240 << "lazy=" << help.lazy << "\n"
241 << "_improve_\n"
242 << "nothing=" << improve.nothing << "\n"
243 << "links=" << improve.links << "\n"
244 << "suggest=" << improve.suggest << "\n";
245
246 for (index = 0; index < improve.approved.size(); index++)
247 {
248 fout << "approved=" << improve.approved[index] << "\n";
249 }
250
251 for (index = 0; index < improve.approve.size(); index++)
252 {
253 fout << "approve=" << improve.approve[index] << "\n";
254 }
255
256 fout.close();
257 }
258
259 void Poller::ballots()
260 {
261 stringstream search;
262 search << session->search(string("ALL HEADER X-Mailer \"WinXPFAQPoll 1.0 ")
263 + "(Perl)\" SUBJECT \"Windows XP FAQ | Poll Ballot\" FROM \"Windows XP"
264 + " FAQ | Poll\"");
265
266 search.ignore(9);
267 search.peek();
268
269 while (search.good())
270 {
271 unsigned message;
272 search >> message;
273
274 if (debug) cerr << "message = " << message << "\n";
275 messages.push(message);
276
277 search.get();
278 search.peek();
279 }
280
281 if (!messages.empty())
282 {
283 unsigned message = messages.front();
284 messages.pop();
285
286 ballot(message);
287 }
288
289 if (submits.size() > 0)
290 {
291 cout << "Sending submits..." << flush;
292
293 for (unsigned index = 0; index < submits.size(); index++)
294 {
295 submit(submits[index].first, submits[index].second);
296 }
297
298 submits.clear();
299
300 cout << "done.\n";
301 }
302 }
303
304 void Poller::ballot(unsigned message)
305 {
306 cout << "Checking message: " << message << "..." << flush;
307
308 ostringstream number;
309 number << message;
310
311 stringstream buffer;
312
313 buffer << session->fetch(number.str() + " BODY.PEEK[2]");
314
315 if (session->successful() && session->fetch(number.str() + " FLAGS").find(
316 "\\Deleted") == string::npos)
317 {
318 buffer.ignore(string::npos, '\n');
319
320 bool approved = session->fetch(number.str() + " FLAGS").find("\\Flagge"
321 + string("d")) != string::npos;
322
323 while (buffer.peek() != '\n' && buffer.good())
324 {
325 enum { FIND, HELP, IMPROVE } type;
326 string vote;
327
328 getline(buffer, vote);
329 if (debug) cerr << "vote = " << vote << "\n";
330
331 if (vote == "_find_")
332 {
333 type = FIND;
334 continue;
335 }
336 else if (vote == "_help_")
337 {
338 type = HELP;
339 continue;
340 }
341 else if (vote == "_improve_")
342 {
343 type = IMPROVE;
344 continue;
345 }
346
347 buffer.peek();
348
349 switch (type)
350 {
351 case FIND:
352 if (vote == "reply")
353 {
354 find.reply++;
355 }
356 else if (vote == "news")
357 {
358 find.news++;
359 }
360 else if (vote == "sig")
361 {
362 find.sig++;
363 }
364 else if (vote == "search")
365 {
366 find.search++;
367 }
368 else if (vote == "link")
369 {
370 find.link++;
371 }
372 else if (vote == "browse")
373 {
374 find.browse++;
375 }
376 else if (vote == "other")
377 {
378 find.other++;
379
380 string text;
381 getline(buffer, text);
382
383 if (approved)
384 {
385 find.approved.push_back(text);
386 }
387 else
388 {
389 find.approve.push_back(text);
390
391 submits.push_back(pair<string, string>("find", text));
392 }
393 }
394 break;
395 case HELP:
396 if (vote == "solved")
397 {
398 help.solved++;
399 }
400 else if (vote == "note")
401 {
402 help.note++;
403 }
404 else if (vote == "link")
405 {
406 help.link++;
407 }
408 else if (vote == "news")
409 {
410 help.news++;
411 }
412 else if (vote == "lazy")
413 {
414 help.lazy++;
415 }
416 break;
417 case IMPROVE:
418 if (vote == "nothing")
419 {
420 improve.nothing++;
421 }
422 else if (vote == "links")
423 {
424 improve.links++;
425 }
426 else if (vote == "suggest")
427 {
428 improve.suggest++;
429
430 string text;
431 getline(buffer, text);
432
433 if (approved)
434 {
435 improve.approved.push_back(text);
436 }
437 else
438 {
439 improve.approve.push_back(text);
440
441 submits.push_back(pair<string, string>("improve",
442 text));
443 }
444 }
445 break;
446 }
447 }
448
449 session->store(number.str() + " +FLAGS (\\Deleted)");
450
451 cout << "done.\n";
452 }
453 else
454 {
455 cout << "cancelled.\n";
456 }
457
458 if (!messages.empty())
459 {
460 unsigned message = messages.front();
461 messages.pop();
462
463 ballot(message);
464 }
465 }
466
467 void Poller::submit(const string& type, const string& text)
468 {
469 ostringstream message;
470
471 message << "From: \"Windows XP FAQ | Poll\" <" << account.getEmail()
472 << ">\n"
473 << "To: \"" << account.getName() << "\" <" << account.getEmail()
474 << ">\n"
475 << "Subject: Windows XP FAQ | Poll Submit\n"
476 << "Content-Type: text/plain charset=\"us-ascii\"\n"
477 << "Content-Transfer-Encoding: 7bit\n"
478 << "X-Mailer: WinXPFAQPoll 1.0\n"
479 << "X-WinXPFAQPoll-Submit-Type: " << type << "\n"
480 << "X-WinXPFAQPoll-Submit-Text: " << text << "\n\n";
481
482 if (type == "find")
483 {
484 message << "How did you find this page?\n"
485 << " I arrived here by entirely different means:\n";
486 }
487 else if (type == "improve")
488 {
489 message << "How could I improve this site?\n"
490 << " I have my own completely insane suggestion:\n";
491 }
492
493 message << " " << text << "\n\n"
494 << "Flag this message to approve the voter\'s possibly objectionable\n"
495 << "input or delete it to disapprove.\n\n"
496 << "This message will be marked deleted when it is processed.\n";
497
498 ostringstream length;
499 length << (message.str().length() + 16);
500
501 session->append('\"' + account.getMailbox() + "\" {" + length.str() + '}',
502 message.str());
503
504 session->noop();
505 }
506
507 void Poller::approvals()
508 {
509 session->check();
510
511 unsigned index;
512
513 for (index = find.approve.size(); index > 0; index--)
514 {
515 cout << "Checking find: " << index << "..." << flush;
516
517 switch (approval("find", find.approve[index - 1]))
518 {
519 case true:
520 find.approved.push_back(find.approve[index - 1]);
521 case false:
522 find.approve.erase(find.approve.begin() + (index - 1));
523 break;
524 default:
525 break;
526 }
527 }
528
529 for (index = improve.approve.size(); index > 0; index--)
530 {
531 cout << "Checking improve: " << index << "..." << flush;
532
533 switch (approval("improve", improve.approve[index - 1]))
534 {
535 case true:
536 improve.approved.push_back(improve.approve[index - 1]);
537 case false:
538 improve.approve.erase(improve.approve.begin() + (index - 1));
539 break;
540 default:
541 break;
542 }
543 }
544
545 if (find.disapprove.size() > 0 || improve.disapprove.size() > 0)
546 {
547 cout << "Sending disapprovals..." << flush;
548
549 ostringstream message;
550
551 message << "From: \"Windows XP FAQ | Poll\" <" << account.getEmail()
552 << ">\n"
553 << "To: \"" << account.getName() << "\" <" << account.getEmail()
554 << ">\n"
555 << "Subject: Windows XP FAQ | Poll Disapprovals\n"
556 << "Content-Type: multipart/mixed;\n"
557 << " boundary=\"----=_NextPart_WinXPFAQPoll_0\"\n"
558 << "Content-Transfer-Encoding: 7bit\n"
559 << "X-Mailer: WinXPFAQPoll 1.0\n\n"
560 << "This is a multi-part message in MIME format.\n\n"
561 << "------=_NextPart_WinXPFAQPoll_0\n"
562 << "Content-Type: text/plain charset=\"us-ascii\"\n"
563 << "Content-Transfer-Encoding: 7bit\n\n"
564 << "Apparently these answers where disapproved:\n\n";
565
566 unsigned extra = 0;
567
568 for (index = 0; index < find.disapprove.size(); index++, extra += 4)
569 {
570 message << "How did you find this page?\n"
571 << " I arrived here by entirely different means:\n"
572 << " " << find.disapprove[index] << "\n\n";
573 }
574
575 for (index = 0; index < improve.disapprove.size(); index++, extra += 4)
576 {
577 message << "How could I improve this site?\n"
578 << " I have my own completely insane suggestion:\n"
579 << " " << improve.disapprove[index] << "\n\n";
580 }
581
582 message << "Make sure there were no errors.\n\n"
583 << "------=_NextPart_WinXPFAQPoll_0\n"
584 << "Content-Type: text/plain;\n"
585 << " name=\"disapprove.dat\"\n"
586 << "Content-Transfer-Encoding: 7bit\n"
587 << "Content-Disposition: attachment;\n"
588 << " filename=\"disapprove.dat\"\n\n";
589
590 if (find.disapprove.size() > 0)
591 {
592 message << "_find_\n";
593 extra++;
594 }
595
596 for (index = 0; index < find.disapprove.size(); index++, extra += 1)
597 {
598 message << find.disapprove[index] << "\n";
599 }
600
601 if (improve.disapprove.size() > 0)
602 {
603 message << "_improve_\n";
604 extra++;
605 }
606
607 for (index = 0; index < improve.disapprove.size(); index++, extra += 1)
608 {
609 message << improve.disapprove[index] << "\n";
610 }
611
612 message << "\n------=_NextPart_WinXPFAQPoll_0--\n";
613
614 ostringstream length;
615 length << (message.str().length() + 26 + extra);
616
617 session->append('\"' + account.getMailbox() + "\" {" + length.str() +
618 '}', message.str());
619
620 session->noop();
621
622 cout << "done.\n";
623 }
624 }
625
626 short Poller::approval(const string& type, const string& text)
627 {
628 short answer = -1;
629
630 stringstream search;
631 search << session->search(string("ALL HEADER X-Mailer \"WinXPFAQPoll 1.0")
632 + "\" SUBJECT \"Windows XP FAQ | Poll Submit\" FROM \"Windows XP FAQ |"
633 + " Poll\" HEADER X-WinXPFAQPoll-Submit-Type \"" + type + "\" HEADER X"
634 + "-WinXPFAQPoll-Submit-Text \"" + text + '\"');
635
636 search.ignore(9);
637 search.peek();
638
639 if (search.good())
640 {
641 unsigned message;
642 search >> message;
643
644 if (debug) cerr << "message = " << message << "\n";
645
646 ostringstream number;
647 number << message;
648
649 if (session->fetch(number.str() + " FLAGS").find("\\Deleted") !=
650 string::npos)
651 {
652 answer = false;
653 }
654 else if (session->fetch(number.str() + " FLAGS").find("\\Flagged") !=
655 string::npos)
656 {
657 answer = true;
658
659 session->store(number.str() + " +FLAGS (\\Deleted)");
660 }
661 }
662 else
663 {
664 answer = false;
665 }
666
667 switch (answer)
668 {
669 case true:
670 cout << "approved.\n";
671 break;
672 case false:
673 if (type == "find")
674 {
675 find.disapprove.push_back(text);
676 }
677 else if (type == "improve")
678 {
679 improve.disapprove.push_back(text);
680 }
681 cout << "disapproved.\n";
682 break;
683 default:
684 cout << "cancelled.\n";
685 break;
686 }
687
688 return answer;
689 }