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 231 by douglas, 2003-08-05T20:36:00-07: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, bool approve)
31 > {
32 >        this->nodelete = nodelete;
33 >        this->file = file;
34 >
35 >        load();
36 >
37 >        session->select('\"' + account.getMailbox() + '\"');
38 >
39 >        if (!approve)
40 >        {
41 >                ballots();
42 >        }
43 >        else
44 >        {
45 >                approvals();
46 >        }
47 >
48 >        save();
49 > }
50 >
51 > void Poller::load()
52 > {
53 >        ifstream fin(file.c_str());
54 >        if (!fin.is_open())
55 >        {
56 >                fin.clear();
57 >
58 >                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 >        while (fin.good())
85 >        {
86 >                enum { FIND, HELP, IMPROVE } type;
87 >                string vote;
88 >                unsigned count;
89 >                string text;
90 >
91 >                fin.peek() != '_' ? getline(fin, vote, '=') : getline(fin, vote);
92 >                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 >                if (fin.peek() == EOF) fin.get();
120 >
121 >                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 >        unsigned index;
214 >        ofstream fout(file.c_str());
215 >
216 >        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 >
225 >        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 >        fout.close();
257 > }
258 >
259 > void Poller::ballots()
260 > {
261 >        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 >
265 >        while (search.good())
266 >        {
267 >                char next = search.peek();
268 >
269 >                if (isdigit(next)) break;
270 >                
271 >                search.get();
272 >        }
273 >
274 >        while (search.good())
275 >        {
276 >                unsigned message;
277 >                search >> message;
278 >
279 >                if (debug) cerr << "message = " << message << "\n";
280 >                messages.push(message);
281 >
282 >                search.get();
283 >
284 >                while (!isdigit(search.peek()) && search.good())
285 >                {
286 >                        search.get();
287 >                }
288 >        }
289 >
290 >        if (!messages.empty())
291 >        {
292 >                unsigned message = messages.front();
293 >                messages.pop();
294 >
295 >                ballot(message);
296 >        }
297 >
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 > }
312 >
313 > void Poller::ballot(unsigned message)
314 > {
315 >        cout << "Checking message: " << message << "..." << flush;
316 >
317 >        ostringstream number;
318 >        number << message;
319 >
320 >        string junk;
321 >        istringstream buffer(session->fetch(number.str() + " BODY.PEEK[2]"));
322 >
323 >        if (session->successful() && buffer.str() == "* " + number.str() + " FETCH"
324 >                + " (BODY[2] \"\")\n")
325 >        {
326 >                buffer.str(session->fetch(number.str() + " BODY.PEEK[TEXT]"));
327 >
328 >                for (unsigned index = 0; index < 25; index++)
329 >                {
330 >                        getline(buffer, junk);
331 >                }
332 >        }
333 >
334 >        if (session->successful() && session->fetch(number.str() + " FLAGS").find(
335 >                "\\Deleted") == string::npos)
336 >        {
337 >                getline(buffer, junk);
338 >
339 >                bool approved = session->fetch(number.str() + " FLAGS").find("\\Flagge"
340 >                        + string("d")) != string::npos;
341 >
342 >                while (buffer.peek() != '\n' && buffer.good())
343 >                {
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 >                        buffer.peek();
367 >
368 >                        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 >                                        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 >                                                submits.push_back(pair<string, string>("find", text));
411 >                                        }
412 >                                }
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 >                                        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 >                                                submits.push_back(pair<string, string>("improve",
461 >                                                        text));
462 >                                        }
463 >                                }
464 >                                break;
465 >                        }
466 >                }
467 >
468 >                session->store(number.str() + " +FLAGS (\\Deleted)");
469 >
470 >                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 > void Poller::submit(const string& type, const string& text)
487 > {
488 >        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 > }
525 >
526 > void Poller::approvals()
527 > {
528 >        session->check();
529 >
530 >        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 >                        find.approve.erase(find.approve.begin() + (index - 1));
542 >                        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 >                        improve.approve.erase(improve.approve.begin() + (index - 1));
558 >                        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   }
644  
645 < void Poller::poll(bool nodelete)
645 > short Poller::approval(const string& type, const string& text)
646   {
647 <        //
647 >        short answer = -1;
648 >
649 >        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 >
654 >        while (search.good())
655 >        {
656 >                char next = search.peek();
657 >
658 >                if (isdigit(next)) break;
659 >                
660 >                search.get();
661 >        }
662 >
663 >        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   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines