ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/proj/trunk/WinXPFAQPoll/Poller.cpp
(Generate patch)

Comparing trunk/WinXPFAQPoll/Poller.cpp (file contents):
Revision 104 by douglas, 2003-03-31T20:18:26-08:00 vs.
Revision 129 by douglas, 2003-04-03T21:13:24-08:00

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines