ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/trunk/WinXPFAQPoll/Poller.cpp
Revision: 128
Committed: 2003-04-03T20:59:00-08:00 (22 years, 2 months ago) by douglas
File size: 13190 byte(s)
Log Message:
Fixed some stuff to work right with GCC 3.1.

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