1:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62:
63: import ;
64: import ;
65: import ;
66: import ;
67:
68: import ;
69: import ;
70: import ;
71: import ;
72:
73: import ;
74: import ;
75: import ;
76: import ;
77: import ;
78: import ;
79: import ;
80: import ;
81: import ;
82: import ;
83:
84:
89: public class IMAPConnection
90: implements IMAPConstants
91: {
92:
93:
96: protected static final String TAG_PREFIX = "A";
97:
98:
101: protected static final String US_ASCII = "US-ASCII";
102:
103:
106: protected static final int DEFAULT_PORT = 143;
107:
108:
111: protected static final int DEFAULT_SSL_PORT = 993;
112:
113:
116: protected Socket socket;
117:
118:
121: protected IMAPResponseTokenizer in;
122:
123:
126: protected CRLFOutputStream out;
127:
128:
131: protected List asyncResponses;
132:
133:
136: private List alerts;
137:
138:
141: private int tagIndex = 0;
142:
143:
146: private boolean debug;
147:
148:
151: private boolean ansiDebug = false;
152:
153:
157: public IMAPConnection(String host)
158: throws UnknownHostException, IOException
159: {
160: this(host, -1, 0, 0, false, null, false);
161: }
162:
163:
168: public IMAPConnection(String host, int port)
169: throws UnknownHostException, IOException
170: {
171: this(host, port, 0, 0, false, null, false);
172: }
173:
174:
182: public IMAPConnection(String host, int port,
183: int connectionTimeout, int timeout,
184: boolean debug)
185: throws UnknownHostException, IOException
186: {
187: this(host, port, connectionTimeout, timeout, false, null, debug);
188: }
189:
190:
197: public IMAPConnection(String host, int port, TrustManager tm)
198: throws UnknownHostException, IOException
199: {
200: this(host, port, 0, 0, true, tm, false);
201: }
202:
203:
214: public IMAPConnection(String host, int port,
215: int connectionTimeout, int timeout,
216: boolean secure, TrustManager tm,
217: boolean debug)
218: throws UnknownHostException, IOException
219: {
220: this.debug = debug;
221: if (port < 0)
222: {
223: port = secure ? DEFAULT_SSL_PORT : DEFAULT_PORT;
224: }
225:
226:
227: try
228: {
229: socket = new Socket();
230: InetSocketAddress address = new InetSocketAddress(host, port);
231: if (connectionTimeout > 0)
232: {
233: socket.connect(address, connectionTimeout);
234: }
235: else
236: {
237: socket.connect(address);
238: }
239: if (timeout > 0)
240: {
241: socket.setSoTimeout(timeout);
242: }
243: if (secure)
244: {
245: SSLSocketFactory factory = getSSLSocketFactory(tm);
246: SSLSocket ss =
247: (SSLSocket) factory.createSocket(socket, host, port, true);
248: String[] protocols = { "TLSv1", "SSLv3" };
249: ss.setEnabledProtocols(protocols);
250: ss.setUseClientMode(true);
251: ss.startHandshake();
252: socket = ss;
253: }
254: }
255: catch (GeneralSecurityException e)
256: {
257: e.printStackTrace();
258: throw new IOException(e.getMessage());
259: }
260:
261: InputStream in = socket.getInputStream();
262: in = new BufferedInputStream(in);
263: this.in = new IMAPResponseTokenizer(in);
264: OutputStream out = socket.getOutputStream();
265: out = new BufferedOutputStream(out);
266: this.out = new CRLFOutputStream(out);
267:
268: asyncResponses = new ArrayList();
269: alerts = new ArrayList();
270: }
271:
272:
275: public void setAnsiDebug(boolean flag)
276: {
277: ansiDebug = flag;
278: }
279:
280:
283: protected String newTag()
284: {
285: return TAG_PREFIX + (++tagIndex);
286: }
287:
288:
291: protected void sendCommand(String tag, String command)
292: throws IOException
293: {
294: if (debug)
295: {
296: Logger logger = Logger.getInstance();
297: logger.log("imap", "> " + tag + " " + command);
298: }
299: out.write(tag + ' ' + command);
300: out.writeln();
301: out.flush();
302: }
303:
304:
310: protected boolean invokeSimpleCommand(String command)
311: throws IOException
312: {
313: String tag = newTag();
314: sendCommand(tag, command);
315: while (true)
316: {
317: IMAPResponse response = readResponse();
318: String id = response.getID();
319: if (tag.equals(response.getTag()))
320: {
321: processAlerts(response);
322: if (id == OK)
323: {
324: return true;
325: }
326: else if (id == NO)
327: {
328: return false;
329: }
330: else
331: {
332: throw new IMAPException(id, response.getText());
333: }
334: }
335: else if (response.isUntagged())
336: {
337: asyncResponses.add(response);
338: }
339: else
340: {
341: throw new IMAPException(id, response.getText());
342: }
343: }
344: }
345:
346:
347:
355: protected IMAPResponse readResponse()
356: throws IOException
357: {
358: IMAPResponse response = in.next();
359: if (debug)
360: {
361: Logger logger = Logger.getInstance();
362: if (response == null)
363: {
364: logger.log("imap", "<EOF");
365: }
366: else if (ansiDebug)
367: {
368: logger.log("imap", "< " + response.toANSIString());
369: }
370: else
371: {
372: logger.log("imap", "< " + response.toString());
373: }
374: }
375: if (response == null)
376: {
377: throw new IOException("EOF");
378: }
379: return response;
380: }
381:
382:
383:
384: private void processAlerts(IMAPResponse response)
385: {
386: List code = response.getResponseCode();
387: if (code != null && code.contains(ALERT))
388: {
389: alerts.add(response.getText());
390: }
391: }
392:
393:
396: public boolean alertsPending()
397: {
398: return (alerts.size() > 0);
399: }
400:
401:
404: public String[] getAlerts()
405: {
406: String[] a = new String[alerts.size()];
407: alerts.toArray(a);
408: alerts.clear();
409: return a;
410: }
411:
412:
413:
414:
417: public List capability()
418: throws IOException
419: {
420: String tag = newTag();
421: sendCommand(tag, CAPABILITY);
422: List capabilities = new ArrayList();
423: while (true)
424: {
425: IMAPResponse response = readResponse();
426: String id = response.getID();
427: if (tag.equals(response.getTag()))
428: {
429: processAlerts(response);
430: if (id == OK)
431: {
432: if (capabilities.size() == 0)
433: {
434:
435:
436: addTokens(capabilities, response.getText());
437: }
438: return capabilities;
439: }
440: else
441: {
442: throw new IMAPException(id, response.getText());
443: }
444: }
445: else if (response.isUntagged())
446: {
447: if (id == CAPABILITY)
448: {
449:
450:
451: addTokens(capabilities, response.getText());
452: }
453: else if (id == OK)
454: {
455:
456:
457: List code = response.getResponseCode();
458: int len = (code == null) ? 0 : code.size();
459: if (len > 0 && CAPABILITY.equals(code.get(0)))
460: {
461: for (int i = 1; i < len; i++)
462: {
463: String token = (String) code.get(i);
464: if (!capabilities.contains(token))
465: {
466: capabilities.add(token);
467: }
468: }
469: }
470: else
471: {
472: asyncResponses.add(response);
473: }
474: }
475: else
476: {
477: asyncResponses.add(response);
478: }
479: }
480: else
481: {
482: throw new IMAPException(id, response.getText());
483: }
484: }
485: }
486:
487: private void addTokens(List list, String text)
488: {
489: int start = 0;
490: int end = text.indexOf(' ');
491: String token;
492: while (end != -1)
493: {
494: token = text.substring(start, end);
495: if (!list.contains(token))
496: {
497: list.add(token);
498: }
499: start = end + 1;
500: end = text.indexOf(' ', start);
501: }
502: token = text.substring(start);
503: if (token.length() > 0 && !list.contains(token))
504: {
505: list.add(token);
506: }
507: }
508:
509:
514: public MailboxStatus noop()
515: throws IOException
516: {
517: String tag = newTag();
518: sendCommand(tag, NOOP);
519: boolean changed = false;
520: MailboxStatus ms = new MailboxStatus();
521: Iterator asyncIterator = asyncResponses.iterator();
522: while (true)
523: {
524: IMAPResponse response;
525:
526: if (asyncIterator.hasNext())
527: {
528: response = (IMAPResponse) asyncIterator.next();
529: asyncIterator.remove();
530: }
531: else
532: {
533: response = readResponse();
534: }
535: String id = response.getID();
536: if (response.isUntagged())
537: {
538: changed = changed || updateMailboxStatus(ms, id, response);
539: }
540: else if (tag.equals(response.getTag()))
541: {
542: processAlerts(response);
543: if (id == OK)
544: {
545: return changed ? ms : null;
546: }
547: else
548: {
549: throw new IMAPException(id, response.getText());
550: }
551: }
552: else
553: {
554: throw new IMAPException(id, response.getText());
555: }
556: }
557: }
558:
559:
564: protected SSLSocketFactory getSSLSocketFactory(TrustManager tm)
565: throws GeneralSecurityException
566: {
567: if (tm == null)
568: {
569: tm = new EmptyX509TrustManager();
570: }
571: SSLContext context = SSLContext.getInstance("TLS");
572: TrustManager[] trust = new TrustManager[] { tm };
573: context.init(null, trust, null);
574: return context.getSocketFactory();
575: }
576:
577:
582: public boolean starttls()
583: throws IOException
584: {
585: return starttls(new EmptyX509TrustManager());
586: }
587:
588:
594: public boolean starttls(TrustManager tm)
595: throws IOException
596: {
597: try
598: {
599: SSLSocketFactory factory = getSSLSocketFactory(tm);
600: String hostname = socket.getInetAddress().getHostName();
601: int port = socket.getPort();
602:
603: String tag = newTag();
604: sendCommand(tag, STARTTLS);
605: while (true)
606: {
607: IMAPResponse response = readResponse();
608: if (response.isTagged() && tag.equals(response.getTag()))
609: {
610: processAlerts(response);
611: String id = response.getID();
612: if (id == OK)
613: {
614: break;
615: }
616: else if (id == BAD)
617: {
618: return false;
619: }
620: }
621: else
622: {
623: asyncResponses.add(response);
624: }
625: }
626:
627: SSLSocket ss =
628: (SSLSocket) factory.createSocket(socket, hostname, port, true);
629: String[] protocols = { "TLSv1", "SSLv3" };
630: ss.setEnabledProtocols(protocols);
631: ss.setUseClientMode(true);
632: ss.startHandshake();
633:
634: InputStream in = ss.getInputStream();
635: in = new BufferedInputStream(in);
636: this.in = new IMAPResponseTokenizer(in);
637: OutputStream out = ss.getOutputStream();
638: out = new BufferedOutputStream(out);
639: this.out = new CRLFOutputStream(out);
640: return true;
641: }
642: catch (GeneralSecurityException e)
643: {
644: e.printStackTrace();
645: return false;
646: }
647: }
648:
649:
655: public boolean login(String username, String password)
656: throws IOException
657: {
658: return invokeSimpleCommand(LOGIN + ' ' + quote(username) +
659: ' ' + quote(password));
660: }
661:
662:
671: public boolean authenticate(String mechanism, String username,
672: String password)
673: throws IOException
674: {
675: try
676: {
677: String[] m = new String[] { mechanism };
678: CallbackHandler ch = new SaslCallbackHandler(username, password);
679:
680: Properties p = new Properties();
681: p.put("gnu.crypto.sasl.username", username);
682: p.put("gnu.crypto.sasl.password", password);
683: SaslClient sasl = Sasl.createSaslClient(m, null, "imap",
684: socket.getInetAddress().
685: getHostName(), p, ch);
686: if (sasl == null)
687: {
688:
689: if ("LOGIN".equalsIgnoreCase(mechanism))
690: {
691: sasl = new SaslLogin(username, password);
692: }
693: else if ("PLAIN".equalsIgnoreCase(mechanism))
694: {
695: sasl = new SaslPlain(username, password);
696: }
697: else if ("CRAM-MD5".equalsIgnoreCase(mechanism))
698: {
699: sasl = new SaslCramMD5(username, password);
700: }
701: else
702: {
703: if (debug)
704: {
705: Logger logger = Logger.getInstance();
706: logger.log("imap", mechanism + " not available");
707: }
708: return false;
709: }
710: }
711:
712: StringBuffer cmd = new StringBuffer(AUTHENTICATE);
713: cmd.append(' ');
714: cmd.append(mechanism);
715: String tag = newTag();
716: sendCommand(tag, cmd.toString());
717: while (true)
718: {
719: IMAPResponse response = readResponse();
720: if (tag.equals(response.getTag()))
721: {
722: processAlerts(response);
723: String id = response.getID();
724: if (id == OK)
725: {
726: String qop =
727: (String) sasl.getNegotiatedProperty(Sasl.QOP);
728: if ("auth-int".equalsIgnoreCase(qop)
729: || "auth-conf".equalsIgnoreCase(qop))
730: {
731: InputStream in = socket.getInputStream();
732: in = new BufferedInputStream(in);
733: in = new SaslInputStream(sasl, in);
734: this.in = new IMAPResponseTokenizer(in);
735: OutputStream out = socket.getOutputStream();
736: out = new BufferedOutputStream(out);
737: out = new SaslOutputStream(sasl, out);
738: this.out = new CRLFOutputStream(out);
739: }
740: return true;
741: }
742: else if (id == NO)
743: {
744: return false;
745: }
746: else if (id == BAD)
747: {
748: throw new IMAPException(id, response.getText());
749: }
750: }
751: else if (response.isContinuation())
752: {
753: try
754: {
755: byte[] c0 = response.getText().getBytes(US_ASCII);
756: byte[] c1 = BASE64.decode(c0);
757: byte[] r0 = sasl.evaluateChallenge(c1);
758: byte[] r1 = BASE64.encode(r0);
759: out.write(r1);
760: out.writeln();
761: out.flush();
762: if (debug)
763: {
764: Logger logger = Logger.getInstance();
765: logger.log("imap", "> " + new String(r1, US_ASCII));
766: }
767: }
768: catch (SaslException e)
769: {
770:
771: out.write(0x2a);
772: out.writeln();
773: out.flush();
774: if (debug)
775: {
776: Logger logger = Logger.getInstance();
777: logger.log("imap", "> *");
778: }
779: }
780: }
781: else
782: {
783: asyncResponses.add(response);
784: }
785: }
786: }
787: catch (SaslException e)
788: {
789: if (debug)
790: {
791: Logger logger = Logger.getInstance();
792: logger.error("imap", e);
793: }
794: return false;
795: }
796: catch (RuntimeException e)
797: {
798: if (debug)
799: {
800: Logger logger = Logger.getInstance();
801: logger.error("imap", e);
802: }
803: return false;
804: }
805: }
806:
807:
811: public void logout()
812: throws IOException
813: {
814: String tag = newTag();
815: sendCommand(tag, LOGOUT);
816: while (true)
817: {
818: IMAPResponse response = readResponse();
819: if (response.isTagged() && tag.equals(response.getTag()))
820: {
821: processAlerts(response);
822: String id = response.getID();
823: if (id == OK)
824: {
825: socket.close();
826: return;
827: }
828: else
829: {
830: throw new IMAPException(id, response.getText());
831: }
832: }
833: else
834: {
835: asyncResponses.add(response);
836: }
837: }
838: }
839:
840:
846: public MailboxStatus select(String mailbox)
847: throws IOException
848: {
849: return selectImpl(mailbox, SELECT);
850: }
851:
852:
858: public MailboxStatus examine(String mailbox)
859: throws IOException
860: {
861: return selectImpl(mailbox, EXAMINE);
862: }
863:
864: protected MailboxStatus selectImpl(String mailbox, String command)
865: throws IOException
866: {
867: String tag = newTag();
868: sendCommand(tag, command + ' ' + quote(UTF7imap.encode(mailbox)));
869: MailboxStatus ms = new MailboxStatus();
870: while (true)
871: {
872: IMAPResponse response = readResponse();
873: String id = response.getID();
874: if (response.isUntagged())
875: {
876: if (!updateMailboxStatus(ms, id, response))
877: {
878: asyncResponses.add(response);
879: }
880: }
881: else if (tag.equals(response.getTag()))
882: {
883: processAlerts(response);
884: if (id == OK)
885: {
886: List rc = response.getResponseCode();
887: if (rc != null && rc.size() > 0 && rc.get(0) == READ_WRITE)
888: {
889: ms.readWrite = true;
890: }
891: return ms;
892: }
893: else
894: {
895: throw new IMAPException(id, response.getText());
896: }
897: }
898: else
899: {
900: throw new IMAPException(id, response.getText());
901: }
902: }
903: }
904:
905: protected boolean updateMailboxStatus(MailboxStatus ms, String id,
906: IMAPResponse response)
907: throws IOException
908: {
909: if (id == OK)
910: {
911: boolean changed = false;
912: List rc = response.getResponseCode();
913: int len = (rc == null) ? 0 : rc.size();
914: for (int i = 0; i < len; i++)
915: {
916: Object ocmd = rc.get(i);
917: if (ocmd instanceof String)
918: {
919: String cmd = (String) ocmd;
920: if (i + 1 < len)
921: {
922: Object oparam = rc.get(i + 1);
923: if (oparam instanceof String)
924: {
925: String param = (String) oparam;
926: try
927: {
928: if (cmd == UNSEEN)
929: {
930: ms.firstUnreadMessage =
931: Integer.parseInt(param);
932: i++;
933: changed = true;
934: }
935: else if (cmd == UIDVALIDITY)
936: {
937: ms.uidValidity = Integer.parseInt(param);
938: i++;
939: changed = true;
940: }
941: }
942: catch (NumberFormatException e)
943: {
944: throw new ProtocolException("Illegal " + cmd +
945: " value: " + param);
946: }
947: }
948: else if (oparam instanceof List)
949: {
950: if (cmd == PERMANENTFLAGS)
951: {
952: ms.permanentFlags = (List) oparam;
953: i++;
954: changed = true;
955: }
956: }
957: }
958: }
959: }
960: return changed;
961: }
962: else if (id == EXISTS)
963: {
964: ms.messageCount = response.getCount();
965: return true;
966: }
967: else if (id == RECENT)
968: {
969: ms.newMessageCount = response.getCount();
970: return true;
971: }
972: else if (id == FLAGS)
973: {
974: ms.flags = response.getResponseCode();
975: return true;
976: }
977: else
978: {
979: return false;
980: }
981: }
982:
983:
988: public boolean create(String mailbox)
989: throws IOException
990: {
991: return invokeSimpleCommand(CREATE + ' ' + quote(UTF7imap.encode(mailbox)));
992: }
993:
994:
999: public boolean delete(String mailbox)
1000: throws IOException
1001: {
1002: return invokeSimpleCommand(DELETE + ' ' + quote(UTF7imap.encode(mailbox)));
1003: }
1004:
1005:
1011: public boolean rename(String source, String target)
1012: throws IOException
1013: {
1014: return invokeSimpleCommand(RENAME + ' ' + quote(UTF7imap.encode(source)) +
1015: ' ' + quote(UTF7imap.encode(target)));
1016: }
1017:
1018:
1024: public boolean subscribe(String mailbox)
1025: throws IOException
1026: {
1027: return invokeSimpleCommand(SUBSCRIBE + ' ' +
1028: quote(UTF7imap.encode(mailbox)));
1029: }
1030:
1031:
1037: public boolean unsubscribe(String mailbox)
1038: throws IOException
1039: {
1040: return invokeSimpleCommand(UNSUBSCRIBE + ' ' +
1041: quote(UTF7imap.encode(mailbox)));
1042: }
1043:
1044:
1051: public ListEntry[] list(String reference, String mailbox)
1052: throws IOException
1053: {
1054: return listImpl(LIST, reference, mailbox);
1055: }
1056:
1057:
1061: public ListEntry[] lsub(String reference, String mailbox)
1062: throws IOException
1063: {
1064: return listImpl(LSUB, reference, mailbox);
1065: }
1066:
1067: protected ListEntry[] listImpl(String command, String reference,
1068: String mailbox)
1069: throws IOException
1070: {
1071: if (reference == null)
1072: {
1073: reference = "";
1074: }
1075: if (mailbox == null)
1076: {
1077: mailbox = "";
1078: }
1079: String tag = newTag();
1080: sendCommand(tag, command + ' ' +
1081: quote(UTF7imap.encode(reference)) + ' ' +
1082: quote(UTF7imap.encode(mailbox)));
1083: List acc = new ArrayList();
1084: while (true)
1085: {
1086: IMAPResponse response = readResponse();
1087: String id = response.getID();
1088: if (response.isUntagged())
1089: {
1090: if (id.equals(command))
1091: {
1092: List code = response.getResponseCode();
1093: String text = response.getText();
1094:
1095:
1096:
1097:
1098: int alen = (code == null) ? 0 : code.size();
1099: boolean noinferiors = false;
1100: boolean noselect = false;
1101: boolean marked = false;
1102: boolean unmarked = false;
1103: for (int i = 0; i < alen; i++)
1104: {
1105: String attribute = (String) code.get(i);
1106: if (attribute.equalsIgnoreCase(LIST_NOINFERIORS))
1107: {
1108: noinferiors = true;
1109: }
1110: else if (attribute.equalsIgnoreCase(LIST_NOSELECT))
1111: {
1112: noselect = true;
1113: }
1114: else if (attribute.equalsIgnoreCase(LIST_MARKED))
1115: {
1116: marked = true;
1117: }
1118: else if (attribute.equalsIgnoreCase(LIST_UNMARKED))
1119: {
1120: unmarked = true;
1121: }
1122: }
1123: int si = text.indexOf(' ');
1124: char delimiter = '\u0000';
1125: String d = text.substring(0, si);
1126: if (!d.equalsIgnoreCase(NIL))
1127: {
1128: delimiter = stripQuotes(d).charAt(0);
1129: }
1130: String mbox = stripQuotes(text.substring(si + 1));
1131: mbox = UTF7imap.decode(mbox);
1132: ListEntry entry = new ListEntry(mbox, delimiter, noinferiors,
1133: noselect, marked, unmarked);
1134: acc.add(entry);
1135: }
1136: else
1137: {
1138: asyncResponses.add(response);
1139: }
1140: }
1141: else if (tag.equals(response.getTag()))
1142: {
1143: processAlerts(response);
1144: if (id == OK)
1145: {
1146: ListEntry[] entries = new ListEntry[acc.size()];
1147: acc.toArray(entries);
1148: return entries;
1149: }
1150: else
1151: {
1152: throw new IMAPException(id, response.getText());
1153: }
1154: }
1155: else
1156: {
1157: throw new IMAPException(id, response.getText());
1158: }
1159: }
1160: }
1161:
1162:
1165: public MailboxStatus status(String mailbox, String[] statusNames)
1166: throws IOException
1167: {
1168: String tag = newTag();
1169: StringBuffer buffer = new StringBuffer(STATUS)
1170: .append(' ')
1171: .append(quote(UTF7imap.encode(mailbox)))
1172: .append(' ')
1173: .append('(');
1174: for (int i = 0; i < statusNames.length; i++)
1175: {
1176: if (i > 0)
1177: {
1178: buffer.append(' ');
1179: }
1180: buffer.append(statusNames[i]);
1181: }
1182: buffer.append(')');
1183: sendCommand(tag, buffer.toString());
1184: MailboxStatus ms = new MailboxStatus();
1185: while (true)
1186: {
1187: IMAPResponse response = readResponse();
1188: String id = response.getID();
1189: if (response.isUntagged())
1190: {
1191: if (id == STATUS)
1192: {
1193: List code = response.getResponseCode();
1194: int last = (code == null) ? 0 : code.size() - 1;
1195: for (int i = 0; i < last; i += 2)
1196: {
1197: try
1198: {
1199: String statusName = ((String) code.get(i)).intern();
1200: int value = Integer.parseInt((String) code.get(i + 1));
1201: if (statusName == MESSAGES)
1202: {
1203: ms.messageCount = value;
1204: }
1205: else if (statusName == RECENT)
1206: {
1207: ms.newMessageCount = value;
1208: }
1209: else if (statusName == UIDNEXT)
1210: {
1211: ms.uidNext = value;
1212: }
1213: else if (statusName == UIDVALIDITY)
1214: {
1215: ms.uidValidity = value;
1216: }
1217: else if (statusName == UNSEEN)
1218: {
1219: ms.firstUnreadMessage = value;
1220: }
1221: }
1222: catch (NumberFormatException e)
1223: {
1224: throw new IMAPException(id, "Invalid code: " + code);
1225: }
1226: }
1227: }
1228: else
1229: {
1230: asyncResponses.add(response);
1231: }
1232: }
1233: else if (tag.equals(response.getTag()))
1234: {
1235: processAlerts(response);
1236: if (id == OK)
1237: {
1238: return ms;
1239: }
1240: else
1241: {
1242: throw new IMAPException(id, response.getText());
1243: }
1244: }
1245: else
1246: {
1247: throw new IMAPException(id, response.getText());
1248: }
1249: }
1250: }
1251:
1252:
1261: public boolean append(String mailbox, String[] flags, byte[] content)
1262: throws IOException
1263: {
1264: String tag = newTag();
1265: StringBuffer buffer = new StringBuffer(APPEND)
1266: .append(' ')
1267: .append(quote(UTF7imap.encode(mailbox)))
1268: .append(' ');
1269: if (flags != null)
1270: {
1271: buffer.append('(');
1272: for (int i = 0; i < flags.length; i++)
1273: {
1274: if (i > 0)
1275: {
1276: buffer.append(' ');
1277: }
1278: buffer.append(flags[i]);
1279: }
1280: buffer.append(')');
1281: buffer.append(' ');
1282: }
1283: buffer.append('{');
1284: buffer.append(content.length);
1285: buffer.append('}');
1286: sendCommand(tag, buffer.toString());
1287: IMAPResponse response = readResponse();
1288: if (!response.isContinuation())
1289: {
1290: throw new IMAPException(response.getID(), response.getText());
1291: }
1292: out.write(content);
1293: out.writeln();
1294: out.flush();
1295: while (true)
1296: {
1297: response = readResponse();
1298: String id = response.getID();
1299: if (tag.equals(response.getTag()))
1300: {
1301: processAlerts(response);
1302: if (id == OK)
1303: {
1304: return true;
1305: }
1306: else if (id == NO)
1307: {
1308: return false;
1309: }
1310: else
1311: {
1312: throw new IMAPException(id, response.getText());
1313: }
1314: }
1315: else if (response.isUntagged())
1316: {
1317: asyncResponses.add(response);
1318: }
1319: else
1320: {
1321: throw new IMAPException(id, response.getText());
1322: }
1323: }
1324: }
1325:
1326:
1329: public void check()
1330: throws IOException
1331: {
1332: invokeSimpleCommand(CHECK);
1333: }
1334:
1335:
1340: public boolean close()
1341: throws IOException
1342: {
1343: return invokeSimpleCommand(CLOSE);
1344: }
1345:
1346:
1350: public int[] expunge()
1351: throws IOException
1352: {
1353: String tag = newTag();
1354: sendCommand(tag, EXPUNGE);
1355: List numbers = new ArrayList();
1356: while (true)
1357: {
1358: IMAPResponse response = readResponse();
1359: String id = response.getID();
1360: if (response.isUntagged())
1361: {
1362: if (id == EXPUNGE)
1363: {
1364: numbers.add(new Integer(response.getCount()));
1365: }
1366: else
1367: {
1368: asyncResponses.add(response);
1369: }
1370: }
1371: else if (tag.equals(response.getTag()))
1372: {
1373: processAlerts(response);
1374: if (id == OK)
1375: {
1376: int len = numbers.size();
1377: int[] mn = new int[len];
1378: for (int i = 0; i < len; i++)
1379: {
1380: mn[i] = ((Integer) numbers.get(i)).intValue();
1381: }
1382: return mn;
1383: }
1384: else
1385: {
1386: throw new IMAPException(id, response.getText());
1387: }
1388: }
1389: else
1390: {
1391: throw new IMAPException(id, response.getText());
1392: }
1393: }
1394: }
1395:
1396:
1400: public int[] search(String charset, String[] criteria)
1401: throws IOException
1402: {
1403: String tag = newTag();
1404: StringBuffer buffer = new StringBuffer(SEARCH);
1405: buffer.append(' ');
1406: if (charset != null)
1407: {
1408: buffer.append(charset);
1409: buffer.append(' ');
1410: }
1411: for (int i = 0; i < criteria.length; i++)
1412: {
1413: if (i > 0)
1414: {
1415: buffer.append(' ');
1416: }
1417: buffer.append(criteria[i]);
1418: }
1419: sendCommand(tag, buffer.toString());
1420: List list = new ArrayList();
1421: while (true)
1422: {
1423: IMAPResponse response = readResponse();
1424: String id = response.getID();
1425: if (response.isUntagged())
1426: {
1427: if (id == SEARCH)
1428: {
1429: String text = response.getText();
1430: if (text == null)
1431: {
1432: continue;
1433: }
1434: try
1435: {
1436: int si = text.indexOf(' ');
1437: while (si != -1)
1438: {
1439: list.add(new Integer(text.substring(0, si)));
1440: text = text.substring(si + 1);
1441: si = text.indexOf(' ');
1442: }
1443: list.add(new Integer(text));
1444: }
1445: catch (NumberFormatException e)
1446: {
1447: throw new IMAPException(id, "Expecting number: " + text);
1448: }
1449: }
1450: else
1451: {
1452: asyncResponses.add(response);
1453: }
1454: }
1455: else if (tag.equals(response.getTag()))
1456: {
1457: processAlerts(response);
1458: if (id == OK)
1459: {
1460: int len = list.size();
1461: int[] mn = new int[len];
1462: for (int i = 0; i < len; i++)
1463: {
1464: mn[i] = ((Integer) list.get(i)).intValue();
1465: }
1466: return mn;
1467: }
1468: else
1469: {
1470: throw new IMAPException(id, response.getText());
1471: }
1472: }
1473: else
1474: {
1475: throw new IMAPException(id, response.getText());
1476: }
1477: }
1478: }
1479:
1480:
1485: public MessageStatus fetch(int message, String[] fetchCommands)
1486: throws IOException
1487: {
1488: String ids = (message == -1) ? "*" : Integer.toString(message);
1489: return fetchImpl(FETCH, ids, fetchCommands)[0];
1490: }
1491:
1492:
1499: public MessageStatus[] fetch(int start, int end, String[] fetchCommands)
1500: throws IOException
1501: {
1502: StringBuffer ids = new StringBuffer();
1503: ids.append((start == -1) ? '*' : start);
1504: ids.append(':');
1505: ids.append((end == -1) ? '*' : end);
1506: return fetchImpl(FETCH, ids.toString(), fetchCommands);
1507: }
1508:
1509:
1514: public MessageStatus[] fetch(int[] messages, String[] fetchCommands)
1515: throws IOException
1516: {
1517: StringBuffer ids = new StringBuffer();
1518: for (int i = 0; i < messages.length; i++)
1519: {
1520: if (i > 0)
1521: {
1522: ids.append(',');
1523: }
1524: ids.append(messages[i]);
1525: }
1526: return fetchImpl(FETCH, ids.toString(), fetchCommands);
1527: }
1528:
1529:
1534: public MessageStatus uidFetch(long uid, String[] fetchCommands)
1535: throws IOException
1536: {
1537: String ids = (uid == -1L) ? "*" : Long.toString(uid);
1538: return fetchImpl(UID + ' ' + FETCH, ids, fetchCommands)[0];
1539: }
1540:
1541:
1548: public MessageStatus[] uidFetch(long start, long end,
1549: String[] fetchCommands)
1550: throws IOException
1551: {
1552: StringBuffer ids = new StringBuffer();
1553: ids.append((start == -1L) ? '*' : start);
1554: ids.append(':');
1555: ids.append((end == -1L) ? '*' : end);
1556: return fetchImpl(UID + ' ' + FETCH, ids.toString(), fetchCommands);
1557: }
1558:
1559:
1564: public MessageStatus[] uidFetch(long[] uids, String[] fetchCommands)
1565: throws IOException
1566: {
1567: StringBuffer ids = new StringBuffer();
1568: for (int i = 0; i < uids.length; i++)
1569: {
1570: if (i > 0)
1571: {
1572: ids.append(',');
1573: }
1574: ids.append(uids[i]);
1575: }
1576: return fetchImpl(UID + ' ' + FETCH, ids.toString(), fetchCommands);
1577: }
1578:
1579: private MessageStatus[] fetchImpl(String cmd, String ids,
1580: String[] fetchCommands)
1581: throws IOException
1582: {
1583: String tag = newTag();
1584: StringBuffer buffer = new StringBuffer(cmd);
1585: buffer.append(' ');
1586: buffer.append(ids);
1587: buffer.append(' ');
1588: buffer.append('(');
1589: for (int i = 0; i < fetchCommands.length; i++)
1590: {
1591: if (i > 0)
1592: {
1593: buffer.append(' ');
1594: }
1595: buffer.append(fetchCommands[i]);
1596: }
1597: buffer.append(')');
1598: sendCommand(tag, buffer.toString());
1599: List list = new ArrayList();
1600: while (true)
1601: {
1602: IMAPResponse response = readResponse();
1603: String id = response.getID();
1604: if (response.isUntagged())
1605: {
1606: if (id == FETCH)
1607: {
1608: int msgnum = response.getCount();
1609: List code = response.getResponseCode();
1610: MessageStatus status = new MessageStatus(msgnum, code);
1611: list.add(status);
1612: }
1613: else
1614: {
1615: asyncResponses.add(response);
1616: }
1617: }
1618: else if (tag.equals(response.getTag()))
1619: {
1620: processAlerts(response);
1621: if (id == OK)
1622: {
1623: MessageStatus[] statuses = new MessageStatus[list.size()];
1624: list.toArray(statuses);
1625: return statuses;
1626: }
1627: else
1628: {
1629: throw new IMAPException(id, response.getText());
1630: }
1631: }
1632: else
1633: {
1634: throw new IMAPException(id, response.getText());
1635: }
1636: }
1637: }
1638:
1639:
1646: public MessageStatus store(int message, String flagCommand,
1647: String[] flags)
1648: throws IOException
1649: {
1650: String ids = (message == -1) ? "*" : Integer.toString(message);
1651: return storeImpl(STORE, ids, flagCommand, flags)[0];
1652: }
1653:
1654:
1663: public MessageStatus[] store(int start, int end, String flagCommand,
1664: String[] flags)
1665: throws IOException
1666: {
1667: StringBuffer ids = new StringBuffer();
1668: ids.append((start == -1) ? '*' : start);
1669: ids.append(':');
1670: ids.append((end == -1) ? '*' : end);
1671: return storeImpl(STORE, ids.toString(), flagCommand, flags);
1672: }
1673:
1674:
1681: public MessageStatus[] store(int[] messages, String flagCommand,
1682: String[] flags)
1683: throws IOException
1684: {
1685: StringBuffer ids = new StringBuffer();
1686: for (int i = 0; i < messages.length; i++)
1687: {
1688: if (i > 0)
1689: {
1690: ids.append(',');
1691: }
1692: ids.append(messages[i]);
1693: }
1694: return storeImpl(STORE, ids.toString(), flagCommand, flags);
1695: }
1696:
1697:
1704: public MessageStatus uidStore(long uid, String flagCommand,
1705: String[] flags)
1706: throws IOException
1707: {
1708: String ids = (uid == -1L) ? "*" : Long.toString(uid);
1709: return storeImpl(UID + ' ' + STORE, ids, flagCommand, flags)[0];
1710: }
1711:
1712:
1721: public MessageStatus[] uidStore(long start, long end, String flagCommand,
1722: String[] flags)
1723: throws IOException
1724: {
1725: StringBuffer ids = new StringBuffer();
1726: ids.append((start == -1L) ? '*' : start);
1727: ids.append(':');
1728: ids.append((end == -1L) ? '*' : end);
1729: return storeImpl(UID + ' ' + STORE, ids.toString(), flagCommand, flags);
1730: }
1731:
1732:
1739: public MessageStatus[] uidStore(long[] uids, String flagCommand,
1740: String[] flags)
1741: throws IOException
1742: {
1743: StringBuffer ids = new StringBuffer();
1744: for (int i = 0; i < uids.length; i++)
1745: {
1746: if (i > 0)
1747: {
1748: ids.append(',');
1749: }
1750: ids.append(uids[i]);
1751: }
1752: return storeImpl(UID + ' ' + STORE, ids.toString(), flagCommand, flags);
1753: }
1754:
1755: private MessageStatus[] storeImpl(String cmd, String ids,
1756: String flagCommand, String[] flags)
1757: throws IOException
1758: {
1759: String tag = newTag();
1760: StringBuffer buffer = new StringBuffer(cmd);
1761: buffer.append(' ');
1762: buffer.append(ids);
1763: buffer.append(' ');
1764: buffer.append(flagCommand);
1765: buffer.append(' ');
1766: buffer.append('(');
1767: for (int i = 0; i < flags.length; i++)
1768: {
1769: if (i > 0)
1770: {
1771: buffer.append(' ');
1772: }
1773: buffer.append(flags[i]);
1774: }
1775: buffer.append(')');
1776: sendCommand(tag, buffer.toString());
1777: List list = new ArrayList();
1778: while (true)
1779: {
1780: IMAPResponse response = readResponse();
1781: String id = response.getID();
1782: if (response.isUntagged())
1783: {
1784: int msgnum = response.getCount();
1785: List code = response.getResponseCode();
1786:
1787: if (id == FETCH)
1788: {
1789: MessageStatus mf = new MessageStatus(msgnum, code);
1790: list.add(mf);
1791: }
1792: else if (id == FETCH_FLAGS)
1793: {
1794: List base = new ArrayList();
1795: base.add(FLAGS);
1796: base.add(code);
1797: MessageStatus mf = new MessageStatus(msgnum, base);
1798: list.add(mf);
1799: }
1800: else
1801: {
1802: asyncResponses.add(response);
1803: }
1804: }
1805: else if (tag.equals(response.getTag()))
1806: {
1807: processAlerts(response);
1808: if (id == OK)
1809: {
1810: MessageStatus[] mf = new MessageStatus[list.size()];
1811: list.toArray(mf);
1812: return mf;
1813: }
1814: else
1815: {
1816: throw new IMAPException(id, response.getText());
1817: }
1818: }
1819: else
1820: {
1821: throw new IMAPException(id, response.getText());
1822: }
1823: }
1824: }
1825:
1826:
1831: public boolean copy(int[] messages, String mailbox)
1832: throws IOException
1833: {
1834: if (messages == null || messages.length < 1)
1835: {
1836: return true;
1837: }
1838: StringBuffer buffer = new StringBuffer(COPY)
1839: .append(' ');
1840: for (int i = 0; i < messages.length; i++)
1841: {
1842: if (i > 0)
1843: {
1844: buffer.append(',');
1845: }
1846: buffer.append(messages[i]);
1847: }
1848: buffer.append(' ').append(quote(UTF7imap.encode(mailbox)));
1849: return invokeSimpleCommand(buffer.toString());
1850: }
1851:
1852:
1856: public Namespaces namespace()
1857: throws IOException
1858: {
1859: String tag = newTag();
1860: sendCommand(tag, NAMESPACE);
1861: Namespaces namespaces = null;
1862: while (true)
1863: {
1864: IMAPResponse response = readResponse();
1865: String id = response.getID();
1866: if (tag.equals(response.getTag()))
1867: {
1868: processAlerts(response);
1869: if (id == OK)
1870: {
1871: return namespaces;
1872: }
1873: else
1874: {
1875: throw new IMAPException(id, response.getText());
1876: }
1877: }
1878: else if (response.isUntagged())
1879: {
1880: if (NAMESPACE.equals(response.getID()))
1881: {
1882: namespaces = new Namespaces(response.getText());
1883: }
1884: else
1885: {
1886: asyncResponses.add(response);
1887: }
1888: }
1889: else
1890: {
1891: throw new IMAPException(id, response.getText());
1892: }
1893: }
1894: }
1895:
1896:
1903: public boolean setacl(String mailbox, String principal, int rights)
1904: throws IOException
1905: {
1906: String command = SETACL + ' ' + quote(UTF7imap.encode(mailbox)) +
1907: ' ' + UTF7imap.encode(principal) + ' ' + rightsToString(rights);
1908: return invokeSimpleCommand(command);
1909: }
1910:
1911:
1917: public boolean deleteacl(String mailbox, String principal)
1918: throws IOException
1919: {
1920: String command = DELETEACL + ' ' + quote(UTF7imap.encode(mailbox)) +
1921: ' ' + UTF7imap.encode(principal);
1922: return invokeSimpleCommand(command);
1923: }
1924:
1925:
1931: public Map getacl(String mailbox)
1932: throws IOException
1933: {
1934: String tag = newTag();
1935: sendCommand(tag, GETACL + ' ' + quote(UTF7imap.encode(mailbox)));
1936: Map ret = new TreeMap();
1937: while (true)
1938: {
1939: IMAPResponse response = readResponse();
1940: String id = response.getID();
1941: if (tag.equals(response.getTag()))
1942: {
1943: processAlerts(response);
1944: if (id == OK)
1945: {
1946: return ret;
1947: }
1948: else if (id == NO)
1949: {
1950: return null;
1951: }
1952: else
1953: {
1954: throw new IMAPException(id, response.getText());
1955: }
1956: }
1957: else if (response.isUntagged())
1958: {
1959: if (ACL.equals(response.getID()))
1960: {
1961: String text = response.getText();
1962: List args = parseACL(text, 1);
1963: String rights = (String) args.get(2);
1964: ret.put(args.get(1), new Integer(stringToRights(rights)));
1965: }
1966: else
1967: {
1968: asyncResponses.add(response);
1969: }
1970: }
1971: else
1972: {
1973: throw new IMAPException(id, response.getText());
1974: }
1975: }
1976: }
1977:
1978:
1984: public int listrights(String mailbox, String principal)
1985: throws IOException
1986: {
1987: String tag = newTag();
1988: String command = LISTRIGHTS + ' ' + quote(UTF7imap.encode(mailbox)) +
1989: ' ' + UTF7imap.encode(principal);
1990: sendCommand(tag, command);
1991: int ret = -1;
1992: while (true)
1993: {
1994: IMAPResponse response = readResponse();
1995: String id = response.getID();
1996: if (tag.equals(response.getTag()))
1997: {
1998: processAlerts(response);
1999: if (id == OK)
2000: {
2001: return ret;
2002: }
2003: else if (id == NO)
2004: {
2005: return -1;
2006: }
2007: else
2008: {
2009: throw new IMAPException(id, response.getText());
2010: }
2011: }
2012: else if (response.isUntagged())
2013: {
2014: if (LISTRIGHTS.equals(response.getID()))
2015: {
2016: String text = response.getText();
2017: List args = parseACL(text, 1);
2018: ret = stringToRights((String) args.get(2));
2019: }
2020: else
2021: {
2022: asyncResponses.add(response);
2023: }
2024: }
2025: else
2026: {
2027: throw new IMAPException(id, response.getText());
2028: }
2029: }
2030: }
2031:
2032:
2037: public int myrights(String mailbox)
2038: throws IOException
2039: {
2040: String tag = newTag();
2041: String command = MYRIGHTS + ' ' + quote(UTF7imap.encode(mailbox));
2042: sendCommand(tag, command);
2043: int ret = -1;
2044: while (true)
2045: {
2046: IMAPResponse response = readResponse();
2047: String id = response.getID();
2048: if (tag.equals(response.getTag()))
2049: {
2050: processAlerts(response);
2051: if (id == OK)
2052: {
2053: return ret;
2054: }
2055: else if (id == NO)
2056: {
2057: return -1;
2058: }
2059: else
2060: {
2061: throw new IMAPException(id, response.getText());
2062: }
2063: }
2064: else if (response.isUntagged())
2065: {
2066: if (MYRIGHTS.equals(response.getID()))
2067: {
2068: String text = response.getText();
2069: List args = parseACL(text, 0);
2070: ret = stringToRights((String) args.get(2));
2071: }
2072: else
2073: {
2074: asyncResponses.add(response);
2075: }
2076: }
2077: else
2078: {
2079: throw new IMAPException(id, response.getText());
2080: }
2081: }
2082: }
2083:
2084: private String rightsToString(int rights)
2085: {
2086: StringBuffer buf = new StringBuffer();
2087: if ((rights & RIGHTS_LOOKUP) != 0)
2088: {
2089: buf.append('l');
2090: }
2091: if ((rights & RIGHTS_READ) != 0)
2092: {
2093: buf.append('r');
2094: }
2095: if ((rights & RIGHTS_SEEN) != 0)
2096: {
2097: buf.append('s');
2098: }
2099: if ((rights & RIGHTS_WRITE) != 0)
2100: {
2101: buf.append('w');
2102: }
2103: if ((rights & RIGHTS_INSERT) != 0)
2104: {
2105: buf.append('i');
2106: }
2107: if ((rights & RIGHTS_POST) != 0)
2108: {
2109: buf.append('p');
2110: }
2111: if ((rights & RIGHTS_CREATE) != 0)
2112: {
2113: buf.append('c');
2114: }
2115: if ((rights & RIGHTS_DELETE) != 0)
2116: {
2117: buf.append('d');
2118: }
2119: if ((rights & RIGHTS_ADMIN) != 0)
2120: {
2121: buf.append('a');
2122: }
2123: return buf.toString();
2124: }
2125:
2126: private int stringToRights(String text)
2127: {
2128: int ret = 0;
2129: int len = text.length();
2130: for (int i = 0; i < len; i++)
2131: {
2132: switch (text.charAt(i))
2133: {
2134: case 'l':
2135: ret |= RIGHTS_LOOKUP;
2136: break;
2137: case 'r':
2138: ret |= RIGHTS_READ;
2139: break;
2140: case 's':
2141: ret |= RIGHTS_SEEN;
2142: break;
2143: case 'w':
2144: ret |= RIGHTS_WRITE;
2145: break;
2146: case 'i':
2147: ret |= RIGHTS_INSERT;
2148: break;
2149: case 'p':
2150: ret |= RIGHTS_POST;
2151: break;
2152: case 'c':
2153: ret |= RIGHTS_CREATE;
2154: break;
2155: case 'd':
2156: ret |= RIGHTS_DELETE;
2157: break;
2158: case 'a':
2159: ret |= RIGHTS_ADMIN;
2160: break;
2161: }
2162: }
2163: return ret;
2164: }
2165:
2166:
2170: private List parseACL(String text, int prolog)
2171: {
2172: int len = text.length();
2173: boolean inQuotes = false;
2174: List ret = new ArrayList();
2175: StringBuffer buf = new StringBuffer();
2176: for (int i = 0; i < len; i++)
2177: {
2178: char c = text.charAt(i);
2179: switch (c)
2180: {
2181: case '"':
2182: inQuotes = !inQuotes;
2183: break;
2184: case ' ':
2185: if (inQuotes || ret.size() > prolog)
2186: {
2187: buf.append(c);
2188: }
2189: else
2190: {
2191: ret.add(UTF7imap.decode(buf.toString()));
2192: buf.setLength(0);
2193: }
2194: break;
2195: default:
2196: buf.append(c);
2197: }
2198: }
2199: ret.add(buf.toString());
2200: return ret;
2201: }
2202:
2203:
2209: public Quota setquota(String quotaRoot, Quota.Resource[] resources)
2210: throws IOException
2211: {
2212:
2213: StringBuffer resourceLimits = new StringBuffer();
2214: if (resources != null)
2215: {
2216: for (int i = 0; i < resources.length; i++)
2217: {
2218: if (i > 0)
2219: {
2220: resourceLimits.append(' ');
2221: }
2222: resourceLimits.append(resources[i].toString());
2223: }
2224: }
2225: String tag = newTag();
2226: String command = SETQUOTA + ' ' + quote(UTF7imap.encode(quotaRoot)) +
2227: ' ' + resourceLimits.toString();
2228: sendCommand(tag, command);
2229: Quota ret = null;
2230: while (true)
2231: {
2232: IMAPResponse response = readResponse();
2233: String id = response.getID();
2234: if (tag.equals(response.getTag()))
2235: {
2236: processAlerts(response);
2237: if (id == OK)
2238: {
2239: return ret;
2240: }
2241: else if (id == NO)
2242: {
2243: return null;
2244: }
2245: else
2246: {
2247: throw new IMAPException(id, response.getText());
2248: }
2249: }
2250: else if (response.isUntagged())
2251: {
2252: if (QUOTA.equals(response.getID()))
2253: {
2254: ret = new Quota(response.getText());
2255: }
2256: else
2257: {
2258: asyncResponses.add(response);
2259: }
2260: }
2261: else
2262: {
2263: throw new IMAPException(id, response.getText());
2264: }
2265: }
2266: }
2267:
2268:
2272: public Quota getquota(String quotaRoot)
2273: throws IOException
2274: {
2275: String tag = newTag();
2276: String command = GETQUOTA + ' ' + quote(UTF7imap.encode(quotaRoot));
2277: sendCommand(tag, command);
2278: Quota ret = null;
2279: while (true)
2280: {
2281: IMAPResponse response = readResponse();
2282: String id = response.getID();
2283: if (tag.equals(response.getTag()))
2284: {
2285: processAlerts(response);
2286: if (id == OK)
2287: {
2288: return ret;
2289: }
2290: else if (id == NO)
2291: {
2292: return null;
2293: }
2294: else
2295: {
2296: throw new IMAPException(id, response.getText());
2297: }
2298: }
2299: else if (response.isUntagged())
2300: {
2301: if (QUOTA.equals(response.getID()))
2302: {
2303: ret = new Quota(response.getText());
2304: }
2305: else
2306: {
2307: asyncResponses.add(response);
2308: }
2309: }
2310: else
2311: {
2312: throw new IMAPException(id, response.getText());
2313: }
2314: }
2315: }
2316:
2317:
2321: public Quota[] getquotaroot(String mailbox)
2322: throws IOException
2323: {
2324: String tag = newTag();
2325: String command = GETQUOTAROOT + ' ' + quote(UTF7imap.encode(mailbox));
2326: sendCommand(tag, command);
2327: List acc = new ArrayList();
2328: while (true)
2329: {
2330: IMAPResponse response = readResponse();
2331: String id = response.getID();
2332: if (tag.equals(response.getTag()))
2333: {
2334: processAlerts(response);
2335: if (id == OK)
2336: {
2337: Quota[] ret = new Quota[acc.size()];
2338: acc.toArray(ret);
2339: return ret;
2340: }
2341: else if (id == NO)
2342: {
2343: return null;
2344: }
2345: else
2346: {
2347: throw new IMAPException(id, response.getText());
2348: }
2349: }
2350: else if (response.isUntagged())
2351: {
2352: if (QUOTA.equals(response.getID()))
2353: {
2354: acc.add(new Quota(response.getText()));
2355: }
2356: else
2357: {
2358: asyncResponses.add(response);
2359: }
2360: }
2361: else
2362: {
2363: throw new IMAPException(id, response.getText());
2364: }
2365: }
2366: }
2367:
2368:
2369:
2370:
2373: static String stripQuotes(String text)
2374: {
2375: if (text.charAt(0) == '"')
2376: {
2377: int len = text.length();
2378: if (text.charAt(len - 1) == '"')
2379: {
2380: return text.substring(1, len - 1);
2381: }
2382: }
2383: return text;
2384: }
2385:
2386:
2389: static String quote(String text)
2390: {
2391: if (text.length() == 0 || text.indexOf(' ') != -1)
2392: {
2393: StringBuffer buffer = new StringBuffer();
2394: buffer.append('"');
2395: buffer.append(text);
2396: buffer.append('"');
2397: return buffer.toString();
2398: }
2399: return text;
2400: }
2401:
2402: }