1 /*
2 ** Copyright 2003-2008, Double Precision Inc.
3 **
4 ** See COPYING for distribution information.
5 */
6 #include "smap.H"
7 #include "misc.H"
8 #include "smaplist.H"
9 #include <sstream>
10 #include <errno.h>
11 #include <cstring>
12
13 using namespace std;
14
15 ////////////////////////////////////////////////////////////////////////
16 //
17 // LIST
18
getName()19 const char *mail::smapLIST::getName()
20 {
21 return "LIST";
22 }
23
smapLIST(string pathArg,mail::callback::folderList & listCallbackArg,mail::callback & callbackArg)24 mail::smapLIST::smapLIST(string pathArg,
25 mail::callback::folderList &listCallbackArg,
26 mail::callback &callbackArg)
27 : path(pathArg), listCallback(listCallbackArg)
28 {
29 defaultCB= &callbackArg;
30 }
31
~smapLIST()32 mail::smapLIST::~smapLIST()
33 {
34 vector<mail::folder *>::iterator b=subfolders.begin(),
35 e=subfolders.end();
36
37 while (b != e)
38 {
39 mail::folder *f= *b;
40
41 *b=NULL;
42 b++;
43 if (f)
44 delete f;
45 }
46 }
47
installed(imap & imapAccount)48 void mail::smapLIST::installed(imap &imapAccount)
49 {
50 string pstr="";
51
52 if (path.size() > 0)
53 {
54 vector<string> words;
55
56 path2words(path, words);
57
58 vector<string>::iterator b=words.begin(), e=words.end();
59
60 pstr="";
61
62 while (b != e)
63 {
64 pstr += " ";
65 pstr += imapAccount.quoteSMAP( *b );
66 b++;
67 }
68 }
69
70 imapAccount.imapcmd("", "LIST" + pstr + "\n");
71 }
72
processLine(imap & imapAccount,vector<const char * > & words)73 bool mail::smapLIST::processLine(imap &imapAccount,
74 vector<const char *> &words)
75 {
76 if (words.size() >= 4 && strcmp(words[0], "*") == 0 &&
77 strcasecmp(words[1], "LIST") == 0)
78 {
79 vector<const char *> dummy;
80
81 dummy.push_back(words[2]);
82
83 string p=path;
84 if (p.size() > 0)
85 p += "/";
86 p += words2path(dummy);
87
88 imapFolder newFolder(imapAccount, p, "",
89 fromutf8(words[3]), 0);
90
91 vector<const char *>::iterator b=words.begin() + 4;
92
93 bool hasFOLDER=false;
94 bool hasDIRECTORY=false;
95
96 while (b != words.end())
97 {
98 const char *c= *b++;
99
100 if (strcasecmp(c, "FOLDER") == 0)
101 {
102 hasFOLDER=true;
103 }
104 else if (strcasecmp(c, "DIRECTORY") == 0)
105 {
106 hasDIRECTORY=true;
107 }
108 }
109
110 newFolder.hasMessages(hasFOLDER);
111 newFolder.hasSubFolders(hasDIRECTORY);
112
113 imapFolder *f=new imapFolder(newFolder);
114
115 if (!f)
116 LIBMAIL_THROW(strerror(errno));
117
118 try {
119 subfolders.push_back(f);
120 } catch (...) {
121 delete f;
122 LIBMAIL_THROW(LIBMAIL_THROW_EMPTY);
123 }
124 return true;
125 }
126
127 return smapHandler::processLine(imapAccount, words);
128 }
129
ok(std::string okMsg)130 bool mail::smapLIST::ok(std::string okMsg)
131 {
132 vector<const mail::folder *> cpy;
133
134 cpy.insert(cpy.end(), subfolders.begin(), subfolders.end());
135
136 listCallback.success(cpy);
137 return smapHandler::ok(okMsg);
138 }
139
140 mail::smapLISToneFolder
smapLISToneFolder(std::string pathArg,mail::callback::folderList & listCallbackArg,mail::callback & callbackArg)141 ::smapLISToneFolder(std::string pathArg,
142 mail::callback::folderList &listCallbackArg,
143 mail::callback &callbackArg)
144 : smapLIST(pathArg, listCallbackArg, callbackArg)
145 {
146 vector<string> words;
147
148 path2words(path, words);
149
150 nameComponent=words.end()[-1];
151 size_t n=path.rfind('/');
152
153 if (n == std::string::npos)
154 path="";
155 else
156 path=path.substr(0, n);
157 }
158
~smapLISToneFolder()159 mail::smapLISToneFolder::~smapLISToneFolder()
160 {
161 }
162
processLine(imap & imapAccount,std::vector<const char * > & words)163 bool mail::smapLISToneFolder::processLine(imap &imapAccount,
164 std::vector<const char *> &words)
165 {
166 if (words.size() >= 4 && strcmp(words[0], "*") == 0 &&
167 strcasecmp(words[1], "LIST") == 0)
168 {
169 if (nameComponent != words[2])
170 return true;
171 }
172
173 if (!smapLIST::processLine(imapAccount, words))
174 return false;
175
176 if (subfolders.size() == 2) // Could be two entries, one a folder,
177 // then a second entry as a folder directory
178 {
179 mail::folder *a=subfolders[0];
180 mail::folder *b=subfolders[1];
181
182 if (b->hasMessages())
183 a->hasMessages(true);
184
185 if (b->hasSubFolders())
186 a->hasSubFolders(true);
187
188 subfolders.erase(subfolders.begin() + 1);
189 delete b;
190 }
191 return true;
192 }
193
ok(std::string msg)194 bool mail::smapLISToneFolder::ok(std::string msg)
195 {
196 // If the folder wasn't found, create a fake entry
197
198 if (subfolders.size() == 0)
199 {
200 vector<const char *> dummy;
201 dummy.push_back("*");
202 dummy.push_back("LIST");
203 dummy.push_back(nameComponent.c_str());
204 dummy.push_back("");
205 processLine(*myimap, dummy);
206 }
207
208 return smapLIST::ok(msg);
209 }
210
211