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

# 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 118 void Poller::poll(bool nodelete, const string& file)
31 douglas 104 {
32 douglas 118 this->nodelete = nodelete;
33 douglas 119 this->file = file;
34    
35     load();
36    
37 douglas 121 ballots();
38     approvals();
39 douglas 119
40 douglas 121 save();
41 douglas 104 }
42 douglas 119
43     void Poller::load()
44     {
45     ifstream fin(file.c_str());
46     if (!fin.is_open())
47     {
48 douglas 123 fin.clear();
49    
50 douglas 119 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 douglas 123 while (fin.good())
77 douglas 119 {
78     enum { FIND, HELP, IMPROVE } type;
79     string vote;
80     unsigned count;
81     string text;
82    
83 douglas 123 fin.peek() != '_' ? getline(fin, vote, '=') : getline(fin, vote);
84 douglas 119 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 douglas 123 fin.peek();
112    
113 douglas 119 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 douglas 120 unsigned index;
206 douglas 119 ofstream fout(file.c_str());
207    
208 douglas 120 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 douglas 119
217 douglas 120 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 douglas 119 fout.close();
249     }
250 douglas 121
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 douglas 126 + "(Perl)\" SUBJECT \"Windows XP FAQ | Poll Ballot\" FROM \"Windows XP"
258     + " FAQ | Poll\"");
259 douglas 121
260 douglas 123 search.ignore(9);
261     search.peek();
262 douglas 121
263     while (search.good())
264     {
265     unsigned message;
266     search >> message;
267    
268     if (debug) cerr << "message = " << message << "\n";
269     messages.push(message);
270 douglas 123
271     search.get();
272     search.peek();
273 douglas 121 }
274    
275     if (!messages.empty())
276     {
277     unsigned message = messages.front();
278     messages.pop();
279    
280     ballot(message);
281     }
282 douglas 126
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 douglas 121 }
297    
298     void Poller::ballot(unsigned message)
299     {
300     cout << "Checking message: " << message << "..." << flush;
301    
302 douglas 123 ostringstream number;
303     number << message;
304 douglas 121
305     stringstream buffer;
306    
307 douglas 123 buffer << session->fetch(number.str() + " BODY.PEEK[2]");
308 douglas 121
309 douglas 126 if (session->successful() && session->fetch(number.str() + " FLAGS").find(
310     "\\Deleted") == string::npos)
311 douglas 121 {
312 douglas 123 buffer.ignore(string::npos, '\n');
313 douglas 121
314 douglas 123 bool approved = session->fetch(number.str() + " FLAGS").find("\\Flagge"
315     + string("d")) != string::npos;
316    
317     while (buffer.peek() != '\n' && buffer.good())
318 douglas 121 {
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 douglas 123 buffer.peek();
342    
343 douglas 121 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 douglas 123 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 douglas 126 submits.push_back(pair<string, string>("find", text));
386 douglas 123 }
387 douglas 121 }
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 douglas 123 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 douglas 126 submits.push_back(pair<string, string>("improve",
436     text));
437 douglas 123 }
438 douglas 121 }
439     break;
440     }
441     }
442    
443 douglas 123 session->store(number.str() + " +FLAGS (\\Deleted)");
444    
445 douglas 121 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 douglas 123 void Poller::submit(const string& type, const string& text)
462     {
463 douglas 125 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 douglas 123 }
500    
501 douglas 121 void Poller::approvals()
502     {
503 douglas 126 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 douglas 128 find.approve.erase(find.approve.begin() + (index - 1));
517 douglas 126 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 douglas 128 improve.approve.erase(improve.approve.begin() + (index - 1));
533 douglas 126 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 douglas 121 }
619 douglas 125
620 douglas 126 short Poller::approval(const string& type, const string& text)
621 douglas 125 {
622 douglas 126 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 douglas 125 }