/[classpath]/inetlib/source/gnu/inet/imap/IMAPConnection.java
ViewVC logotype

Diff of /inetlib/source/gnu/inet/imap/IMAPConnection.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by dog, Sun Oct 19 08:51:37 2003 UTC revision 1.2 by dog, Sun Oct 19 16:16:50 2003 UTC
# Line 78  public class IMAPConnection implements I Line 78  public class IMAPConnection implements I
78     */     */
79    protected static final String US_ASCII = "US-ASCII";    protected static final String US_ASCII = "US-ASCII";
80    
81          /**          /**
82           * The default IMAP port.           * The default IMAP port.
83           */           */
84          protected static final int DEFAULT_PORT = 143;    protected static final int DEFAULT_PORT = 143;
85    
86    /**    /**
87     * The socket used for communication with the server.     * The socket used for communication with the server.
# Line 133  public class IMAPConnection implements I Line 133  public class IMAPConnection implements I
133    {    {
134      this(host, port, -1, -1, false);      this(host, port, -1, -1, false);
135    }    }
136      
137    /**    /**
138     * Creates a new connection.     * Creates a new connection.
139           * @param host the name of the host to connect to           * @param host the name of the host to connect to
140           * @param port the port to connect to           * @param port the port to connect to
141     */     */
142    public IMAPConnection(String host, int port,    public IMAPConnection(String host, int port,
143        int connectionTimeout, int timeout, boolean debug)                          int connectionTimeout, int timeout, boolean debug)
144      throws UnknownHostException, IOException      throws UnknownHostException, IOException
145    {    {
146      this.debug = debug;      this.debug = debug;
147      // TODO connectionTimeout      // TODO connectionTimeout
148                    
149                  if (port<0)      if (port < 0)
150                          port = DEFAULT_PORT;        port = DEFAULT_PORT;
151        
152      // Set up socket      // Set up socket
153      socket = new Socket(host, port);      socket = new Socket(host, port);
154      if (timeout>0)      if (timeout > 0)
155        socket.setSoTimeout(timeout);        socket.setSoTimeout(timeout);
156        
157                  InputStream in = socket.getInputStream();      InputStream in = socket.getInputStream();
158                  in = new BufferedInputStream(in);        in = new BufferedInputStream(in);
159      this.in = new IMAPResponseTokenizer(in);        this.in = new IMAPResponseTokenizer(in);
160                  OutputStream out = socket.getOutputStream();      OutputStream out = socket.getOutputStream();
161                  out = new BufferedOutputStream(out);        out = new BufferedOutputStream(out);
162      this.out = new CRLFOutputStream(out);        this.out = new CRLFOutputStream(out);
163                    
164      asyncResponses = new ArrayList();        asyncResponses = new ArrayList();
165      alerts = new ArrayList();        alerts = new ArrayList();
166    }    }
167    
168    /**    /**
# Line 176  public class IMAPConnection implements I Line 176  public class IMAPConnection implements I
176    /**    /**
177     * Returns a new tag for a command.     * Returns a new tag for a command.
178     */     */
179    protected String newTag() {    protected String newTag()
180      {
181      return new StringBuffer(TAG_PREFIX).append(++tagIndex).toString();      return new StringBuffer(TAG_PREFIX).append(++tagIndex).toString();
182    }    }
183    
184    /**    /**
185     * Sends the specified IMAP tagged command to the server.     * Sends the specified IMAP tagged command to the server.
186     */     */
187    protected void sendCommand(String tag, String command)    protected void sendCommand(String tag, String command) throws IOException
     throws IOException  
188    {    {
189      if (debug)      if (debug)
190                  {      {
191                          Logger logger = Logger.getInstance();        Logger logger = Logger.getInstance();
192        logger.log("imap", "> "+tag+" "+command);          logger.log("imap", "> " + tag + " " + command);
193                  }      }
194      String cmd = new StringBuffer(tag)      String cmd = new StringBuffer(tag).append(' ').append(command).toString();
       .append(' ')  
       .append(command)  
       .toString();  
195      out.write(cmd);      out.write(cmd);
196                  out.writeln();      out.writeln();
197                  out.flush();      out.flush();
198    }    }
199    
200    /**    /**
# Line 206  public class IMAPConnection implements I Line 203  public class IMAPConnection implements I
203     * @return true if OK was received, or false if NO was received     * @return true if OK was received, or false if NO was received
204     * @exception IOException if BAD was received or an I/O error occurred     * @exception IOException if BAD was received or an I/O error occurred
205     */     */
206    protected boolean invokeSimpleCommand(String command)    protected boolean invokeSimpleCommand(String command) throws IOException
     throws IOException  
