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