1 21 22 package org.armedbear.j.mail; 23 24 import java.io.Serializable ; 25 import java.text.SimpleDateFormat ; 26 import java.util.ArrayList ; 27 import java.util.Locale ; 28 import org.armedbear.j.Debug; 29 import org.armedbear.j.Editor; 30 import org.armedbear.j.FastStringBuffer; 31 import org.armedbear.j.Log; 32 import org.armedbear.j.Property; 33 import org.armedbear.j.Utilities; 34 35 public abstract class MailboxEntry implements Serializable 36 { 37 private static final boolean DEBUG = 40 Editor.preferences().getBooleanProperty("MailboxEntry.debug", false); 41 42 protected static final boolean SHOW_MESSAGE_NUMBERS = 43 Editor.preferences().getBooleanProperty(Property.SHOW_MESSAGE_NUMBERS); 44 45 public static final int SEEN = 0x01; 47 public static final int RECENT = 0x02; 48 public static final int ANSWERED = 0x04; 49 public static final int DELETED = 0x08; 50 public static final int FLAGGED = 0x10; 51 public static final int TAGGED = 0x20; 53 protected static final String STRING_DEFAULT = " "; 54 protected static final String STRING_DELETED = "D"; 55 protected static final String STRING_REPLIED = "r"; 56 protected static final String STRING_NEW = "N"; 57 protected static final String STRING_OLD = "O"; 58 protected static final String STRING_FLAGGED = "!"; 59 60 protected int flags; 61 protected int messageNumber; 62 protected int size; 63 protected String subject; 64 protected RFC822Date date; 65 protected MailAddress[] from; 66 protected MailAddress[] replyTo; 67 protected MailAddress[] to; 68 protected MailAddress[] cc; 69 protected String messageId; 70 protected String inReplyTo; 71 protected String [] references; 72 73 private transient int sequenceNumber; 75 76 private transient boolean orphan; 77 78 public final int getFlags() 79 { 80 return flags; 81 } 82 83 public final void setFlags(int flags) 84 { 85 this.flags = flags; 86 } 87 88 public final int getSize() 89 { 90 return size; 91 } 92 93 public final void setSize(int size) 94 { 95 this.size = size; 96 } 97 98 public final int getMessageNumber() 99 { 100 return messageNumber; 101 } 102 103 public final int getSequenceNumber() 104 { 105 return sequenceNumber; 106 } 107 108 public final void setSequenceNumber(int n) 109 { 110 sequenceNumber = n; 111 } 112 113 public final RFC822Date getDate() 114 { 115 return date; 116 } 117 118 public final MailAddress[] getFrom() 119 { 120 return from; 121 } 122 123 public final MailAddress[] getReplyTo() 124 { 125 return replyTo; 126 } 127 128 public final MailAddress[] getTo() 129 { 130 return to; 131 } 132 133 public final MailAddress[] getCc() 134 { 135 return cc; 136 } 137 138 public final String getSubject() 139 { 140 if (subject != null && subject.length() > 0) 141 return subject; 142 return "(no subject)"; 143 } 144 145 public final String getBaseSubject() 146 { 147 if (subject == null) 148 return null; 149 final int length = subject.length(); 150 if (length == 0) 151 return null; 152 String s = subject.trim(); 153 while (true) { 154 if (s.toLowerCase().startsWith("re:")) { 155 s = s.substring(3).trim(); 156 continue; 157 } 158 if (s.length() > 0 && s.charAt(0) == '[') { 159 int end = s.indexOf(']', 1); 160 if (end >= 0) { 161 s = s.substring(end+1).trim(); 162 continue; 163 } 164 } 165 break; 166 } 167 while (s.toLowerCase().endsWith("(fwd)")) 168 s = s.substring(0, s.length()-5).trim(); 169 170 FastStringBuffer sb = new FastStringBuffer(); 178 for (int i = 0, limit = s.length(); i < limit; i++) { 179 char c = s.charAt(i); 180 if (c != ' ' && c != '\t') 181 sb.append(c); 182 } 183 return sb.toString(); 184 } 185 186 public final boolean subjectIsReply() 187 { 188 if (subject != null && subject.toLowerCase().startsWith("re:")) 189 return true; 190 return false; 191 } 192 193 public final String getMessageId() 194 { 195 return messageId; 196 } 197 198 public final String getInReplyTo() 199 { 200 return inReplyTo; 201 } 202 203 public final String [] getReferences() 204 { 205 return references; 206 } 207 208 public final void setOrphan(boolean b) 209 { 210 orphan = b; 211 } 212 213 public String getUidl() 214 { 215 return null; 216 } 217 218 public String formatSubject() 219 { 220 if (subject == null) 221 return ""; 222 return subject; 223 } 224 225 public final boolean isDeleted() 226 { 227 return (flags & DELETED) == DELETED; 228 } 229 230 public final boolean isTagged() 231 { 232 return (flags & TAGGED) == TAGGED; 233 } 234 235 public final boolean isFlagged() 236 { 237 return (flags & FLAGGED) == FLAGGED; 238 } 239 240 public final boolean isAnswered() 241 { 242 return (flags & ANSWERED) == ANSWERED; 243 } 244 245 public final boolean isNew() 246 { 247 return (flags & (SEEN | DELETED | RECENT)) == RECENT; 248 } 249 250 public final boolean isRead() 251 { 252 return (flags & SEEN) != 0; 253 } 254 255 public final boolean isUnread() 256 { 257 return (flags & (SEEN | DELETED)) == 0; 258 } 259 260 public final void tag() 261 { 262 flags |= TAGGED; 263 } 264 265 public final void untag() 266 { 267 flags &= ~TAGGED; 268 } 269 270 public final void toggleTag() 271 { 272 if ((flags & TAGGED) != 0) 273 flags &= ~TAGGED; 274 else 275 flags |= TAGGED; 276 } 277 278 public final void flag() 279 { 280 flags |= FLAGGED; 281 } 282 283 public final void unflag() 284 { 285 flags &= ~FLAGGED; 286 } 287 288 public final void toggleFlag() 289 { 290 if ((flags & FLAGGED) != 0) 291 flags &= ~FLAGGED; 292 else 293 flags |= FLAGGED; 294 } 295 296 protected String formatSize() 297 { 298 if (size < 1000) 299 return Utilities.rightJustify(size, 4); 300 if (size < 10000) { 301 int k = size / 1000; 302 int remainder = size % 1000; 303 int h = remainder / 100; 304 if (remainder % 100 > 49) { 305 ++h; 306 if (h == 10) { 307 ++k; 308 h = 0; 309 } 310 } 311 if (k < 10) { 312 FastStringBuffer sb = new FastStringBuffer(); 313 sb.append(String.valueOf(k)); 314 sb.append('.'); 315 sb.append(String.valueOf(h)); 316 sb.append('K'); 317 return sb.toString(); 318 } 319 } 321 if (size < 1000000) { 322 int k = size / 1000; 323 if (size % 1000 > 499) 324 ++k; 325 if (k < 1000) 326 return Utilities.rightJustify(k, 3) + "K"; 327 } 329 int m = size / 1000000; 330 if (size % 1000000 > 499999) 331 ++m; 332 return Utilities.rightJustify(m, 3) + "M"; 333 } 334 335 protected char getToChar() 336 { 337 if (isFlagged()) 338 return '!'; 339 if (isFromMe()) 340 return 'F'; 341 char c = ' '; 342 if (to != null) { 343 for (int i = to.length-1; i >= 0; i--) { 344 MailAddress a = to[i]; 345 if (a.matches(Mail.getUserMailAddress())) { 346 if (to.length == 1) 348 c = '+'; 349 else 350 return 'T'; 351 } 352 } 353 } 354 if (c == '+') { 355 if (cc != null && cc.length > 0) return 'T'; 358 return c; 359 } 360 if (cc != null) { 361 for (int i = cc.length-1; i >= 0; i--) { 362 MailAddress a = cc[i]; 363 if (a.matches(Mail.getUserMailAddress())) { 364 return 'C'; 366 } 367 } 368 } 369 return ' '; 370 } 371 372 private boolean isFromMe() 373 { 374 if (from != null) { 375 MailAddress a = from[0]; 376 if (a.matches(Mail.getUserMailAddress())) 377 return true; 378 } 379 return false; 380 } 381 382 protected String formatFlags() 383 { 384 if (isAnswered()) 385 return STRING_REPLIED; 386 else if ((flags & (SEEN | RECENT)) == RECENT) return STRING_NEW; 388 else if ((flags & SEEN) == 0) return STRING_OLD; 390 else 391 return STRING_DEFAULT; 392 } 393 394 private static final SimpleDateFormat dateFormat1 = 395 new SimpleDateFormat ("MMM dd HH:mm", Locale.US); 396 397 private static final SimpleDateFormat dateFormat2 = 398 new SimpleDateFormat ("MMM dd yyyy", Locale.US); 399 400 private static final String NULL_DATE = "null "; 401 402 private static final long SIX_MONTHS = (long) 6 * 30 * 24 * 60 * 60 * 1000; 403 404 protected String formatDate() 405 { 406 if (date == null) 407 return NULL_DATE; 408 long millis = date.getTime(); 409 if (millis == 0) 410 return NULL_DATE; 411 if (DEBUG || System.currentTimeMillis() - millis < SIX_MONTHS) 412 return dateFormat1.format(date.getDate()); 413 return dateFormat2.format(date.getDate()); 414 } 415 416 protected String formatFrom(int fieldWidth) 417 { 418 String s = null; 419 if (isFromMe() && to != null && to.length > 0) { 420 MailAddress a = to[0]; 421 s = a.getPersonal(); 422 if (s == null || s.length() == 0) 423 s = a.getAddress(); 424 if (s != null) 425 s = "To: " + s; 426 } else if (from != null && from.length > 0) { 427 MailAddress a = from[0]; 428 s = a.getPersonal(); 429 if (s == null || s.length() == 0) 430 s = a.getAddress(); 431 } 432 if (s == null) 433 s = ""; 434 final int length = s.length(); 435 if (length > fieldWidth) 436 s = s.substring(0, fieldWidth); 437 else if (length < fieldWidth) 438 s = s + Utilities.spaces(fieldWidth - length); 439 return s; 440 } 441 442 public String toString() 443 { 444 return toString(1); 445 } 446 447 public String toString(int depth) 448 { 449 FastStringBuffer sb = new FastStringBuffer(128); 450 if (SHOW_MESSAGE_NUMBERS) { 451 sb.append(Utilities.rightJustify(sequenceNumber, 5)); 452 sb.append(' '); 453 } 454 sb.append(getToChar()); 455 sb.append(' '); 456 sb.append(formatFlags()); 457 sb.append(" "); 458 sb.append(formatDate()); 459 sb.append(" "); 460 sb.append(formatFrom(20)); 461 sb.append(" "); 462 sb.append(formatSize()); 463 sb.append(" "); 464 if (orphan) 465 sb.append("- "); 466 else if (depth > 1) 467 sb.append(Utilities.spaces((depth-1)*2)); 468 sb.append(formatSubject()); 469 return sb.toString(); 470 } 471 472 protected static String parseInReplyTo(String s) 473 { 474 if (s != null) { 475 int begin = s.indexOf('<'); 476 if (begin >= 0) { 477 int end = s.indexOf('>', begin+1); 478 if (end > begin) 479 return s.substring(begin, end+1); 480 } 481 } 482 return null; 483 } 484 485 protected static String [] parseReferences(String s) 486 { 487 ArrayList list = null; 488 int begin = 0; 489 while (true) { 490 begin = s.indexOf('<', begin); 491 if (begin < 0) 492 break; 493 int end = s.indexOf('>', begin+1); 494 if (end < 0) 495 break; 496 if (list == null) 497 list = new ArrayList (); 498 list.add(s.substring(begin, ++end)); 499 begin = end; 500 } 501 if (list == null) 502 return null; 503 String [] array = new String [list.size()]; 504 return (String []) list.toArray(array); 505 } 506 } 507 | Popular Tags |