Bincimap 2.0.16
Easy Imapping
Loading...
Searching...
No Matches
maildirmessage.cc
Go to the documentation of this file.
1
7#include <string>
8
9#include <stack>
10#include <fcntl.h>
11#include <unistd.h>
12#include <errno.h>
13#include <ctype.h>
14#include <time.h>
15#include <utime.h>
16
17#include "maildir.h"
18#include "maildirmessage.h"
19#include "convert.h"
20#include "mime.h"
21#include "iodevice.h"
22#include "iofactory.h"
23#include "mime-utils.h"
24#include "mime-inputsource.h"
25
26using namespace ::std;
27using namespace Binc;
28
29string Message::lastError;
30string MaildirMessage::storage;
31
32namespace {
33 //----------------------------------------------------------------------
34 void printOneHeader(IODevice &io, const MimePart *message,
35 const string &s_in, bool removecomments = true)
36 {
37 string tmp = "";
38 HeaderItem hitem;
39
40 if (message->h.getFirstHeader(s_in, hitem)) {
41 tmp = hitem.getValue();
42 io << toImapString(unfold(tmp, removecomments));
43 } else
44 io << "NIL";
45 }
46
47 //----------------------------------------------------------------------
48 void printOneAddressList(IODevice &io, const MimePart *message,
49 const string &s_in, bool removecomments = true)
50 {
51 string tmp = "";
52 HeaderItem hitem;
53
54 if (message->h.getFirstHeader(s_in, hitem)) {
55 tmp = hitem.getValue();
56 vector<string> addr;
57 splitAddr(unfold(tmp, removecomments), addr);
58 if (addr.size() != 0) {
59 io << "(";
60 for (vector<string>::const_iterator i = addr.begin();
61 i != addr.end(); ++i)
62
63 io << Address(*i).toParenList();
64 io << ")";
65 } else io << "NIL";
66 } else
67 io << "NIL";
68 }
69
70 //----------------------------------------------------------------------
71 void envelope(IODevice &io, const MimePart *message)
72 {
73 HeaderItem hitem;
74 io << "(";
75 printOneHeader(io, message, "date");
76 io << " ";
77 printOneHeader(io, message, "subject", false);
78 io << " ";
79 printOneAddressList(io, message, "from", false);
80 io << " ";
81 printOneAddressList(io, message,
82 message->h.getFirstHeader("sender", hitem)
83 ? "sender" : "from", false);
84 io << " ";
85 printOneAddressList(io, message,
86 message->h.getFirstHeader("reply-to", hitem)
87 ? "reply-to" : "from", false);
88 io << " ";
89 printOneAddressList(io, message, "to", false);
90 io << " ";
91 printOneAddressList(io, message, "cc", false);
92 io << " ";
93 printOneAddressList(io, message, "bcc", false);
94 io << " ";
95 printOneHeader(io, message, "in-reply-to");
96 io << " ";
97 printOneHeader(io, message, "message-id");
98 io << ")";
99 }
100
101 //----------------------------------------------------------------------
102 void bodyStructure(IODevice &io, const MimePart *message, bool extended)
103 {
104 HeaderItem hitem;
105 if (message->isMultipart() && message->members.size() > 0) {
106 io << "(";
107
108 for (vector<MimePart>::const_iterator i = message->members.begin();
109 i != message->members.end(); ++i)
110 bodyStructure(io, &(*i), extended);
111
112 io << " ";
113 io << toImapString(message->getSubType());
114
115 if (extended) {
116 io << " ";
117
118 vector<string> parameters;
119 vector<string> headers;
120 string tmp;
121
122 string type, subtype;
123
124 tmp = "";
125 if (message->h.getFirstHeader("content-type", hitem)) {
126 tmp = unfold(hitem.getValue());
127 trim(tmp);
128
129 vector<string> v;
130 split(tmp, ";", v);
131
132 for (vector<string>::const_iterator i = v.begin(); i != v.end(); ++i) {
133 string element = *i;
134 trim(element);
135 if (element.find('=') != string::npos) {
136 string::size_type pos = element.find('=');
137 string s = element.substr(0, pos);
138 string t = element.substr(pos + 1);
139 trim(s, " \"");
140 trim(t, " \"");
141 parameters.push_back(s);
142 parameters.push_back(t);
143 }
144 }
145
146 if (parameters.size() != 0) {
147 io << "(";
148 for (vector<string>::const_iterator i = parameters.begin();
149 i != parameters.end(); ++i) {
150 if (i != parameters.begin()) io << " ";
151 io << toImapString(*i);
152 }
153 io << ")";
154 } else
155 io << "NIL";
156 } else
157 io << "NIL";
158
159 // CONTENT-DISPOSITION
160 io << " ";
161 tmp = "";
162 if (message->h.getFirstHeader("content-disposition", hitem)) {
163 tmp = hitem.getValue();
164 trim(tmp);
165
166 vector<string> v;
167 split(tmp, ";", v);
168 if (v.size() > 0) {
169 string disp = v[0];
170 trim(disp);
171 io << "(" << toImapString(disp);
172 io << " ";
173 if (v.size() > 1) {
174 io << "(";
175 vector<string>::const_iterator i = v.begin();
176 ++i;
177 bool wrote = false;
178 while (i != v.end()) {
179 string s = *i;
180 trim(s);
181 string::size_type pos = s.find('=');
182 string key = s.substr(0, pos);
183 string value = s.substr(pos + 1);
184
185 trim(key);
186 trim(value);
187
188 trim(key, " \"");
189 trim(value, " \"");
190
191 if (!wrote) wrote = true;
192 else io << " ";
193
194 io << toImapString(key);
195 io << " ";
196 io << toImapString(value);
197
198 ++i;
199 }
200 io << ")";
201 } else
202 io << "NIL";
203 io << ")";
204 } else
205 io << "NIL";
206 } else
207 io << "NIL";
208
209 // CONTENT-LANGUAGE
210 io << " ";
211 printOneHeader(io, message, "content-language");
212 }
213 io << ")";
214 } else {
215 io << "(";
216
217 vector<string> parameters;
218 vector<string> headers;
219 string tmp;
220 tmp = "";
221 string type, subtype;
222
223 tmp = "";
224 if (message->h.getFirstHeader("content-type", hitem)) {
225 tmp = unfold(hitem.getValue());
226
227 vector<string> v;
228 split(tmp, ";", v);
229
230 if (v.size() > 0) {
231 vector<string> b;
232 split(v[0], "/", b);
233
234 if (b.size() > 0)
235 type = b[0];
236 else
237 type = "text";
238
239 if (b.size() > 1)
240 subtype = b[1];
241 else
242 subtype = "plain";
243 }
244
245 for (vector<string>::const_iterator i = v.begin(); i != v.end(); ++i) {
246 if (i == v.begin()) continue;
247 string element = *i;
248 trim(element);
249 if (element.find('=') != string::npos) {
250 string::size_type pos = element.find('=');
251 string s = element.substr(0, pos);
252 string t = element.substr(pos + 1);
253 trim(s, " \"");
254 trim(t, " \"");
255 parameters.push_back(s);
256 parameters.push_back(t);
257 }
258 }
259
260 } else {
261 type = "text";
262 subtype = "plain";
263 }
264
265 io << toImapString(type);
266 io << " ";
267 io << toImapString(subtype);
268
269 io << " ";
270 if (parameters.size() != 0) {
271 io << "(";
272 for (vector<string>::const_iterator i = parameters.begin();
273 i != parameters.end(); ++i) {
274 if (i != parameters.begin())
275 io << " ";
276 io << toImapString(*i);
277 }
278 io << ")";
279 } else
280 io << "NIL";
281
282 // CONTENT-ID
283 io << " ";
284 printOneHeader(io, message, "content-id");
285
286 // CONTENT-DESCRIPTION
287 io << " ";
288 printOneHeader(io, message, "content-description");
289
290 // CONTENT-TRANSFER-ENCODING
291 io << " ";
292 tmp = "";
293 if (message->h.getFirstHeader("content-transfer-encoding", hitem)) {
294 tmp = hitem.getValue();
295 trim(tmp);
296 io << toImapString(tmp);
297 } else
298 io << "\"7bit\"";
299 io << " ";
300
301 // Size of body in octets
302 io << message->getBodyLength();
303
304 lowercase(type);
305 if (type == "text") {
306 io << " ";
307 io << message->getNofBodyLines();
308 } else if (message->isMessageRFC822()) {
309 io << " ";
310 envelope(io, &message->members[0]);
311 io << " ";
312 bodyStructure(io, &message->members[0], extended);
313 io << " ";
314 io << message->getNofBodyLines();
315 }
316
317 // Extension data follows
318
319 if (extended) {
320 // CONTENT-MD5
321 io << " ";
322 printOneHeader(io, message, "content-md5");
323
324 // CONTENT-DISPOSITION
325 io << " ";
326 tmp = "";
327 if (message->h.getFirstHeader("content-disposition", hitem)) {
328 tmp = hitem.getValue();
329 trim(tmp);
330 vector<string> v;
331 split(tmp, ";", v);
332 if (v.size() > 0) {
333 string disp = v[0];
334 trim(disp);
335 io << "(" << toImapString(disp);
336 io << " ";
337 if (v.size() > 1) {
338 io << "(";
339 vector<string>::const_iterator i = v.begin();
340 ++i;
341 bool wrote = false;
342 while (i != v.end()) {
343 string s = *i;
344 trim(s);
345 string::size_type pos = s.find('=');
346 string key = s.substr(0, pos);
347 string value = s.substr(pos + 1);
348 trim(key);
349 trim(value);
350 trim(key, " \"");
351 trim(value, " \"");
352 if (!wrote) wrote = true;
353 else io << " ";
354 io << toImapString(key);
355 io << " ";
356 io << toImapString(value);
357 ++i;
358 }
359 io << ")";
360 } else
361 io << "NIL";
362 io << ")";
363 } else
364 io << "NIL";
365 } else
366 io << "NIL";
367
368 // CONTENT-LANGUAGE
369 io << " ";
370 printOneHeader(io, message, "content-language");
371
372 // CONTENT-LOCATION
373 io << " ";
374 printOneHeader(io, message, "content-location");
375 }
376
377 io << ")";
378 }
379 }
380}
381
382//------------------------------------------------------------------------
384 : fd(-1), doc(0), internalFlags(None), stdflags(F_NONE),
385 uid(0), size(0), unique(""), safeName(""), internaldate(0),
386 home(hom), customFlags(0)
387{
388}
389
390//------------------------------------------------------------------------
392 : fd(copy.fd), doc(copy.doc), internalFlags(copy.internalFlags),
393 stdflags(copy.stdflags), uid(copy.uid), size(copy.size),
394 unique(copy.unique), safeName(copy.safeName),
395 internaldate(copy.internaldate), home(copy.home)
396{
397 if (copy.customFlags) {
398 customFlags = new vector<string>;
399 *customFlags = *copy.customFlags;
400 } else {
401 customFlags = 0;
402 }
403}
404
405//------------------------------------------------------------------------
407{
408 delete customFlags;
409}
410
411//------------------------------------------------------------------------
413{
414 fd = copy.fd;
415 doc = copy.doc;
416 internalFlags = copy.internalFlags;
417 stdflags = copy.stdflags;
418 uid = copy.uid;
419 size = copy.size;
420 unique = copy.unique;
421 safeName = copy.safeName;
422 internaldate = copy.internaldate;
423 home = copy.home;
424
425 if (copy.customFlags) {
426 customFlags = new vector<string>;
427 *customFlags = *copy.customFlags;
428 } else {
429 customFlags = 0;
430 }
431
432 return *this;
433}
434
435//------------------------------------------------------------------------
437{
438 return uid < a.uid;
439}
440//------------------------------------------------------------------------
442{
443 if (fd != -1) {
444 if ((internalFlags & WasWrittenTo) && fsync(fd) != 0
445 && errno != EINVAL && errno != EROFS) {
446 // FIXME: report this error
447 }
448
449 if (::close(fd) != 0) {
450 // FIXME: report this error
451 }
452
453 fd = -1;
454 }
455
456 // The file will not be moved from tmp/ before this function has
457 // finished. So it's safe to assume that safeName is still valid.
458 if (internalFlags & WasWrittenTo) {
459 if (internaldate != 0) {
460 struct utimbuf tim = {internaldate, internaldate};
461 utime(safeName.c_str(), &tim);
462 } else {
463 time_t t = time(0);
464 struct utimbuf tim = {t, t};
465 utime(safeName.c_str(), &tim);
466 }
467
468 internalFlags &= ~WasWrittenTo;
469 }
470
471
472 if (doc) {
473 doc->clear();
474 delete doc;
475 doc = 0;
476 }
477}
478
479//------------------------------------------------------------------------
481{
482 internalFlags |= Expunged;
483}
484
485//------------------------------------------------------------------------
487{
488 internalFlags &= ~Expunged;
489}
490
491//------------------------------------------------------------------------
493{
494 internalFlags &= ~FlagsChanged;
495}
496
497//------------------------------------------------------------------------
499{
500 return (internalFlags & FlagsChanged) != 0;
501}
502
503//------------------------------------------------------------------------
504unsigned char MaildirMessage::getStdFlags(void) const
505{
506 return stdflags;
507}
508
509//------------------------------------------------------------------------
511{
512 return (internalFlags & Expunged) != 0;
513}
514
515//------------------------------------------------------------------------
516unsigned int MaildirMessage::getUID(void) const
517{
518 return uid;
519}
520
521//------------------------------------------------------------------------
522unsigned int MaildirMessage::getSize(bool render) const
523{
524 if (size == 0 && render) {
525 size = getDocSize();
526 home.mailboxchanged = true;
527 }
528
529 return size;
530}
531
532//------------------------------------------------------------------------
533const string &MaildirMessage::getUnique(void) const
534{
535 return unique;
536}
537
538//------------------------------------------------------------------------
540{
541 return internaldate;
542}
543
544//------------------------------------------------------------------------
546{
547 internaldate = t;
548}
549
550//------------------------------------------------------------------------
551void MaildirMessage::setStdFlag(unsigned char f_in)
552{
553 internalFlags |= FlagsChanged;
554 stdflags |= f_in;
555}
556
557//------------------------------------------------------------------------
559{
560 internalFlags |= FlagsChanged;
561 stdflags = F_NONE;
562}
563
564//------------------------------------------------------------------------
565void MaildirMessage::setUID(unsigned int i_in)
566{
567 uid = i_in;
568}
569
570//------------------------------------------------------------------------
571void MaildirMessage::setSize(unsigned int i_in)
572{
573 size = i_in;
574}
575
576//------------------------------------------------------------------------
577void MaildirMessage::setUnique(const string &s_in)
578{
579 unique = s_in;
580}
581
582//------------------------------------------------------------------------
584{
585 if (fd != -1)
586 return fd;
587
588 const string &id = getUnique();
589 MaildirIndexItem *item = home.index.find(id);
590 if (item) {
591 string fpath = home.path + "/cur/" + item->fileName;
592
593 unsigned int oflags = O_RDONLY;
594#ifdef HAVE_OLARGEFILE
595 oflags |= O_LARGEFILE;
596#endif
597 while ((fd = open(fpath.c_str(), oflags)) == -1) {
598 if (errno == ENOENT) {
599 struct stat st;
600 if (lstat(fpath.c_str(), &st) != -1) {
601 bincWarning << "dangling symlink: " << fpath << endl;
602 return -1;
603 }
604 } else {
605 bincWarning << "unable to open " << fpath << ": "
606 << strerror(errno) << endl;
607 return -1;
608 }
609
610 home.scanFileNames();
611 if ((item = home.index.find(id)) == 0)
612 break;
613 else
614 fpath = home.path + "/cur/" + item->fileName;
615 }
616
619
620 return fd;
621 }
622
623 return -1;
624}
625
626//------------------------------------------------------------------------
628{
629 this->fd = fd;
630}
631
632//------------------------------------------------------------------------
633void MaildirMessage::setSafeName(const string &name)
634{
635 safeName = name;
636}
637
638//------------------------------------------------------------------------
639const string &MaildirMessage::getSafeName(void) const
640{
641 return safeName;
642}
643
644//------------------------------------------------------------------------
646{
647 MaildirIndexItem *item = home.index.find(getUnique());
648 if (!item) {
649 home.scanFileNames();
650
651 if ((item = home.index.find(getUnique())) == 0)
652 return "";
653 }
654
655 return item->fileName;
656}
657
658//------------------------------------------------------------------------
660{
661 if (fd == -1) {
662 if ((fd = getFile()) == -1)
663 return -1;
664 }
665
666 char buffer[1024];
667 ssize_t readBytes = read(fd, buffer, (size_t) sizeof(buffer));
668 if (readBytes == -1) {
669 setLastError("Error reading from " + getFileName()
670 + ": " + string(strerror(errno)));
671 return -1;
672 }
673
674 chunk = string(buffer, readBytes);
675 return readBytes;
676}
677
678//------------------------------------------------------------------------
679bool MaildirMessage::appendChunk(const string &chunk)
680{
681 if (fd == -1) {
682 setLastError("Error writing to " + getSafeName()
683 + ": File is not open");
684 return false;
685 }
686
687 internalFlags |= WasWrittenTo;
688
689 string out;
690 for (string::const_iterator i = chunk.begin(); i != chunk.end(); ++i) {
691 const char c = *i;
692 if (c != '\r')
693 out += c;
694 }
695
696 ssize_t wroteBytes = 0;
697 for (;;) {
698 wroteBytes = write(fd, out.c_str(), (size_t) out.length());
699 if (wroteBytes == -1) {
700 if (errno == EINTR)
701 continue;
702 wroteBytes = 0;
703 }
704
705 break;
706 }
707
708 if (wroteBytes == (ssize_t) out.length())
709 return true;
710
711 setLastError("Error writing to " + getSafeName()
712 + ": " + string(strerror(errno)));
713 return false;
714}
715
716//------------------------------------------------------------------------
718{
721 if (ps == MaildirMessageCache::AllParsed && doc)
722 return true;
723
724 int fd = getFile();
725 if (fd == -1)
726 return false;
727
728 // FIXME: parse errors
729 if (!doc)
730 doc = new MimeDocument;
731 doc->parseFull(fd);
732
734
735 return true;
736}
737
738//------------------------------------------------------------------------
740{
744 || ps == MaildirMessageCache::HeaderParsed) && doc)
745 return true;
746
747 int fd = getFile();
748 if (fd == -1)
749 return false;
750
751 // FIXME: parse errors
752 if (!doc)
753 doc = new MimeDocument;
754 doc->parseOnlyHeader(fd);
755
757
758 return true;
759}
760
761//------------------------------------------------------------------------
762bool MaildirMessage::printBodyStructure(bool extended) const
763{
764 if (!parseFull())
765 return false;
766
767 bodyStructure(bincClient, doc, extended);
768 return true;
769}
770
771//------------------------------------------------------------------------
773{
774 if (!parseFull())
775 return false;
776
777 envelope(bincClient, doc);
778 return true;
779}
780
781//------------------------------------------------------------------------
782bool MaildirMessage::printHeader(const std::string &section,
783 std::vector<std::string> headers,
784 bool includeHeaders,
785 unsigned int startOffset,
786 unsigned int length,
787 bool mime) const
788{
789 bincClient << storage;
790 storage = "";
791 return true;
792}
793
794//------------------------------------------------------------------------
795unsigned int MaildirMessage::getHeaderSize(const std::string &section,
796 std::vector<std::string> headers,
797 bool includeHeaders,
798 unsigned int startOffset,
799 unsigned int length,
800 bool mime) const
801{
802 if (section == "") {
803 if (!parseHeaders())
804 return 0;
805 } else if (!parseFull())
806 return 0;
807
808 const MimePart *part = doc->getPart(section, "", mime ? MimePart::FetchMime
810 if (!part) {
811 storage = "";
812 return 0;
813 }
814
815 int fd = getFile();
816 if (fd == -1)
817 return 0;
818
819 storage = "";
820 part->printHeader(fd, bincClient, headers,
821 includeHeaders, startOffset,
822 length, storage);
823
824 return storage.size();
825}
826
827//------------------------------------------------------------------------
828bool MaildirMessage::printBody(const std::string &section,
829 unsigned int startOffset,
830 unsigned int length) const
831{
832 if (!parseFull())
833 return false;
834
835 const MimePart *part = doc->getPart(section, "");
836 if (!part) {
837 storage = "";
838 return 0;
839 }
840
841 int fd = getFile();
842 if (fd == -1)
843 return false;
844
845 storage = "";
846 part->printBody(fd, bincClient, startOffset, length);
847 return true;
848}
849
850//------------------------------------------------------------------------
851unsigned int MaildirMessage::getBodySize(const std::string &section,
852 unsigned int startOffset,
853 unsigned int length) const
854{
855 if (!parseFull())
856 return false;
857
858 const MimePart *part = doc->getPart(section, "");
859 if (!part) {
860 storage = "";
861 return 0;
862 }
863
864 if (startOffset > part->bodylength)
865 return 0;
866
867 unsigned int s = part->bodylength - startOffset;
868 return s < length ? s : length;
869}
870
871//------------------------------------------------------------------------
872bool MaildirMessage::printDoc(unsigned int startOffset,
873 unsigned int length, bool onlyText) const
874{
875 if (!parseFull())
876 return false;
877
878 int fd = getFile();
879 if (fd == -1)
880 return false;
881
882 if (onlyText)
883 startOffset += doc->bodystartoffsetcrlf;
884
885 storage = "";
886 doc->printDoc(fd, bincClient, startOffset, length);
887 return true;
888}
889
890//------------------------------------------------------------------------
891unsigned int MaildirMessage::getDocSize(unsigned int startOffset,
892 unsigned int length,
893 bool onlyText) const
894{
895 if (!parseFull())
896 return false;
897
898 unsigned int s = doc->size;
899 if (onlyText) s -= doc->bodystartoffsetcrlf;
900
901 if (startOffset > s)
902 return 0;
903
904 s -= startOffset;
905 return s < length ? s : length;
906}
907
908//------------------------------------------------------------------------
909bool MaildirMessage::headerContains(const std::string &header,
910 const std::string &text)
911{
912 if (!parseHeaders())
913 return false;
914
915 HeaderItem hitem;
916 if (!doc->h.getFirstHeader(header, hitem))
917 return false;
918
919 string tmp = hitem.getValue();
920 uppercase(tmp);
921 string tmp2 = text;
922 uppercase(tmp2);
923 return (tmp.find(tmp2) != string::npos);
924}
925
926//------------------------------------------------------------------------
927bool MaildirMessage::bodyContains(const std::string &text)
928{
929 if (!parseFull())
930 return false;
931
932 // search the body part of the message..
933 int fd = getFile();
934 if (fd == -1)
935 return false;
936
938
939 char c;
940 for (unsigned int i = 0; i < doc->getBodyStartOffset(); ++i)
941 if (!mimeSource.getChar(&c))
942 break;
943
944 char *ring = new char[text.length()];
945 int pos = 0;
946 int length = doc->getBodyLength();
947 const char *textStr = text.c_str();
948 unsigned int textLength = text.length();
949 while (mimeSource.getChar(&c) && length--) {
950 ring[pos % textLength] = toupper(c);
951
952 if (compareStringToQueue(textStr, ring, pos + 1, textLength)) {
953 delete[] ring;
954 return true;
955 }
956
957 ++pos;
958 }
959
960 delete[] ring;
961 return false;
962}
963
964//------------------------------------------------------------------------
965bool MaildirMessage::textContains(const std::string &text)
966{
967 // search the body part of the message..
968 int fd = getFile();
969 if (fd == -1)
970 return false;
971
973
974 char c;
975 char *ring = new char[text.length()];
976 int pos = 0;
977 const char *textStr = text.c_str();
978 unsigned int textLength = text.length();
979 while (mimeSource.getChar(&c)) {
980 ring[pos % textLength] = toupper(c);
981
982 if (compareStringToQueue(textStr, ring, pos + 1, textLength)) {
983 delete[] ring;
984 return true;
985 }
986
987 ++pos;
988 }
989
990 delete[] ring;
991 return false;
992}
993
994//------------------------------------------------------------------------
995const std::string &MaildirMessage::getHeader(const std::string &header)
996{
997 static string NIL = "";
998
999 if (!parseHeaders())
1000 return NIL;
1001
1002 HeaderItem hitem;
1003 if (!doc->h.getFirstHeader(header, hitem))
1004 return NIL;
1005
1006 return hitem.getValue();
1007}
1008
1009//------------------------------------------------------------------------
1010MaildirMessageCache::MaildirMessageCache(void)
1011{
1012}
1013
1014//------------------------------------------------------------------------
1016{
1017 clear();
1018}
1019
1020//------------------------------------------------------------------------
1022{
1023 static MaildirMessageCache cache;
1024 return cache;
1025}
1026
1027//------------------------------------------------------------------------
1029 ParseStatus s)
1030{
1031 if (statuses.find(m) == statuses.end()) {
1032 // Insert status. Perhaps remove oldest status.
1033 if (statuses.size() > 2) {
1034 MaildirMessage *message = const_cast<MaildirMessage *>(parsed.front());
1035
1036 removeStatus(message);
1037 }
1038
1039 parsed.push_back(m);
1040 }
1041
1042 statuses[m] = s;
1043}
1044
1045//------------------------------------------------------------------------
1048{
1049 if (statuses.find(m) == statuses.end())
1050 return NotParsed;
1051
1052 return statuses[m];
1053}
1054
1055//------------------------------------------------------------------------
1057{
1058 for (deque<const MaildirMessage *>::iterator i = parsed.begin();
1059 i != parsed.end(); ++i)
1060 const_cast<MaildirMessage *>(*i)->close();
1061
1062 parsed.clear();
1063 statuses.clear();
1064}
1065
1066//------------------------------------------------------------------------
1068{
1069 if (statuses.find(m) == statuses.end())
1070 return;
1071
1072 statuses.erase(statuses.find(m));
1073
1074 for (deque<const MaildirMessage *>::iterator i = parsed.begin();
1075 i != parsed.end(); ++i) {
1076 if (*i == m) {
1077 const_cast<MaildirMessage *>(*i)->close();
1078 parsed.erase(i);
1079 break;
1080 }
1081 }
1082}
1083
1084//------------------------------------------------------------------------
1086{
1087 internalFlags |= f;
1088}
1089
1090//------------------------------------------------------------------------
1091unsigned char MaildirMessage::getInternalFlags(void) const
1092{
1093 return internalFlags;
1094}
1095
1096//------------------------------------------------------------------------
1098{
1099 internalFlags &= ~f;
1100}
1101
1102//------------------------------------------------------------------------
1103void MaildirMessage::setCustomFlag(const string &flag)
1104{
1105 if (!customFlags) {
1106 internalFlags |= FlagsChanged | CustomFlagsChanged;
1107 customFlags = new vector<string>;
1108 }
1109
1110 for (vector<string>::const_iterator it = customFlags->begin();
1111 it != customFlags->end(); ++it) {
1112 if (*it == flag)
1113 return;
1114 }
1115
1116 internalFlags |= FlagsChanged | CustomFlagsChanged;
1117 customFlags->push_back(flag);
1118}
1119
1120//------------------------------------------------------------------------
1121void MaildirMessage::removeCustomFlag(const string &flag)
1122{
1123 internalFlags |= FlagsChanged | CustomFlagsChanged;
1124
1125 if (!customFlags)
1126 return;
1127
1128 for (vector<string>::iterator it = customFlags->begin();
1129 it != customFlags->end(); ++it) {
1130 if (*it == flag) {
1131 customFlags->erase(it);
1132 return;
1133 }
1134 }
1135}
1136
1137//------------------------------------------------------------------------
1139{
1140 internalFlags |= FlagsChanged | CustomFlagsChanged;
1141
1142 delete customFlags;
1143 customFlags = 0;
1144}
1145
1146//------------------------------------------------------------------------
1147vector<string> MaildirMessage::getCustomFlags(void) const
1148{
1149 if (!customFlags)
1150 return vector<string>();
1151
1152 return *customFlags;
1153}
std::string toParenList(void) const
Definition: address.cc:54
bool getFirstHeader(const std::string &key, HeaderItem &dest) const
Definition: mime.cc:89
const std::string & getValue(void) const
Definition: mime.h:23
The IODevice class provides a framework for reading and writing to device.
Definition: iodevice.h:31
bool scanFileNames(void) const
MaildirIndexItem * find(const std::string &unique)
Definition: maildir.cc:810
std::string fileName
Definition: maildir.h:34
void addStatus(const MaildirMessage *, ParseStatus pstat)
static MaildirMessageCache & getInstance(void)
void removeStatus(const MaildirMessage *)
ParseStatus getStatus(const MaildirMessage *) const
The MaildirMessage class provides an interface for IMAP messages.
bool printBody(const std::string &section="", unsigned int startOffset=0, unsigned int length=UINTMAX) const
void setUnique(const std::string &s_in)
void setInternalDate(time_t internaldate)
bool appendChunk(const std::string &chunk)
unsigned int getBodySize(const std::string &section, unsigned int startOffset=0, unsigned int length=UINTMAX) const
const std::string & getHeader(const std::string &header)
bool parseHeaders(void) const
unsigned char getInternalFlags(void) const
void setFlagsUnchanged(void)
std::vector< std::string > getCustomFlags(void) const
void setUID(unsigned int uid)
int getFile(void) const
bool printDoc(unsigned int startOffset=0, unsigned int length=UINTMAX, bool onlyText=false) const
void setCustomFlag(const std::string &flag)
bool printBodyStructure(bool extended=true) const
bool textContains(const std::string &text)
bool parseFull(void) const
bool printHeader(const std::string &section, std::vector< std::string > headers, bool includeHeaders=false, unsigned int startOffset=0, unsigned int length=UINTMAX, bool mime=false) const
bool bodyContains(const std::string &text)
bool printEnvelope(void) const
bool headerContains(const std::string &header, const std::string &text)
unsigned int getSize(bool determine=false) const
unsigned int getUID(void) const
const std::string & getSafeName(void) const
void setSize(unsigned int size)
unsigned int getDocSize(unsigned int startOffset=0, unsigned int length=UINTMAX, bool onlyText=false) const
MaildirMessage(Maildir &home)
void setSafeName(const std::string &name)
void setInternalFlag(unsigned char flags)
std::string getFileName(void) const
const std::string & getUnique(void) const
bool isExpunged(void) const
unsigned char getStdFlags(void) const
void clearInternalFlag(unsigned char flags)
void setStdFlag(unsigned char flags)
MaildirMessage & operator=(const MaildirMessage &copy)
unsigned int getHeaderSize(const std::string &section, std::vector< std::string > headers, bool includeHeaders=false, unsigned int startOffset=0, unsigned int length=UINTMAX, bool mime=false) const
int readChunk(std::string &chunk)
bool hasFlagsChanged(void) const
bool operator<(const MaildirMessage &a) const
void removeCustomFlag(const std::string &flag)
time_t getInternalDate(void) const
void setLastError(const std::string &) const
Definition: message.h:140
void parseFull(int fd) const
void clear(void) const
Definition: mime.cc:35
void parseOnlyHeader(int fd) const
bool isMessageRFC822(void) const
Definition: mime.h:79
void printBody(int fd, Binc::IODevice &output, unsigned int startoffset, unsigned int length) const
unsigned int getBodyStartOffset(void) const
Definition: mime.h:84
std::vector< MimePart > members
Definition: mime.h:75
unsigned int getNofBodyLines(void) const
Definition: mime.h:82
Header h
Definition: mime.h:73
void printHeader(int fd, Binc::IODevice &output, std::vector< std::string > headers, bool includeheaders, unsigned int startoffset, unsigned int length, std::string &storage) const
unsigned int getBodyLength(void) const
Definition: mime.h:83
unsigned int bodylength
Definition: mime.h:61
unsigned int bodystartoffsetcrlf
Definition: mime.h:60
bool isMultipart(void) const
Definition: mime.h:78
unsigned int size
Definition: mime.h:64
const MimePart * getPart(const std::string &findpart, std::string genpart, FetchType fetchType=FetchBody) const
Definition: mime-getpart.cc:23
const std::string & getSubType(void) const
Definition: mime.h:77
void printDoc(int fd, Binc::IODevice &output, unsigned int startoffset, unsigned int length) const
@ FetchHeader
Definition: mime.h:69
@ FetchMime
Definition: mime.h:70
Declaration of miscellaneous convertion functions.
Declaration of the IODevice class.
Declaration of the IOFactory class.
#define bincWarning
Definition: iofactory.h:44
#define bincClient
Definition: iofactory.h:31
Declaration of the Maildir class.
Declaration of the MaildirMessage class.
The base class of the MIME input source.
Binc::MimeInputSource * mimeSource
bool compareStringToQueue(const char *s_in, char *bqueue, int pos, int size)
Definition: mime-utils.h:17
Declaration of main mime parser components.
Definition: bincimapd.cc:9
std::string toImapString(const std::string &s_in)
Definition: convert.h:103
void splitAddr(const std::string &s_in, std::vector< std::string > &dest, bool skipempty=true)
Definition: convert.h:195
const std::string unfold(const std::string &a, bool removecomment=true)
Definition: convert.h:145
void split(const std::string &s_in, const std::string &delim, std::vector< std::string > &dest, bool skipempty=true)
Definition: convert.h:177
void uppercase(std::string &input)
Definition: convert.h:115
void lowercase(std::string &input)
Definition: convert.h:122
void trim(std::string &s_in, const std::string &chars=" \t\r\n")
Definition: convert.h:137