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

# User Rev Content
1 douglas 104 // Windows XP FAQ Poll
2     //
3     // Douglas Thrift
4     //
5     // Poller.cpp
6    
7     #include "Poller.h"
8    
9     Poller::Poller()
10     {
11 douglas 118 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 douglas 104 }
21    
22 douglas 123 Poller::~Poller()
23     {
24     if (!nodelete)
25     {
26     session->expunge();
27     }
28     }
29    
30 douglas 219 void Poller::poll(bool nodelete, const string& file, bool approve)
31 douglas 104 {
32 douglas 118 this->nodelete = nodelete;
33 douglas 119 this->file = file;
34    
35     load();
36    
37 douglas 219 session->select('\"' + account.getMailbox() + '\"');
38 douglas 119
39 douglas 219 if (!approve)
40     {
41     ballots();
42     }
43     else
44     {
45     approvals();
46     }
47    
48 douglas 121 save();
49 douglas 104 }
50 douglas 119
51     void Poller::load()
52     {
53     ifstream fin(file.c_str());
54     if (!fin.is_open())
55     {
56 douglas 123 fin.clear();
57    
58 douglas 119 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 douglas 123 while (fin.good())
85 douglas 119 {
86     enum { FIND, HELP, IMPROVE } type;
87     string vote;
88     unsigned count;
89     string text;
90    
91 douglas 123 fin.peek() != '_' ? getline(fin, vote, '=') : getline(fin, vote);
92 douglas 119 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 douglas 129 if (fin.peek() == EOF) fin.get();
120 douglas 123
121 douglas 119 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 douglas 120 unsigned index;
214 douglas 119 ofstream fout(file.c_str());
215    
216 douglas 120 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 douglas 119
225 douglas 120 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 douglas 119 fout.close();
257     }
258 douglas 121
259     void Poller::ballots()
260     {
261     stringstream search;
262     search << session->search(string("ALL HEADER X-Mailer \"WinXPFAQPoll 1.0 ")
263 douglas 126 + "(Perl)\" SUBJECT \"Windows XP FAQ | Poll Ballot\" FROM \"Windows XP"
264     + " FAQ | Poll\"");
265 douglas 121
266 douglas 123 search.ignore(9);
267     search.peek();
268 douglas 121
269     while (search.good())
270     {
271     unsigned message;
272     search >> message;
273    
274     if (debug) cerr << "message = " << message << "\n";
275     messages.push(message);
276 douglas 123
277     search.get();
278     search.peek();
279 douglas 121 }
280    
281     if (!messages.empty())
282     {
283     unsigned message = messages.front();
284     messages.pop();
285    
286     ballot(message);
287     }
288 douglas 126
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 douglas 121 }
303    
304     void Poller::ballot(unsigned message)
305     {
306     cout << "Checking message: " << message << "..." << flush;
307    
308 douglas 123 ostringstream number;
309     number << message;
310 douglas 121
311     stringstream buffer;
312    
313 douglas 123 buffer << session->fetch(number.str() + " BODY.PEEK[2]");
314 douglas 121
315 douglas 126 if (session->successful() && session->fetch(number.str() + " FLAGS").find(
316     "\\Deleted") == string::npos)
317 douglas 121 {
318 douglas 123 buffer.ignore(string::npos, '\n');
319 douglas 121
320 douglas 123 bool approved = session->fetch(number.str() + " FLAGS").find("\\Flagge"
321     + string("d")) != string::npos;
322    
323     while (buffer.peek() != '\n' && buffer.good())
324 douglas 121 {
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 douglas 123 buffer.peek();
348    
349 douglas 121 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 douglas 123 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 douglas 126 submits.push_back(pair<string, string>("find", text));
392 douglas 123 }
393 douglas 121 }
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 douglas 123 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 douglas 126 submits.push_back(pair<string, string>("improve",
442     text));
443 douglas 123 }
444 douglas 121 }
445     break;
446     }
447     }
448    
449 douglas 123 session->store(number.str() + " +FLAGS (\\Deleted)");
450    
451 douglas 121 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 douglas 123 void Poller::submit(const string& type, const string& text)
468     {
469 douglas 125 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 douglas 123 }
506    
507 douglas 121 void Poller::approvals()
508     {
509 douglas 219 session->check();
510    
511 douglas 126 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 douglas 128 find.approve.erase(find.approve.begin() + (index - 1));
523 douglas 126 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 douglas 128 improve.approve.erase(improve.approve.begin() + (index - 1));
539 douglas 126 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 douglas 121 }
625 douglas 125
626 douglas 126 short Poller::approval(const string& type, const string& text)
627 douglas 125 {
628 douglas 126 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 douglas 125 }