ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/trunk/WinXPFAQPoll/Poller.cpp
Revision: 230
Committed: 2003-08-05T19:01:05-07:00 (21 years, 10 months ago) by douglas
File size: 13719 byte(s)
Log Message:
Ack, messed up Cpanel IMAP Server and froofy sstream.ignore() function.

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
268 while (!isdigit(search.peek()) && search.good())
269 {
270 search.get();
271 }
272
273 while (search.good())
274 {
275 unsigned message;
276 search >> message;
277
278 if (debug) cerr << "message = " << message << "\n";
279 messages.push(message);
280
281 search.get();
282
283 while (!isdigit(search.peek()) && search.good())
284 {
285 search.get();
286 }
287 }
288
289 if (!messages.empty())
290 {
291 unsigned message = messages.front();
292 messages.pop();
293
294 ballot(message);
295 }
296
297 if (submits.size() > 0)
298 {
299 cout << "Sending submits..." << flush;
300
301 for (unsigned index = 0; index < submits.size(); index++)
302 {
303 submit(submits[index].first, submits[index].second);
304 }
305
306 submits.clear();
307
308 cout << "done.\n";
309 }
310 }
311
312 void Poller::ballot(unsigned message)
313 {
314 cout << "Checking message: " << message << "..." << flush;
315
316 ostringstream number;
317 number << message;
318
319 stringstream buffer;
320 string junk;
321
322 buffer << session->fetch(number.str() + " BODY.PEEK[2]");
323
324 if (session->successful() && buffer.str() == "* " + number.str() + " FETCH"
325 + " (BODY[2] \"\")\n")
326 {
327 do
328 {
329 getline(buffer, junk);
330 }
331 while (buffer.good());
332
333 buffer.clear();
334
335 buffer << session->fetch(number.str() + " BODY.PEEK[TEXT]");
336
337 for (unsigned index = 0; index < 25; index++)
338 {
339 getline(buffer, junk);
340 }
341 }
342
343 if (session->successful() && session->fetch(number.str() + " FLAGS").find(
344 "\\Deleted") == string::npos)
345 {
346 getline(buffer, junk);
347
348 bool approved = session->fetch(number.str() + " FLAGS").find("\\Flagge"
349 + string("d")) != string::npos;
350
351 while (buffer.peek() != '\n' && buffer.good())
352 {
353 enum { FIND, HELP, IMPROVE } type;
354 string vote;
355
356 getline(buffer, vote);
357 if (debug) cerr << "vote = " << vote << "\n";
358
359 if (vote == "_find_")
360 {
361 type = FIND;
362 continue;
363 }
364 else if (vote == "_help_")
365 {
366 type = HELP;
367 continue;
368 }
369 else if (vote == "_improve_")
370 {
371 type = IMPROVE;
372 continue;
373 }
374
375 buffer.peek();
376
377 switch (type)
378 {
379 case FIND:
380 if (vote == "reply")
381 {
382 find.reply++;
383 }
384 else if (vote == "news")
385 {
386 find.news++;
387 }
388 else if (vote == "sig")
389 {
390 find.sig++;
391 }
392 else if (vote == "search")
393 {
394 find.search++;
395 }
396 else if (vote == "link")
397 {
398 find.link++;
399 }
400 else if (vote == "browse")
401 {
402 find.browse++;
403 }
404 else if (vote == "other")
405 {
406 find.other++;
407
408 string text;
409 getline(buffer, text);
410
411 if (approved)
412 {
413 find.approved.push_back(text);
414 }
415 else
416 {
417 find.approve.push_back(text);
418
419 submits.push_back(pair<string, string>("find", text));
420 }
421 }
422 break;
423 case HELP:
424 if (vote == "solved")
425 {
426 help.solved++;
427 }
428 else if (vote == "note")
429 {
430 help.note++;
431 }
432 else if (vote == "link")
433 {
434 help.link++;
435 }
436 else if (vote == "news")
437 {
438 help.news++;
439 }
440 else if (vote == "lazy")
441 {
442 help.lazy++;
443 }
444 break;
445 case IMPROVE:
446 if (vote == "nothing")
447 {
448 improve.nothing++;
449 }
450 else if (vote == "links")
451 {
452 improve.links++;
453 }
454 else if (vote == "suggest")
455 {
456 improve.suggest++;
457
458 string text;
459 getline(buffer, text);
460
461 if (approved)
462 {
463 improve.approved.push_back(text);
464 }
465 else
466 {
467 improve.approve.push_back(text);
468
469 submits.push_back(pair<string, string>("improve",
470 text));
471 }
472 }
473 break;
474 }
475 }
476
477 session->store(number.str() + " +FLAGS (\\Deleted)");
478
479 cout << "done.\n";
480 }
481 else
482 {
483 cout << "cancelled.\n";
484 }
485
486 if (!messages.empty())
487 {
488 unsigned message = messages.front();
489 messages.pop();
490
491 ballot(message);
492 }
493 }
494
495 void Poller::submit(const string& type, const string& text)
496 {
497 ostringstream message;
498
499 message << "From: \"Windows XP FAQ | Poll\" <" << account.getEmail()
500 << ">\n"
501 << "To: \"" << account.getName() << "\" <" << account.getEmail()
502 << ">\n"
503 << "Subject: Windows XP FAQ | Poll Submit\n"
504 << "Content-Type: text/plain charset=\"us-ascii\"\n"
505 << "Content-Transfer-Encoding: 7bit\n"
506 << "X-Mailer: WinXPFAQPoll 1.0\n"
507 << "X-WinXPFAQPoll-Submit-Type: " << type << "\n"
508 << "X-WinXPFAQPoll-Submit-Text: " << text << "\n\n";
509
510 if (type == "find")
511 {
512 message << "How did you find this page?\n"
513 << " I arrived here by entirely different means:\n";
514 }
515 else if (type == "improve")
516 {
517 message << "How could I improve this site?\n"
518 << " I have my own completely insane suggestion:\n";
519 }
520
521 message << " " << text << "\n\n"
522 << "Flag this message to approve the voter\'s possibly objectionable\n"
523 << "input or delete it to disapprove.\n\n"
524 << "This message will be marked deleted when it is processed.\n";
525
526 ostringstream length;
527 length << (message.str().length() + 16);
528
529 session->append('\"' + account.getMailbox() + "\" {" + length.str() + '}',
530 message.str());
531
532 session->noop();
533 }
534
535 void Poller::approvals()
536 {
537 session->check();
538
539 unsigned index;
540
541 for (index = find.approve.size(); index > 0; index--)
542 {
543 cout << "Checking find: " << index << "..." << flush;
544
545 switch (approval("find", find.approve[index - 1]))
546 {
547 case true:
548 find.approved.push_back(find.approve[index - 1]);
549 case false:
550 find.approve.erase(find.approve.begin() + (index - 1));
551 break;
552 default:
553 break;
554 }
555 }
556
557 for (index = improve.approve.size(); index > 0; index--)
558 {
559 cout << "Checking improve: " << index << "..." << flush;
560
561 switch (approval("improve", improve.approve[index - 1]))
562 {
563 case true:
564 improve.approved.push_back(improve.approve[index - 1]);
565 case false:
566 improve.approve.erase(improve.approve.begin() + (index - 1));
567 break;
568 default:
569 break;
570 }
571 }
572
573 if (find.disapprove.size() > 0 || improve.disapprove.size() > 0)
574 {
575 cout << "Sending disapprovals..." << flush;
576
577 ostringstream message;
578
579 message << "From: \"Windows XP FAQ | Poll\" <" << account.getEmail()
580 << ">\n"
581 << "To: \"" << account.getName() << "\" <" << account.getEmail()
582 << ">\n"
583 << "Subject: Windows XP FAQ | Poll Disapprovals\n"
584 << "Content-Type: multipart/mixed;\n"
585 << " boundary=\"----=_NextPart_WinXPFAQPoll_0\"\n"
586 << "Content-Transfer-Encoding: 7bit\n"
587 << "X-Mailer: WinXPFAQPoll 1.0\n\n"
588 << "This is a multi-part message in MIME format.\n\n"
589 << "------=_NextPart_WinXPFAQPoll_0\n"
590 << "Content-Type: text/plain charset=\"us-ascii\"\n"
591 << "Content-Transfer-Encoding: 7bit\n\n"
592 << "Apparently these answers where disapproved:\n\n";
593
594 unsigned extra = 0;
595
596 for (index = 0; index < find.disapprove.size(); index++, extra += 4)
597 {
598 message << "How did you find this page?\n"
599 << " I arrived here by entirely different means:\n"
600 << " " << find.disapprove[index] << "\n\n";
601 }
602
603 for (index = 0; index < improve.disapprove.size(); index++, extra += 4)
604 {
605 message << "How could I improve this site?\n"
606 << " I have my own completely insane suggestion:\n"
607 << " " << improve.disapprove[index] << "\n\n";
608 }
609
610 message << "Make sure there were no errors.\n\n"
611 << "------=_NextPart_WinXPFAQPoll_0\n"
612 << "Content-Type: text/plain;\n"
613 << " name=\"disapprove.dat\"\n"
614 << "Content-Transfer-Encoding: 7bit\n"
615 << "Content-Disposition: attachment;\n"
616 << " filename=\"disapprove.dat\"\n\n";
617
618 if (find.disapprove.size() > 0)
619 {
620 message << "_find_\n";
621 extra++;
622 }
623
624 for (index = 0; index < find.disapprove.size(); index++, extra += 1)
625 {
626 message << find.disapprove[index] << "\n";
627 }
628
629 if (improve.disapprove.size() > 0)
630 {
631 message << "_improve_\n";
632 extra++;
633 }
634
635 for (index = 0; index < improve.disapprove.size(); index++, extra += 1)
636 {
637 message << improve.disapprove[index] << "\n";
638 }
639
640 message << "\n------=_NextPart_WinXPFAQPoll_0--\n";
641
642 ostringstream length;
643 length << (message.str().length() + 26 + extra);
644
645 session->append('\"' + account.getMailbox() + "\" {" + length.str() +
646 '}', message.str());
647
648 session->noop();
649
650 cout << "done.\n";
651 }
652 }
653
654 short Poller::approval(const string& type, const string& text)
655 {
656 short answer = -1;
657
658 stringstream search;
659 search << session->search(string("ALL HEADER X-Mailer \"WinXPFAQPoll 1.0")
660 + "\" SUBJECT \"Windows XP FAQ | Poll Submit\" FROM \"Windows XP FAQ |"
661 + " Poll\" HEADER X-WinXPFAQPoll-Submit-Type \"" + type + "\" HEADER X"
662 + "-WinXPFAQPoll-Submit-Text \"" + text + '\"');
663
664 search.ignore(9);
665 search.peek();
666
667 if (search.good())
668 {
669 unsigned message;
670 search >> message;
671
672 if (debug) cerr << "message = " << message << "\n";
673
674 ostringstream number;
675 number << message;
676
677 if (session->fetch(number.str() + " FLAGS").find("\\Deleted") !=
678 string::npos)
679 {
680 answer = false;
681 }
682 else if (session->fetch(number.str() + " FLAGS").find("\\Flagged") !=
683 string::npos)
684 {
685 answer = true;
686
687 session->store(number.str() + " +FLAGS (\\Deleted)");
688 }
689 }
690 else
691 {
692 answer = false;
693 }
694
695 switch (answer)
696 {
697 case true:
698 cout << "approved.\n";
699 break;
700 case false:
701 if (type == "find")
702 {
703 find.disapprove.push_back(text);
704 }
705 else if (type == "improve")
706 {
707 improve.disapprove.push_back(text);
708 }
709 cout << "disapproved.\n";
710 break;
711 default:
712 cout << "cancelled.\n";
713 break;
714 }
715
716 return answer;
717 }