207    {    {
208      String tag = newTag();      String tag = newTag();
209      sendCommand(tag, command);        sendCommand(tag, command);
210      while (true)      while (true)
211      {      {
212        IMAPResponse response = readResponse();        IMAPResponse response = readResponse();
# Line 218  public class IMAPConnection implements I Line 214  public class IMAPConnection implements I
214        if (tag.equals(response.getTag()))        if (tag.equals(response.getTag()))
215        {        {
216          processAlerts(response);          processAlerts(response);
217          if (id==OK)          if (id == OK)
218            return true;            return true;
219          else if (id==NO)          else if (id == NO)
220            return false;            return false;
221          else          else
222            throw new IMAPException(id, response.getText());            throw new IMAPException(id, response.getText());
223        }        }
224        else if (response.isUntagged())        else if (response.isUntagged())
225          asyncResponses.add(response);            asyncResponses.add(response);
226        else        else
227          throw new IMAPException(id, response.getText());          throw new IMAPException(id, response.getText());
228      }      }
# Line 241  public class IMAPConnection implements I Line 237  public class IMAPConnection implements I
237     * <li>An untagged error response</li>     * <li>An untagged error response</li>
238     * <li>A continuation response</li>     * <li>A continuation response</li>
239     */     */
240    protected IMAPResponse readResponse()    protected IMAPResponse readResponse() throws IOException
     throws IOException  
241    {    {
242      IMAPResponse response = in.next();      IMAPResponse response = in.next();
243      if (debug)      if (debug)
244      {      {
245                          Logger logger = Logger.getInstance();        Logger logger = Logger.getInstance();
246        if (ansiDebug)        if (ansiDebug)
247          logger.log("imap", "< "+response.toANSIString());            logger.log("imap", "< " + response.toANSIString());
248        else        else
249          logger.log("imap", "< "+response.toString());            logger.log("imap", "< " + response.toString());
250      }      }
251      return response;      return response;
252    }    }
# Line 261  public class IMAPConnection implements I Line 256  public class IMAPConnection implements I
256    private void processAlerts(IMAPResponse response)    private void processAlerts(IMAPResponse response)
257    {    {
258      List code = response.getResponseCode();      List code = response.getResponseCode();
259      if (code!=null && code.contains(ALERT))      if (code != null && code.contains(ALERT))
260        alerts.add(response.getText());        alerts.add(response.getText());
261    }    }
262    
263    boolean alertsPending()    boolean alertsPending()
264    {    {
265      return (alerts.size()>0);      return (alerts.size() > 0);
266    }    }
267    
268    String[] getAlerts()    String[]getAlerts()
269    {    {
270      String[] a = new String[alerts.size()];      String[]a = new String[alerts.size()];
271      alerts.toArray(a);      alerts.toArray(a);
272      alerts.clear(); // flush      alerts.clear();             // flush
273      return a;      return a;
274    }    }
275    
# Line 283  public class IMAPConnection implements I Line 278  public class IMAPConnection implements I
278    /**    /**
279     * Returns a list of the capabilities of the IMAP server.     * Returns a list of the capabilities of the IMAP server.
280     */     */
281    public List capability()    public List capability() throws IOException
     throws IOException  
282    {    {
283      String tag = newTag();      String tag = newTag();
284      sendCommand(tag, CAPABILITY);        sendCommand(tag, CAPABILITY);
285      while (true)      while (true)
286      {      {
287        IMAPResponse response = readResponse();        IMAPResponse response = readResponse();
# Line 295  public class IMAPConnection implements I Line 289  public class IMAPConnection implements I
289        if (tag.equals(response.getTag()))        if (tag.equals(response.getTag()))
290        {        {
291          processAlerts(response);          processAlerts(response);
292          if (id==OK)          if (id == OK)
293          {          {
294            // The capability "list" is actually contained in the response            // The capability "list" is actually contained in the response
295            // text.            // text.
296            String text = response.getText();            String text = response.getText();
297            List capabilities = new ArrayList();            List capabilities = new ArrayList();
298            int si = text.indexOf(' ');            int si = text.indexOf(' ');
299            while (si!=-1)            while (si != -1)
300            {            {
301              capabilities.add(text.substring(0, si));              capabilities.add(text.substring(0, si));
302              text = text.substring(si+1);              text = text.substring(si + 1);
303              si = text.indexOf(' ');              si = text.indexOf(' ');
304            }            }
305            if (text.length()>0)            if (text.length() > 0)
306              capabilities.add(text);                capabilities.add(text);
307            return capabilities;            return capabilities;
308          }          }
309          else          else
# Line 327  public class IMAPConnection implements I Line 321  public class IMAPConnection implements I
321     * If a change in mailbox state is detected, a new mailbox status is     * If a change in mailbox state is detected, a new mailbox status is
322     * returned, otherwise this method returns null.     * returned, otherwise this method returns null.
323     */     */
324    public MailboxStatus noop()    public MailboxStatus noop() throws IOException
     throws IOException  
325    {    {
326      String tag = newTag();      String tag = newTag();
327      sendCommand(tag, NOOP);        sendCommand(tag, NOOP);
328      boolean changed = false;      boolean changed = false;
329      MailboxStatus ms = new MailboxStatus();      MailboxStatus ms = new MailboxStatus();
330      Iterator asyncIterator = asyncResponses.iterator();      Iterator asyncIterator = asyncResponses.iterator();
# Line 341  public class IMAPConnection implements I Line 334  public class IMAPConnection implements I
334        // Process any asynchronous responses first        // Process any asynchronous responses first
335        if (asyncIterator.hasNext())        if (asyncIterator.hasNext())
336        {        {
337          response = (IMAPResponse)asyncIterator.next();          response = (IMAPResponse) asyncIterator.next();
338          asyncIterator.remove();          asyncIterator.remove();
339        }        }
340        else        else
341          response = readResponse();            response = readResponse();
342        String id = response.getID();        String id = response.getID();
343        if (response.isUntagged())        if (response.isUntagged())
344        {        {
# Line 354  public class IMAPConnection implements I Line 347  public class IMAPConnection implements I
347        else if (tag.equals(response.getTag()))        else if (tag.equals(response.getTag()))
348        {        {
349          processAlerts(response);          processAlerts(response);
350          if (id==OK)          if (id == OK)
351            return changed ? ms : null;            return changed ? ms : null;
352          else          else
353            throw new IMAPException(id, response.getText());            throw new IMAPException(id, response.getText());
# Line 369  public class IMAPConnection implements I Line 362  public class IMAPConnection implements I
362     * See RFC 2595 for details.     * See RFC 2595 for details.
363     * @return true if successful, false otherwise     * @return true if successful, false otherwise
364     */     */
365    public boolean starttls()    public boolean starttls() throws IOException
     throws IOException  
366    {    {
367      try      try
368      {      {
369        // Use SSLSocketFactory to negotiate a TLS session and wrap the        // Use SSLSocketFactory to negotiate a TLS session and wrap the
370                          // current socket.        // current socket.
371                          SSLSocketFactory factory =        SSLSocketFactory factory =
372                                  (SSLSocketFactory)SSLSocketFactory.getDefault();          (SSLSocketFactory) SSLSocketFactory.getDefault();
373    
374                          String tag = newTag();        String tag = newTag();
375                          sendCommand(tag, STARTTLS);          sendCommand(tag, STARTTLS);
376                          while (true)        while (true)
377                          {        {
378                                  IMAPResponse response = readResponse();          IMAPResponse response = readResponse();
379                                  if (response.isTagged() && tag.equals(response.getTag()))          if (response.isTagged() && tag.equals(response.getTag()))
380                                  {          {
381                                          processAlerts(response);            processAlerts(response);
382                                          String id = response.getID();            String id = response.getID();
383                                          if (id==OK)            if (id == OK)
384                                                  break; // negotiate TLS              break;              // negotiate TLS
385                                          else if (id==BAD)            else if (id == BAD)
386            return false;              return false;
387                                  }          }
388                                  else          else
389                                          asyncResponses.add(response);              asyncResponses.add(response);
390                          }        }
391                            
392                          socket = factory.createSocket(socket,        socket = factory.createSocket(socket,
393                                          socket.getInetAddress().getHostName(),                                      socket.getInetAddress().getHostName(),
394                                          socket.getPort(),                                      socket.getPort(), true);
395                                          true);  
396                                  InputStream in = socket.getInputStream();
397                          InputStream in = socket.getInputStream();        in = new BufferedInputStream(in);
398                          in = new BufferedInputStream(in);        this.in = new IMAPResponseTokenizer(in);
399                          this.in = new IMAPResponseTokenizer(in);        OutputStream out = socket.getOutputStream();
400                          OutputStream out = socket.getOutputStream();        out = new BufferedOutputStream(out);
401                          out = new BufferedOutputStream(out);        this.out = new CRLFOutputStream(out);
                         this.out = new CRLFOutputStream(out);  
402        return true;        return true;
403      }      }
404      catch (ClassNotFoundException e)      catch(ClassNotFoundException e)
405      {      {
406        return false; // No javax.net classes in runtime        return false;             // No javax.net classes in runtime
407      }      }
408    }    }
409    
# Line 422  public class IMAPConnection implements I Line 413  public class IMAPConnection implements I
413     * @param password the authentication credentials     * @param password the authentication credentials
414     * @return true if authentication was successful, false otherwise     * @return true if authentication was successful, false otherwise
415     */     */
416    public boolean login(String username, String password)    public boolean login(String username, String password) throws IOException
     throws IOException  
417    {    {
418      StringBuffer cmd = new StringBuffer(LOGIN);      StringBuffer cmd = new StringBuffer(LOGIN);
419      cmd.append(' ');        cmd.append(' ');
420      cmd.append(quote(username));        cmd.append(quote(username));
421      cmd.append(' ');        cmd.append(' ');
422      cmd.append(quote(password));        cmd.append(quote(password));
423      return invokeSimpleCommand(cmd.toString());        return invokeSimpleCommand(cmd.toString());
424    }    }
425    
426          /**          /**
427           * Authenticates the connection using the specified SASL mechanism,           * Authenticates the connection using the specified SASL mechanism,
428           * username, and password.           * username, and password.
429           * @param mechanism a SASL authentication mechanism, e.g. LOGIN, PLAIN,           * @param mechanism a SASL authentication mechanism, e.g. LOGIN, PLAIN,
# Line 442  public class IMAPConnection implements I Line 432  public class IMAPConnection implements I
432           * @param password the authentication credentials           * @param password the authentication credentials
433           * @return true if authentication was successful, false otherwise           * @return true if authentication was successful, false otherwise
434           */           */
435          public boolean authenticate(String mechanism, String username, String password)    public boolean authenticate(String mechanism, String username,
436                  throws IOException                                String password) throws IOException
437          {    {
438                  try      try
439                  {      {
440                          String[] m = new String[] { mechanism };        String[]m = new String[]
441                          CallbackHandler ch = new SaslCallbackHandler(username, password);        {
442                          // Avoid lengthy callback procedure for GNU Crypto        mechanism};
443                          Properties p = new Properties();        CallbackHandler ch = new SaslCallbackHandler(username, password);
444                          p.put("gnu.crypto.sasl.username", username);        // Avoid lengthy callback procedure for GNU Crypto
445                          p.put("gnu.crypto.sasl.password", password);        Properties p = new Properties();
446                          SaslClient sasl = Sasl.createSaslClient(m, null, "smtp",        p.put("gnu.crypto.sasl.username", username);
447                                          socket.getInetAddress().getHostName(), p, ch);        p.put("gnu.crypto.sasl.password", password);
448                                  SaslClient sasl = Sasl.createSaslClient(m, null, "smtp",
449                          StringBuffer cmd = new StringBuffer(AUTHENTICATE);                                                socket.getInetAddress().
450                          cmd.append(' ');                                                getHostName(), p, ch);
451                          cmd.append(mechanism);  
452                          if (sasl.hasInitialResponse())        StringBuffer cmd = new StringBuffer(AUTHENTICATE);
453                          {        cmd.append(' ');
454                                  cmd.append(' ');        cmd.append(mechanism);
455                                  byte[] init = sasl.evaluateChallenge(new byte[0]);        if (sasl.hasInitialResponse())
456                                  cmd.append(new String(init, US_ASCII));        {
457                          }          cmd.append(' ');
458                          String tag = newTag();          byte[]init = sasl.evaluateChallenge(new byte[0]);
459                          sendCommand(tag, cmd.toString());          cmd.append(new String(init, US_ASCII));
460                          while (true)        }
461                          {        String tag = newTag();
462                                  IMAPResponse response = readResponse();        sendCommand(tag, cmd.toString());
463                                  if (tag.equals(response.getTag()))        while (true)
464                                  {        {
465                                          processAlerts(response);          IMAPResponse response = readResponse();
466                                          String id = response.getID();          if (tag.equals(response.getTag()))
467                                          if (id==OK)          {
468                                          {            processAlerts(response);
469                                                  String qop = (String)sasl.getNegotiatedProperty(Sasl.QOP);            String id = response.getID();
470                                                  if ("auth-int".equalsIgnoreCase(qop)            if (id == OK)
471                                                                  || "auth-conf".equalsIgnoreCase(qop))            {
472                                                  {              String qop = (String) sasl.getNegotiatedProperty(Sasl.QOP);
473                                                          InputStream in = socket.getInputStream();              if ("auth-int".equalsIgnoreCase(qop)
474                                                          in = new BufferedInputStream(in);                  || "auth-conf".equalsIgnoreCase(qop))
475                                                          in = new SaslInputStream(sasl, in);              {
476                                                          this.in = new IMAPResponseTokenizer(in);                InputStream in = socket.getInputStream();
477                                                          OutputStream out = socket.getOutputStream();                in = new BufferedInputStream(in);
478                                                          out = new BufferedOutputStream(out);                in = new SaslInputStream(sasl, in);
479                                                          out = new SaslOutputStream(sasl, out);                this.in = new IMAPResponseTokenizer(in);
480                                                          this.out = new CRLFOutputStream(out);                OutputStream out = socket.getOutputStream();
481                                                  }                out = new BufferedOutputStream(out);
482                                                  return true;                out = new SaslOutputStream(sasl, out);
483                                          }                this.out = new CRLFOutputStream(out);
484                                          else if (id==NO)              }
485                                                  return false;              return true;
486                                          else if (id==BAD)            }
487                                                  throw new IMAPException(id, response.getText());            else if (id == NO)
488                                  }              return false;
489                                  else if (response.isContinuation())            else if (id == BAD)
490                                  {              throw new IMAPException(id, response.getText());
491                                          try          }
492                                          {          else if (response.isContinuation())
493                                                  byte[] c0 = response.getText().getBytes(US_ASCII);          {
494                                                  byte[] c1 = BASE64.decode(c0); // challenge            try
495                                                  byte[] r0 = sasl.evaluateChallenge(c1);            {
496                                                  byte[] r1 = BASE64.encode(r0); // response              byte[]c0 = response.getText().getBytes(US_ASCII);
497                                                  out.write(r1);              byte[]c1 = BASE64.decode(c0);       // challenge
498                                                  out.write(0x0d);              byte[]r0 = sasl.evaluateChallenge(c1);
499                                                  out.flush();              byte[]r1 = BASE64.encode(r0);       // response
500                                          }              out.write(r1);
501                                          catch (SaslException e)              out.writeln();
502                                          {              out.flush();
503                                                  // Error in SASL challenge evaluation - cancel exchange            }
504                                                  out.write(0x2a);            catch(SaslException e)
505                                                  out.write(0x0d);            {
506                                                  out.flush();              // Error in SASL challenge evaluation - cancel exchange
507                                          }              out.write(0x2a);
508                                  }              out.writeln();
509                                  else              out.flush();
510                                          asyncResponses.add(response);            }
511                          }          }
512                  }          else
513                  catch (SaslException e)            asyncResponses.add(response);
514                  {        }
515                          return false; // No provider for mechanism      }
516                  }      catch(SaslException e)
517                  catch (ClassNotFoundException e)      {
518                  {        return false;             // No provider for mechanism
519                          return false; // No javax.security.sasl classes      }
520                  }      catch(ClassNotFoundException e)
521          }      {
522                  return false;             // No javax.security.sasl classes
523        }
524      }
525    
526    /**    /**
527     * Login to the connection using the CRAM-MD5 authorization extension.     * Login to the connection using the CRAM-MD5 authorization extension.
528     * This method is fully documented in RFC 2195.     * This method is fully documented in RFC 2195.
# Line 571  public class IMAPConnection implements I Line 564  public class IMAPConnection implements I
564            System.arraycopy(digest, 0, r1, r0.length+1, digest.length);            System.arraycopy(digest, 0, r1, r0.length+1, digest.length);
565            byte[] r2 = BASE64.encode(r1);            byte[] r2 = BASE64.encode(r1);
566            out.write(r2);            out.write(r2);
567            out.write(0x0d);            out.writeln();
568                                          out.flush();                                          out.flush();
569          }          }
570          catch (NoSuchAlgorithmException e)          catch (NoSuchAlgorithmException e)
571          {          {
572            // No MD5 algorithm provider - cancel exchange            // No MD5 algorithm provider - cancel exchange
573            out.write(0x2a);            out.write(0x2a);
574            out.write(0x0d);            out.writeln();
575                                          out.flush();                                          out.flush();
576          }          }
577        }        }
# Line 636  public class IMAPConnection implements I Line 629  public class IMAPConnection implements I
629     * Logout this connection.     * Logout this connection.
630     * Underlying network resources will be freed.     * Underlying network resources will be freed.
631     */     */
632    public void logout()    public void logout() throws IOException
     throws IOException  
633    {    {
634      String tag = newTag();      String tag = newTag();
635      sendCommand(tag, LOGOUT);        sendCommand(tag, LOGOUT);
636      while (true)      while (true)
637      {      {
638        IMAPResponse response = readResponse();        IMAPResponse response = readResponse();
# Line 648  public class IMAPConnection implements I Line 640  public class IMAPConnection implements I
640        {        {
641          processAlerts(response);          processAlerts(response);
642          String id = response.getID();          String id = response.getID();
643          if (id==OK)          if (id == OK)
644          {          {
645            socket.close();            socket.close();
646            return;            return;
647          }          }
648          else          else
649            throw new IMAPException(id, response.getText());              throw new IMAPException(id, response.getText());
650        }        }
651        else        else
652          asyncResponses.add(response);          asyncResponses.add(response);
# Line 667  public class IMAPConnection implements I Line 659  public class IMAPConnection implements I
659     * @param mailbox the mailbox name     * @param mailbox the mailbox name
660     * @return a MailboxStatus containing the state of the selected mailbox     * @return a MailboxStatus containing the state of the selected mailbox
661     */     */
662    public MailboxStatus select(String mailbox)    public MailboxStatus select(String mailbox) throws IOException
     throws IOException  
663    {    {
664      return selectImpl(mailbox, SELECT);      return selectImpl(mailbox, SELECT);
665    }    }
# Line 679  public class IMAPConnection implements I Line 670  public class IMAPConnection implements I
670     * @param mailbox the mailbox name     * @param mailbox the mailbox name
671     * @return a MailboxStatus containing the state of the selected mailbox     * @return a MailboxStatus containing the state of the selected mailbox
672     */     */
673    public MailboxStatus examine(String mailbox)    public MailboxStatus examine(String mailbox) throws IOException
     throws IOException  
674    {    {
675      return selectImpl(mailbox, EXAMINE);      return selectImpl(mailbox, EXAMINE);
676    }    }
# Line 689  public class IMAPConnection implements I Line 679  public class IMAPConnection implements I
679      throws IOException      throws IOException
680    {    {
681      String tag = newTag();      String tag = newTag();
682      sendCommand(tag, new StringBuffer(command)        sendCommand(tag,
683          .append(' ')                    new StringBuffer(command).append(' ').
684          .append(quote(UTF7imap.encode(mailbox)))                    append(quote(UTF7imap.encode(mailbox))).toString());
         .toString());  
685      MailboxStatus ms = new MailboxStatus();      MailboxStatus ms = new MailboxStatus();
686      while (true)      while (true)
687      {      {
# Line 706  public class IMAPConnection implements I Line 695  public class IMAPConnection implements I
695        else if (tag.equals(response.getTag()))        else if (tag.equals(response.getTag()))
696        {        {
697          processAlerts(response);          processAlerts(response);
698          if (id==OK)          if (id == OK)
699          {          {
700            List rc = response.getResponseCode();            List rc = response.getResponseCode();
701            if (rc.size()>0 && rc.get(0)==READ_WRITE)            if (rc.size() > 0 && rc.get(0) == READ_WRITE)
702              ms.readWrite = true;              ms.readWrite = true;
703            return ms;            return ms;
704          }          }
# Line 722  public class IMAPConnection implements I Line 711  public class IMAPConnection implements I
711    }    }
712    
713    protected boolean updateMailboxStatus(MailboxStatus ms,    protected boolean updateMailboxStatus(MailboxStatus ms,
714        String id, IMAPResponse response)                                          String id, IMAPResponse response)
715      throws IOException      throws IOException
716    {    {
717      if (id==OK)      if (id == OK)
718      {      {
719        boolean changed = false;        boolean changed = false;
720        List rc = response.getResponseCode();        List rc = response.getResponseCode();
721        int len = (rc==null) ? 0 : rc.size();        int len = (rc == null) ? 0 : rc.size();
722        for (int i=0; i<len; i++)        for (int i = 0; i < len; i++)
723        {        {
724          Object ocmd = rc.get(i);          Object ocmd = rc.get(i);
725          if (ocmd instanceof String)          if (ocmd instanceof String)
726          {          {
727            String cmd = (String)ocmd;            String cmd = (String) ocmd;
728            if (i+1<len)            if (i + 1 < len)
729            {            {
730              Object oparam = rc.get(i+1);              Object oparam = rc.get(i + 1);
731              if (oparam instanceof String)              if (oparam instanceof String)
732              {              {
733                String param = (String)oparam;                String param = (String) oparam;
734                try                  try
735                {                {
736                  if (cmd==UNSEEN)                  if (cmd == UNSEEN)
737                  {                  {
738                    ms.firstUnreadMessage = Integer.parseInt(param);                    ms.firstUnreadMessage = Integer.parseInt(param);
739                    i++;                    i++;
740                    changed = true;                    changed = true;
741                  }                  }
742                  else if (cmd==UIDVALIDITY)                  else if (cmd == UIDVALIDITY)
743                  {                  {
744                    ms.uidValidity = Integer.parseInt(param);                    ms.uidValidity = Integer.parseInt(param);
745                    i++;                    i++;
746                    changed = true;                    changed = true;
747                  }                  }
748                }                }
749                catch (NumberFormatException e)                catch(NumberFormatException e)
750                {                {
751                  throw new ProtocolException("Illegal "+cmd+" value: "+                  throw new ProtocolException("Illegal " + cmd +
752                      param);                                              " value: " + param);
753                }                }
754              }              }
755              else if (oparam instanceof List)              else if (oparam instanceof List)
756              {              {
757                if (cmd==PERMANENTFLAGS)                if (cmd == PERMANENTFLAGS)
758                {                {
759                  ms.permanentFlags = (List)oparam;                  ms.permanentFlags = (List) oparam;
760                  i++;                  i++;
761                  changed = true;                  changed = true;
762                }                }
# Line 777  public class IMAPConnection implements I Line 766  public class IMAPConnection implements I
766        }        }
767        return changed;        return changed;
768      }      }
769      else if (id==EXISTS)      else if (id == EXISTS)
770      {      {
771        ms.messageCount = response.getCount();        ms.messageCount = response.getCount();
772        return true;        return true;
773      }      }
774      else if (id==RECENT)      else if (id == RECENT)
775      {      {
776        ms.newMessageCount = response.getCount();        ms.newMessageCount = response.getCount();
777        return true;        return true;
778      }      }
779      else if (id==FLAGS)      else if (id == FLAGS)
780      {      {
781        ms.flags = response.getResponseCode();        ms.flags = response.getResponseCode();
782        return true;        return true;
# Line 801  public class IMAPConnection implements I Line 790  public class IMAPConnection implements I
790     * @param mailbox the mailbox name     * @param mailbox the mailbox name
791     * @return true if the mailbox was successfully created, false otherwise     * @return true if the mailbox was successfully created, false otherwise
792     */     */
793    public boolean create(String mailbox)    public boolean create(String mailbox) throws IOException
     throws IOException  
794    {    {
795      return invokeSimpleCommand(new StringBuffer(CREATE)      return invokeSimpleCommand(new StringBuffer(CREATE).append(' ').
796          .append(' ')                                 append(quote(UTF7imap.encode(mailbox))).
797          .append(quote(UTF7imap.encode(mailbox)))                                 toString());
         .toString());  
798    }    }
799    
800    /**    /**
# Line 815  public class IMAPConnection implements I Line 802  public class IMAPConnection implements I
802     * @param mailbox the mailbox name     * @param mailbox the mailbox name
803     * @return true if the mailbox was successfully deleted, false otherwise     * @return true if the mailbox was successfully deleted, false otherwise
804     */     */
805    public boolean delete(String mailbox)    public boolean delete(String mailbox) throws IOException
     throws IOException  
806    {    {
807      return invokeSimpleCommand(new StringBuffer(DELETE)      return invokeSimpleCommand(new StringBuffer(DELETE).append(' ').
808          .append(' ')                                 append(quote(UTF7imap.encode(mailbox))).
809          .append(quote(UTF7imap.encode(mailbox)))                                 toString());
         .toString());  
810    }    }
811    
812    /**    /**
# Line 830  public class IMAPConnection implements I Line 815  public class IMAPConnection implements I
815     * @param target the target mailbox name     * @param target the target mailbox name
816     * @return true if the mailbox was successfully renamed, false otherwise     * @return true if the mailbox was successfully renamed, false otherwise
817     */     */
818    public boolean rename(String source, String target)    public boolean rename(String source, String target) throws IOException
     throws IOException  
819    {    {
820      return invokeSimpleCommand(new StringBuffer(RENAME)      return invokeSimpleCommand(new StringBuffer(RENAME).append(' ').
821          .append(' ')                                 append(quote(UTF7imap.encode(source))).
822          .append(quote(UTF7imap.encode(source)))                                 append(' ').
823          .append(' ')                                 append(quote(UTF7imap.encode(target))).
824          .append(quote(UTF7imap.encode(target)))                                 toString());
         .toString());  
825    }    }
826    
827    /**    /**
# Line 847  public class IMAPConnection implements I Line 830  public class IMAPConnection implements I
830     * @param mailbox the mailbox name     * @param mailbox the mailbox name
831     * @return true if the mailbox was successfully subscribed, false otherwise     * @return true if the mailbox was successfully subscribed, false otherwise
832     */     */
833    public boolean subscribe(String mailbox)    public boolean subscribe(String mailbox) throws IOException
     throws IOException  
834    {    {
835      return invokeSimpleCommand(new StringBuffer(SUBSCRIBE)      return invokeSimpleCommand(new StringBuffer(SUBSCRIBE).append(' ').
836          .append(' ')                                 append(quote(UTF7imap.encode(mailbox))).
837          .append(quote(UTF7imap.encode(mailbox)))                                 toString());
         .toString());  
838    }    }
839    
840    /**    /**
# Line 862  public class IMAPConnection implements I Line 843  public class IMAPConnection implements I
843     * @param mailbox the mailbox name     * @param mailbox the mailbox name
844     * @return true if the mailbox was successfully unsubscribed, false otherwise     * @return true if the mailbox was successfully unsubscribed, false otherwise
845     */     */
846    public boolean unsubscribe(String mailbox)    public boolean unsubscribe(String mailbox) throws IOException
     throws IOException  
847    {    {
848      return invokeSimpleCommand(new StringBuffer(UNSUBSCRIBE)      return invokeSimpleCommand(new StringBuffer(UNSUBSCRIBE).append(' ').
849          .append(' ')                                 append(quote(UTF7imap.encode(mailbox))).
850          .append(quote(UTF7imap.encode(mailbox)))                                 toString());
         .toString());  
851    }    }
852    
853    /**    /**
# Line 878  public class IMAPConnection implements I Line 857  public class IMAPConnection implements I
857     * defined     * defined
858     * @param mailbox a mailbox name, possibly including IMAP wildcards     * @param mailbox a mailbox name, possibly including IMAP wildcards
859     */     */
860    public ListEntry[] list(String reference, String mailbox)    public ListEntry[] list(String reference, String mailbox) throws IOException
     throws IOException  
861    {    {
862      return listImpl(LIST, reference, mailbox);      return listImpl(LIST, reference, mailbox);
863    }    }
# Line 888  public class IMAPConnection implements I Line 866  public class IMAPConnection implements I
866     * Returns a subset of subscribed names.     * Returns a subset of subscribed names.
867     * @see #list     * @see #list
868     */     */
869    public ListEntry[] lsub(String reference, String mailbox)    public ListEntry[] lsub(String reference, String mailbox) throws IOException
     throws IOException  
870    {    {
871      return listImpl(LSUB, reference, mailbox);      return listImpl(LSUB, reference, mailbox);
872    }    }
873    
874    protected ListEntry[] listImpl(String command, String reference,    protected ListEntry[] listImpl(String command, String reference,
875        String mailbox)                                   String mailbox) throws IOException
     throws IOException  
876    {    {
877      if (reference==null)      if (reference == null)
878        reference = "";        reference = "";
879      if (mailbox==null)      if (mailbox == null)
880        mailbox = "";        mailbox = "";
881      String tag = newTag();      String tag = newTag();
882      sendCommand(tag, new StringBuffer(command)        sendCommand(tag,
883          .append(' ')                    new StringBuffer(command).append(' ').
884          .append(quote(UTF7imap.encode(reference)))                    append(quote(UTF7imap.encode(reference))).append(' ').
885          .append(' ')                    append(quote(UTF7imap.encode(mailbox))).toString());
         .append(quote(UTF7imap.encode(mailbox)))  
         .toString());  
886      List acc = new ArrayList();      List acc = new ArrayList();
887      while (true)      while (true)
888      {      {
# Line 920  public class IMAPConnection implements I Line 894  public class IMAPConnection implements I
894          {          {
895            List code = response.getResponseCode();            List code = response.getResponseCode();
896            String text = response.getText();            String text = response.getText();
897              
898            // Populate entry attributes with the interned versions            // Populate entry attributes with the interned versions
899            // of the response code.            // of the response code.
900            // NB IMAP servers do not necessarily pay attention to case.            // NB IMAP servers do not necessarily pay attention to case.
# Line 929  public class IMAPConnection implements I Line 903  public class IMAPConnection implements I
903            boolean noselect = false;            boolean noselect = false;
904            boolean marked = false;            boolean marked = false;
905            boolean unmarked = false;            boolean unmarked = false;
906            for (int i=0; i<alen; i++)            for (int i = 0; i < alen; i++)
907            {            {
908              String attribute = (String)code.get(i);              String attribute = (String) code.get(i);
909              if (attribute.equalsIgnoreCase(LIST_NOINFERIORS))              if (attribute.equalsIgnoreCase(LIST_NOINFERIORS))
910                noinferiors = true;                  noinferiors = true;
911              else if (attribute.equalsIgnoreCase(LIST_NOSELECT))              else if (attribute.equalsIgnoreCase(LIST_NOSELECT))
912                noselect = true;                  noselect = true;
913              else if (attribute.equalsIgnoreCase(LIST_MARKED))              else if (attribute.equalsIgnoreCase(LIST_MARKED))
914                marked = true;                  marked = true;
915              else if (attribute.equalsIgnoreCase(LIST_UNMARKED))              else if (attribute.equalsIgnoreCase(LIST_UNMARKED))
916                unmarked = true;                  unmarked = true;
917            }            }
918            int si = text.indexOf(' ');            int si = text.indexOf(' ');
919            char delimiter='\u0000';            char delimiter = '\u0000';
920            String d = text.substring(0, si);            String d = text.substring(0, si);
921            if (d.equalsIgnoreCase(NIL))            if (d.equalsIgnoreCase(NIL))
922              delimiter = stripQuotes(d).charAt(0);              delimiter = stripQuotes(d).charAt(0);
923            String mbox = stripQuotes(text.substring(si+1));            String mbox = stripQuotes(text.substring(si + 1));
924            mbox = UTF7imap.decode(mbox);            mbox = UTF7imap.decode(mbox);
925            ListEntry entry = new ListEntry(mbox, delimiter, noinferiors,            ListEntry entry = new ListEntry(mbox, delimiter, noinferiors,
926                noselect, marked, unmarked);                                            noselect, marked, unmarked);
927            acc.add(entry);            acc.add(entry);
928          }          }
929          else          else
# Line 958  public class IMAPConnection implements I Line 932  public class IMAPConnection implements I
932        else if (tag.equals(response.getTag()))        else if (tag.equals(response.getTag()))
933        {        {
934          processAlerts(response);          processAlerts(response);
935          if (id==OK)          if (id == OK)
936          {          {
937            ListEntry[] entries = new ListEntry[acc.size()];            ListEntry[]entries = new ListEntry[acc.size()];
938            acc.toArray(entries);            acc.toArray(entries);
939            return entries;            return entries;
940          }          }
# Line 975  public class IMAPConnection implements I Line 949  public class IMAPConnection implements I
949    /**    /**
950     * Requests the status of the specified mailbox.     * Requests the status of the specified mailbox.
951     */     */
952    public MailboxStatus status(String mailbox, String[] statusNames)    public MailboxStatus status(String mailbox, String[]statusNames)
953      throws IOException      throws IOException
954    {    {
955      String tag = newTag();      String tag = newTag();
956      StringBuffer buffer = new StringBuffer(STATUS)      StringBuffer buffer =
957        .append(' ')        new StringBuffer(STATUS).append(' ').
958        .append(quote(UTF7imap.encode(mailbox)))        append(quote(UTF7imap.encode(mailbox))).append(' ').append('(');
959        .append(' ')      for (int i = 0; i < statusNames.length; i++)
       .append('(');  
     for (int i=0; i<statusNames.length; i++)  
960      {      {
961        if (i>0)        if (i > 0)
962          buffer.append(' ');          buffer.append(' ');
963        buffer.append(statusNames[i]);        buffer.append(statusNames[i]);
964      }      }
# Line 999  public class IMAPConnection implements I Line 971  public class IMAPConnection implements I
971        String id = response.getID();        String id = response.getID();
972        if (response.isUntagged())        if (response.isUntagged())
973        {        {
974          if (id==STATUS)          if (id == STATUS)
975          {          {
976            List code = response.getResponseCode();            List code = response.getResponseCode();
977            int last = code.size()-1;            int last = code.size() - 1;
978            for (int i=0; i<last; i+=2)            for (int i = 0; i < last; i += 2)
979            {            {
980              try              try
981              {              {
982                String statusName = ((String)code.get(i)).intern();                String statusName = ((String) code.get(i)).intern();
983                int value = Integer.parseInt((String)code.get(i+1));                int value = Integer.parseInt((String) code.get(i + 1));
984                if (statusName==MESSAGES)                if (statusName == MESSAGES)
985                  ms.messageCount = value;                  ms.messageCount = value;
986                else if (statusName==RECENT)                else if (statusName == RECENT)
987                  ms.newMessageCount = value;                  ms.newMessageCount = value;
988                else if (statusName==UIDNEXT)                else if (statusName == UIDNEXT)
989                  ms.uidNext = value;                  ms.uidNext = value;
990                else if (statusName==UIDVALIDITY)                else if (statusName == UIDVALIDITY)
991                  ms.uidValidity = value;                  ms.uidValidity = value;
992                else if (statusName==UNSEEN)                else if (statusName == UNSEEN)
993                  ms.firstUnreadMessage = value;                  ms.firstUnreadMessage = value;
994              }              }
995              catch (NumberFormatException e)              catch(NumberFormatException e)
996              {              {
997                throw new IMAPException(id, "Invalid code: "+code);                throw new IMAPException(id, "Invalid code: " + code);
998              }              }
999            }            }
1000          }          }
# Line 1032  public class IMAPConnection implements I Line 1004  public class IMAPConnection implements I
1004        else if (tag.equals(response.getTag()))        else if (tag.equals(response.getTag()))
1005        {        {
1006          processAlerts(response);          processAlerts(response);
1007          if (id==OK)          if (id == OK)
1008            return ms;            return ms;
1009          else          else
1010            throw new IMAPException(id, response.getText());            throw new IMAPException(id, response.getText());
# Line 1051  public class IMAPConnection implements I Line 1023  public class IMAPConnection implements I
1023     * @param content the message body (including headers)     * @param content the message body (including headers)
1024     * @return true if successful, false if error in flags/text     * @return true if successful, false if error in flags/text
1025     */     */
1026    public boolean append(String mailbox, String[] flags, byte[] content)    public boolean append(String mailbox, String[]flags, byte[]content)
1027      throws IOException      throws IOException
1028    {    {
1029      String tag = newTag();      String tag = newTag();
1030      StringBuffer buffer = new StringBuffer(APPEND)      StringBuffer buffer =
1031        .append(' ')        new StringBuffer(APPEND).append(' ').
1032        .append(quote(UTF7imap.encode(mailbox)))        append(quote(UTF7imap.encode(mailbox))).append(' ');
1033        .append(' ');      if (flags != null)
     if (flags!=null)  
1034      {      {
1035        buffer.append('(');        buffer.append('(');
1036        for (int i=0; i<flags.length; i++)        for (int i = 0; i < flags.length; i++)
1037        {        {
1038          if (i>0)          if (i > 0)
1039            buffer.append(' ');            buffer.append(' ');
1040          buffer.append(flags[i]);          buffer.append(flags[i]);
1041        }        }
# Line 1078  public class IMAPConnection implements I Line 1049  public class IMAPConnection implements I
1049      IMAPResponse response = readResponse();      IMAPResponse response = readResponse();
1050      if (!response.isContinuation())      if (!response.isContinuation())
1051        throw new IMAPException(response.getID(), response.getText());        throw new IMAPException(response.getID(), response.getText());
1052      out.write(content); // write the message body      out.write(content);         // write the message body
1053      out.write(0x0a);      out.writeln();
     out.write(0x0d); // write CRLF  
1054      out.flush();      out.flush();
1055      while (true)      while (true)
1056      {      {
1057        response = readResponse();        response = readResponse();
1058        String id = response.getID();        String id = response.getID();
1059        if (tag.equals(response.getTag())) {        if (tag.equals(response.getTag()))
1060          {
1061          processAlerts(response);          processAlerts(response);
1062          if (id==OK)          if (id == OK)
1063            return true;            return true;
1064          else if (id==NO)          else if (id == NO)
1065            return false;            return false;
1066          else          else
1067            throw new IMAPException(id, response.getText());            throw new IMAPException(id, response.getText());
# Line 1105  public class IMAPConnection implements I Line 1076  public class IMAPConnection implements I
1076    /**    /**
1077     * Request a checkpoint of the currently selected mailbox.     * Request a checkpoint of the currently selected mailbox.
1078     */     */
1079    public void check()    public void check() throws IOException
     throws IOException  
1080    {    {
1081      invokeSimpleCommand(CHECK);      invokeSimpleCommand(CHECK);
1082    }    }
# Line 1116  public class IMAPConnection implements I Line 1086  public class IMAPConnection implements I
1086     * and close the mailbox.     * and close the mailbox.
1087     * @return true if successful, false if no mailbox was selected     * @return true if successful, false if no mailbox was selected
1088     */     */
1089    public boolean close()    public boolean close() throws IOException
     throws IOException  
1090    {    {
1091      return invokeSimpleCommand(CLOSE);      return invokeSimpleCommand(CLOSE);
1092    }    }
# Line 1126  public class IMAPConnection implements I Line 1095  public class IMAPConnection implements I
1095     * Permanently removes all messages that have the \Delete flag set.     * Permanently removes all messages that have the \Delete flag set.
1096     * @return the numbers of the messages expunged     * @return the numbers of the messages expunged
1097     */     */
1098    public int[] expunge()    public int[] expunge() throws IOException
     throws IOException  
1099    {    {
1100      String tag = newTag();      String tag = newTag();
1101      sendCommand(tag, EXPUNGE);        sendCommand(tag, EXPUNGE);
1102      List numbers = new ArrayList();      List numbers = new ArrayList();
1103      while (true)      while (true)
1104      {      {
# Line 1138  public class IMAPConnection implements I Line 1106  public class IMAPConnection implements I
1106        String id = response.getID();        String id = response.getID();
1107        if (response.isUntagged())        if (response.isUntagged())
1108        {        {
1109          if (id==EXPUNGE)          if (id == EXPUNGE)
1110            numbers.add(new Integer(response.getCount()));            numbers.add(new Integer(response.getCount()));
1111          else          else
1112            asyncResponses.add(response);            asyncResponses.add(response);
# Line 1146  public class IMAPConnection implements I Line 1114  public class IMAPConnection implements I
1114        else if (tag.equals(response.getTag()))        else if (tag.equals(response.getTag()))
1115        {        {
1116          processAlerts(response);          processAlerts(response);
1117          if (id==OK)          if (id == OK)
1118          {          {
1119            int len = numbers.size();            int len = numbers.size();
1120            int[] mn = new int[len];            int[] mn = new int[len];
1121            for (int i=0; i<len; i++)            for (int i = 0; i < len; i++)
1122              mn[i] = ((Integer)numbers.get(i)).intValue();              mn[i] = ((Integer) numbers.get(i)).intValue();
1123            return mn;            return mn;
1124          }          }
1125          else          else
# Line 1166  public class IMAPConnection implements I Line 1134  public class IMAPConnection implements I
1134     * Searches the currently selected mailbox for messages matching the     * Searches the currently selected mailbox for messages matching the
1135     * specified criteria.     * specified criteria.
1136     */     */
1137    public int[] search(String charset, String[] criteria)    public int[] search(String charset, String[]criteria) throws IOException
     throws IOException  
1138    {    {
1139      String tag = newTag();      String tag = newTag();
1140      StringBuffer buffer = new StringBuffer(SEARCH);      StringBuffer buffer = new StringBuffer(SEARCH);
1141      buffer.append(' ');        buffer.append(' ');
1142      if (charset!=null)      if (charset != null)
1143      {      {
1144        buffer.append(charset);        buffer.append(charset);
1145        buffer.append(' ');        buffer.append(' ');
1146      }      }
1147      for (int i=0; i<criteria.length; i++)      for (int i = 0; i < criteria.length; i++)
1148      {      {
1149        if (i>0)        if (i > 0)
1150          buffer.append(' ');          buffer.append(' ');
1151        buffer.append(criteria[i]);        buffer.append(criteria[i]);
1152      }      }
# Line 1191  public class IMAPConnection implements I Line 1158  public class IMAPConnection implements I
1158        String id = response.getID();        String id = response.getID();
1159        if (response.isUntagged())        if (response.isUntagged())
1160        {        {
1161          if (id==SEARCH)          if (id == SEARCH)
1162          {          {
1163            String text = response.getText();            String text = response.getText();
1164            try            try
1165            {            {
1166              int si = text.indexOf(' ');              int si = text.indexOf(' ');
1167              while (si!=-1)              while (si != -1)
1168              {              {
1169                list.add(new Integer(text.substring(0, si)));                list.add(new Integer(text.substring(0, si)));
1170                text = text.substring(si+1);                text = text.substring(si + 1);
1171                si = text.indexOf(' ');                si = text.indexOf(' ');
1172              }              }
1173              list.add(new Integer(text));              list.add(new Integer(text));
1174            }            }
1175            catch (NumberFormatException e)            catch(NumberFormatException e)
1176            {            {
1177              throw new IMAPException(id, "Expecting number: "+text);              throw new IMAPException(id, "Expecting number: " + text);
1178            }            }
1179          }          }
1180          else          else
# Line 1216  public class IMAPConnection implements I Line 1183  public class IMAPConnection implements I
1183        else if (tag.equals(response.getTag()))        else if (tag.equals(response.getTag()))
1184        {        {
1185          processAlerts(response);          processAlerts(response);
1186          if (id==OK)          if (id == OK)
1187          {          {
1188            int len = list.size();            int len = list.size();
1189            int[] mn = new int[len];            int[] mn = new int[len];
1190            for (int i=0; i<len; i++)            for (int i = 0; i < len; i++)
1191              mn[i] = ((Integer)list.get(i)).intValue();              mn[i] = ((Integer) list.get(i)).intValue();
1192            return mn;            return mn;
1193          }          }
1194          else          else
# Line 1236  public class IMAPConnection implements I Line 1203  public class IMAPConnection implements I
1203     * Retrieves data associated with messages in the mailbox.     * Retrieves data associated with messages in the mailbox.
1204     * @param messages the message numbers     * @param messages the message numbers
1205     */     */
1206    public MessageStatus[] fetch(int[] messages, String[] fetchCommands)    public MessageStatus[] fetch(int[]messages, String[]fetchCommands)
1207      throws IOException      throws IOException
1208    {    {
1209      String tag = newTag();      String tag = newTag();
1210      StringBuffer buffer = new StringBuffer(FETCH);      StringBuffer buffer = new StringBuffer(FETCH);
1211      buffer.append(' ');        buffer.append(' ');
1212      for (int i=0; i<messages.length; i++)      for (int i = 0; i < messages.length; i++)
1213      {      {
1214        if (i>0)        if (i > 0)
1215          buffer.append(',');          buffer.append(',');
1216        buffer.append(messages[i]);        buffer.append(messages[i]);
1217      }      }
1218      buffer.append(' ');      buffer.append(' ');
1219      buffer.append('(');      buffer.append('(');
1220      for (int i=0; i<fetchCommands.length; i++)      for (int i = 0; i < fetchCommands.length; i++)
1221      {      {
1222        if (i>0)        if (i > 0)
1223          buffer.append(' ');          buffer.append(' ');
1224        buffer.append(fetchCommands[i]);        buffer.append(fetchCommands[i]);
1225      }      }
# Line 1265  public class IMAPConnection implements I Line 1232  public class IMAPConnection implements I
1232        String id = response.getID();        String id = response.getID();
1233        if (response.isUntagged())        if (response.isUntagged())
1234        {        {
1235          if (id==FETCH)          if (id == FETCH)
1236          {          {
1237            int msgnum = response.getCount();            int msgnum = response.getCount();
1238            List code = response.getResponseCode();            List code = response.getResponseCode();
# Line 1278  public class IMAPConnection implements I Line 1245  public class IMAPConnection implements I
1245        else if (tag.equals(response.getTag()))        else if (tag.equals(response.getTag()))
1246        {        {
1247          processAlerts(response);          processAlerts(response);
1248          if (id==OK)          if (id == OK)
1249          {          {
1250            MessageStatus[] statuses = new MessageStatus[list.size()];            MessageStatus[]statuses = new MessageStatus[list.size()];
1251            list.toArray(statuses);            list.toArray(statuses);
1252            return statuses;            return statuses;
1253          }          }
# Line 1299  public class IMAPConnection implements I Line 1266  public class IMAPConnection implements I
1266     * @param flags message flags to set     * @param flags message flags to set
1267     * @return a list of message-number to current flags     * @return a list of message-number to current flags
1268     */     */
1269    public MessageStatus[] store(int[] messages,    public MessageStatus[] store(int[]messages,
1270        String flagCommand,                                 String flagCommand,
1271        String[] flags)                                 String[]flags) throws IOException
     throws IOException  
1272    {    {
1273      String tag = newTag();      String tag = newTag();
1274      StringBuffer buffer = new StringBuffer(STORE);      StringBuffer buffer = new StringBuffer(STORE);
1275      buffer.append(' ');        buffer.append(' ');
1276      for (int i=0; i<messages.length; i++)      for (int i = 0; i < messages.length; i++)
1277      {      {
1278        if (i>0)        if (i > 0)
1279          buffer.append(',');          buffer.append(',');
1280        buffer.append(messages[i]);        buffer.append(messages[i]);
1281      }      }
# Line 1317  public class IMAPConnection implements I Line 1283  public class IMAPConnection implements I
1283      buffer.append(flagCommand);      buffer.append(flagCommand);
1284      buffer.append(' ');      buffer.append(' ');
1285      buffer.append('(');      buffer.append('(');
1286      for (int i=0; i<flags.length; i++)      for (int i = 0; i < flags.length; i++)
1287      {      {
1288        if (i>0)        if (i > 0)
1289          buffer.append(' ');          buffer.append(' ');
1290        buffer.append(flags[i]);        buffer.append(flags[i]);
1291      }      }
# Line 1335  public class IMAPConnection implements I Line 1301  public class IMAPConnection implements I
1301          int msgnum = response.getCount();          int msgnum = response.getCount();
1302          List code = response.getResponseCode();          List code = response.getResponseCode();
1303          // 2 different styles returned by server: FETCH or FETCH FLAGS          // 2 different styles returned by server: FETCH or FETCH FLAGS
1304          if (id==FETCH)          if (id == FETCH)
1305          {          {
1306            MessageStatus mf = new MessageStatus(msgnum, code);            MessageStatus mf = new MessageStatus(msgnum, code);
1307            list.add(mf);            list.add(mf);
1308          }          }
1309          else if (id==FETCH_FLAGS)          else if (id == FETCH_FLAGS)
1310          {          {
1311            List base = new ArrayList();            List base = new ArrayList();
1312            base.add(FLAGS);            base.add(FLAGS);
# Line 1354  public class IMAPConnection implements I Line 1320  public class IMAPConnection implements I
1320        else if (tag.equals(response.getTag()))        else if (tag.equals(response.getTag()))
1321        {        {
1322          processAlerts(response);          processAlerts(response);
1323          if (id==OK)          if (id == OK)
1324          {          {
1325            MessageStatus[] mf = new MessageStatus[list.size()];            MessageStatus[]mf = new MessageStatus[list.size()];
1326            list.toArray(mf);            list.toArray(mf);
1327            return mf;            return mf;
1328          }          }
# Line 1373  public class IMAPConnection implements I Line 1339  public class IMAPConnection implements I
1339     * @param messages the message numbers     * @param messages the message numbers
1340     * @param mailbox the destination mailbox     * @param mailbox the destination mailbox
1341     */     */
1342    public boolean copy(int[] messages, String mailbox)    public boolean copy(int[]messages, String mailbox) throws IOException
     throws IOException  
1343    {    {
1344      if (messages==null || messages.length<1)      if (messages == null || messages.length < 1)
1345        return true;        return true;
1346      StringBuffer buffer = new StringBuffer(COPY)      StringBuffer buffer = new StringBuffer(COPY).append(' ');
1347        .append(' ');      for (int i = 0; i < messages.length; i++)
     for (int i=0; i<messages.length; i++)  
1348      {      {
1349        if (i>0)        if (i > 0)
1350          buffer.append(',');          buffer.append(',');
1351        buffer.append(messages[i]);        buffer.append(messages[i]);
1352      }      }
1353      buffer.append(' ')      buffer.append(' ').append(quote(UTF7imap.encode(mailbox)));
       .append(quote(UTF7imap.encode(mailbox)));  
1354      return invokeSimpleCommand(buffer.toString());      return invokeSimpleCommand(buffer.toString());
1355    }    }
1356    
1357    // -- Utility methods --    // -- Utility methods --
1358      
1359    /**    /**
1360     * Remove the quotes from each end of a string literal.     * Remove the quotes from each end of a string literal.
1361     */     */
1362    static String stripQuotes(String text)    static String stripQuotes(String text)
1363    {    {
1364      if (text.charAt(0)=='"')      if (text.charAt(0) == '"')
1365      {      {
1366        int len = text.length();        int len = text.length();
1367        if (text.charAt(len-1)=='"')        if (text.charAt(len - 1) == '"')
1368          return text.substring(1, len-1);          return text.substring(1, len - 1);
1369      }      }
1370      return text;      return text;
1371    }    }
# Line 1412  public class IMAPConnection implements I Line 1375  public class IMAPConnection implements I
1375     */     */
1376    static String quote(String text)    static String quote(String text)
1377    {    {
1378      if (text.length()==0 || text.indexOf(' ')!=-1)      if (text.length() == 0 || text.indexOf(' ') != -1)
1379      {      {
1380        StringBuffer buffer = new StringBuffer();        StringBuffer buffer = new StringBuffer();
1381        buffer.append('"');        buffer.append('"');

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26