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

# 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 douglas 121
268 douglas 230 while (!isdigit(search.peek()) && search.good())
269     {
270     search.get();
271     }
272    
273 douglas 121 while (search.good())
274     {
275     unsigned message;
276     search >> message;
277    
278     if (debug) cerr << "message = " << message << "\n";
279     messages.push(message);
280 douglas 123
281     search.get();
282 douglas 230
283     while (!isdigit(search.peek()) && search.good())
284     {
285     search.get();
286     }
287 douglas 121 }
288    
289     if (!messages.empty())
290     {
291     unsigned message = messages.front();
292     messages.pop();
293    
294     ballot(message);
295     }
296 douglas 126
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 douglas 121 }
311    
312     void Poller::ballot(unsigned message)
313     {
314     cout << "Checking message: " << message << "..." << flush;
315    
316 douglas 123 ostringstream number;
317     number << message;
318 douglas 121
319     stringstream buffer;
320 douglas 230 string junk;
321 douglas 121
322 douglas 123 buffer << session->fetch(number.str() + " BODY.PEEK[2]");
323 douglas 121
324 douglas 230 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 douglas 126 if (session->successful() && session->fetch(number.str() + " FLAGS").find(
344     "\\Deleted") == string::npos)
345 douglas 121 {
346 douglas 230 getline(buffer, junk);
347 douglas 121
348 douglas 123 bool approved = session->fetch(number.str() + " FLAGS").find("\\Flagge"
349     + string("d")) != string::npos;
350    
351     while (buffer.peek() != '\n' && buffer.good())
352 douglas 121 {
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 douglas 123 buffer.peek();
376    
377 douglas 121 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 douglas 123 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 douglas 126 submits.push_back(pair<string, string>("find", text));
420 douglas 123 }
421 douglas 121 }
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 douglas 123 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 douglas 126 submits.push_back(pair<string, string>("improve",
470     text));
471 douglas 123 }
472 douglas 121 }
473     break;
474     }
475     }
476    
477 douglas 123 session->store(number.str() + " +FLAGS (\\Deleted)");
478    
479 douglas 121 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 douglas 123 void Poller::submit(const string& type, const string& text)
496     {
497 douglas 125 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 douglas 123 }
534    
535 douglas 121 void Poller::approvals()
536     {
537 douglas 219 session->check();
538    
539 douglas 126 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 douglas 128 find.approve.erase(find.approve.begin() + (index - 1));
551 douglas 126 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 douglas 128 improve.approve.erase(improve.approve.begin() + (index - 1));
567 douglas 126 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 douglas 121 }
653 douglas 125
654 douglas 126 short Poller::approval(const string& type, const string& text)
655 douglas 125 {
656 douglas 126 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 douglas 125 }