ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/trunk/WinXPFAQPoll/Poller.cpp
Revision: 231
Committed: 2003-08-05T20:36:00-07:00 (21 years, 10 months ago) by douglas
File size: 13686 byte(s)
Log Message:
Maybe it will work now!

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