1 36 package org.columba.ristretto.imap.parser; 37 38 import org.columba.ristretto.imap.IMAPResponse; 39 import org.columba.ristretto.message.Attributes; 40 import org.columba.ristretto.message.Header; 41 import org.columba.ristretto.message.LocalMimePart; 42 import org.columba.ristretto.message.Message; 43 import org.columba.ristretto.message.MessageMimePart; 44 import org.columba.ristretto.message.MimeHeader; 45 import org.columba.ristretto.message.MimePart; 46 import org.columba.ristretto.message.MimeTree; 47 import org.columba.ristretto.message.MimeType; 48 import org.columba.ristretto.message.StreamableMimePart; 49 import org.columba.ristretto.parser.ParserException; 50 51 56 public class MimeTreeParser { 57 58 65 public static MimeTree parse(IMAPResponse response) throws ParserException { 66 String message = response.getResponseMessage(); 67 68 Attributes attributes = 70 MessageAttributeParser.parse(message); 71 72 String bodystructure = (String ) attributes.get("BODYSTRUCTURE"); 73 if( bodystructure == null ) throw new ParserException(message); 74 75 MimeTree mptree = 76 parseBodyStructure(response , bodystructure); 77 78 return mptree; 79 } 80 81 private static MimeTree parseBodyStructure( 82 IMAPResponse response, 83 String input) throws ParserException { 84 int openParenthesis = input.indexOf("("); 85 86 String bodystructure = 87 input.substring( 88 openParenthesis + 1, 89 ParenthesisParser.getClosingPos( 90 input, 91 openParenthesis)); 92 93 return new MimeTree(parseBS(response, bodystructure)); 94 } 95 96 protected static MimePart parseBS(IMAPResponse response, String input) throws ParserException { 97 MimePart result; 98 99 if (input.charAt(0) == '(') { 100 result = new MimePart(); 101 102 BodystructureTokenizer tokenizer = 103 new BodystructureTokenizer(response, input); 104 BodystructureTokenizer subtokenizer; 105 106 Item nextItem = tokenizer.getNextItem(); 107 Item valueItem; 108 109 while (nextItem != null) { 110 if (nextItem.getType() != Item.PARENTHESIS) 111 break; 112 113 result.addChild( 114 parseBS(response, (String ) nextItem.getValue())); 115 nextItem = tokenizer.getNextItem(); 116 } 117 118 120 result.getHeader().setMimeType( 122 new MimeType( 123 "multipart", 124 ((String ) nextItem.getValue()).toLowerCase())); 125 126 nextItem = tokenizer.getNextItem(); 128 if (nextItem.getType() == Item.PARENTHESIS) { 129 subtokenizer = 130 new BodystructureTokenizer( 131 response, 132 (String ) nextItem.getValue()); 133 134 nextItem = subtokenizer.getNextItem(); 135 while (nextItem != null) { 136 valueItem = subtokenizer.getNextItem(); 137 138 result.getHeader().putContentParameter( 139 ((String ) nextItem.getValue()).toLowerCase(), 140 (String ) valueItem.getValue()); 141 142 nextItem = subtokenizer.getNextItem(); 143 } 144 } 145 146 nextItem = tokenizer.getNextItem(); 148 if (nextItem == null) 149 return result; 150 if (nextItem.getType() == Item.STRING) 151 result.getHeader().setContentID( 152 ((String ) nextItem.getValue()).toLowerCase()); 153 154 nextItem = tokenizer.getNextItem(); 156 if (nextItem == null) 157 return result; 158 if (nextItem.getType() == Item.STRING) 159 result.getHeader().setContentDescription( 160 ((String ) nextItem.getValue()).toLowerCase()); 161 162 } else { 163 164 result = parseMimeStructure(response, input); 165 } 166 167 return result; 168 } 169 170 private static Header parseEnvelope( 171 IMAPResponse response, 172 String envelope) throws ParserException { 173 174 Header result = new Header(); 175 176 BodystructureTokenizer tokenizer = 177 new BodystructureTokenizer(response, envelope); 178 Item nextItem; 179 180 nextItem = tokenizer.getNextItem(); 182 if (nextItem.getType() == Item.STRING) 183 result.set("Date", (String ) nextItem.getValue()); 184 185 nextItem = tokenizer.getNextItem(); 187 if (nextItem.getType() == Item.STRING) 188 result.set("Subject", (String ) nextItem.getValue()); 189 190 nextItem = tokenizer.getNextItem(); 192 if (nextItem.getType() == Item.PARENTHESIS); 193 194 nextItem = tokenizer.getNextItem(); 196 if (nextItem.getType() == Item.PARENTHESIS); 197 198 nextItem = tokenizer.getNextItem(); 200 if (nextItem.getType() == Item.PARENTHESIS); 201 202 nextItem = tokenizer.getNextItem(); 204 if (nextItem.getType() == Item.PARENTHESIS); 205 206 nextItem = tokenizer.getNextItem(); 208 if (nextItem.getType() == Item.PARENTHESIS); 209 210 nextItem = tokenizer.getNextItem(); 212 if (nextItem.getType() == Item.PARENTHESIS); 213 214 nextItem = tokenizer.getNextItem(); 216 if (nextItem.getType() == Item.STRING) 217 result.set("In-Reply-To", (String ) nextItem.getValue()); 218 219 nextItem = tokenizer.getNextItem(); 221 if (nextItem.getType() == Item.STRING) 222 result.set("Message-ID", (String ) nextItem.getValue()); 223 224 return result; 225 } 226 227 private static MimePart parseMimeStructure ( 228 IMAPResponse response, 229 String structure) throws ParserException { 230 MimeHeader header = new MimeHeader(); 231 BodystructureTokenizer tokenizer = 232 new BodystructureTokenizer(response, structure); 233 BodystructureTokenizer subtokenizer; 234 Item nextItem, valueItem; 235 MimeType type = null; 236 StreamableMimePart result = null; 237 238 String contentType = "text"; 239 nextItem = tokenizer.getNextItem(); 241 if (nextItem.getType() == Item.STRING) 242 contentType = ((String ) nextItem.getValue()).toLowerCase(); 243 244 nextItem = tokenizer.getNextItem(); 246 if (nextItem.getType() == Item.STRING) { 247 type = 248 new MimeType( 249 contentType, 250 ((String ) nextItem.getValue()).toLowerCase()); 251 header.setMimeType(type); 252 } 253 254 nextItem = tokenizer.getNextItem(); 256 if (nextItem.getType() == Item.PARENTHESIS) { 257 subtokenizer = 258 new BodystructureTokenizer( 259 response, 260 (String ) nextItem.getValue()); 261 262 nextItem = subtokenizer.getNextItem(); 263 while (nextItem != null) { 264 valueItem = subtokenizer.getNextItem(); 265 266 header.putContentParameter( 267 ((String ) nextItem.getValue()).toLowerCase(), 268 (String ) valueItem.getValue()); 269 270 nextItem = subtokenizer.getNextItem(); 271 } 272 } 273 274 nextItem = tokenizer.getNextItem(); 276 if (nextItem.getType() == Item.STRING) 277 header.setContentID(((String ) nextItem.getValue()).toLowerCase()); 278 279 nextItem = tokenizer.getNextItem(); 281 if (nextItem.getType() == Item.STRING) 282 header.setContentDescription( 283 ((String ) nextItem.getValue()).toLowerCase()); 284 285 nextItem = tokenizer.getNextItem(); 287 if (nextItem.getType() == Item.STRING) 288 header.setContentTransferEncoding( 289 ((String ) nextItem.getValue()).toLowerCase()); 290 291 int size = 0; 293 nextItem = tokenizer.getNextItem(); 294 if (nextItem.getType() == Item.NUMBER) 295 size = ((Integer ) nextItem.getValue()).intValue(); 296 297 if (type.getType().equals("message") 299 && type.getSubtype().equals("rfc822")) { 300 result = new MessageMimePart(header); 301 302 Message subMessage = new Message(); 303 304 306 nextItem = tokenizer.getNextItem(); 307 if (nextItem.getType() == Item.PARENTHESIS) { 308 subMessage.setHeader( 309 parseEnvelope(response, (String ) nextItem.getValue())); 310 } 311 312 314 nextItem = tokenizer.getNextItem(); 315 if (nextItem.getType() == Item.PARENTHESIS) { 316 MimePart subStructure = 317 parseBS(response, (String ) nextItem.getValue()); 318 subStructure.setParent(result); 319 subMessage.setMimePartTree(new MimeTree(subStructure)); 320 } 321 322 ((MessageMimePart) result).setMessage(subMessage); 323 324 nextItem = tokenizer.getNextItem(); 326 } 327 else if (type.getType().equals("text")) { 329 result = new LocalMimePart(header); 330 331 nextItem = tokenizer.getNextItem(); 333 } else { 335 result = new LocalMimePart(header); 336 } 337 338 result.setSize(size); 340 341 nextItem = tokenizer.getNextItem(); 344 if (nextItem == null) 345 return new MimePart(header); 346 348 nextItem = tokenizer.getNextItem(); 350 if (nextItem == null) 351 return new MimePart(header); 352 353 if (nextItem.getType() == Item.STRING) { 354 header.setContentDisposition( 355 ((String ) nextItem.getValue()).toLowerCase()); 356 } else if (nextItem.getType() == Item.PARENTHESIS) { 357 subtokenizer = 358 new BodystructureTokenizer( 359 response, 360 (String ) nextItem.getValue()); 361 362 nextItem = subtokenizer.getNextItem(); 363 header.setContentDisposition( 364 ((String ) nextItem.getValue()).toLowerCase()); 365 366 nextItem = subtokenizer.getNextItem(); 367 if (nextItem.getType() == Item.PARENTHESIS) { 369 subtokenizer = 370 new BodystructureTokenizer( 371 response, 372 (String ) nextItem.getValue()); 373 374 nextItem = subtokenizer.getNextItem(); 375 376 while (nextItem != null) { 377 valueItem = subtokenizer.getNextItem(); 378 379 header.putDispositionParameter( 380 ((String ) nextItem.getValue()).toLowerCase(), 381 (String ) valueItem.getValue()); 382 383 nextItem = subtokenizer.getNextItem(); 384 } 385 } 386 } 387 388 390 return result; 391 } 392 393 } 394 395 class BodystructureTokenizer { 396 397 private String s; 398 private Interval i; 399 private IMAPResponse response; 400 401 407 public BodystructureTokenizer(IMAPResponse response, String s) { 408 this.s = s; 409 this.response = response; 410 i = new Interval(); 411 } 412 413 419 public Item getNextItem() throws ParserException { 420 Item result = new Item(); 421 422 i.a = i.b + 1; 424 if (i.a >= s.length()) 426 return null; 427 while (s.charAt(i.a) == ' ') { 428 i.a++; 429 if (i.a >= s.length()) 430 return null; 431 } 432 433 435 if (s.charAt(i.a) == '\"') { 436 i.b = s.indexOf("\"", i.a + 1); 437 438 result.setType(Item.STRING); 439 result.setValue(s.substring(i.a + 1, i.b)); 440 } 441 442 444 else if (s.charAt(i.a) == '{') { 445 i.b = s.indexOf("}", i.a); 446 447 result.setType(Item.STRING); 448 result.setValue(response.getData(s.substring(i.a, i.b+1)).toString()); 449 } 450 451 453 else if (s.charAt(i.a) == '(') { 454 i.b = ParenthesisParser.getClosingPos(s, i.a); 455 456 result.setType(Item.PARENTHESIS); 457 result.setValue(s.substring(i.a + 1, i.b)); 458 } 459 460 462 else { 463 i.b = s.indexOf(" ", i.a + 1); 464 if (i.b == -1) 465 i.b = s.length(); 466 467 String item = s.substring(i.a, i.b); 468 i.b--; 469 470 if (item.equals("NIL")) { 471 result.setType(Item.NIL); 472 } else { 473 result.setValue(new Integer (item)); 474 result.setType(Item.NUMBER); 475 } 476 } 477 478 return result; 479 } 480 } 481 482 class Item { 483 486 public static final int STRING = 0; 487 490 public static final int PARENTHESIS = 1; 491 494 public static final int NIL = 2; 495 498 public static final int NUMBER = 3; 499 500 private Object value; 501 private int type; 502 507 public int getType() { 508 return type; 509 } 510 511 516 public Object getValue() { 517 return value; 518 } 519 520 526 public void setType(int type) { 527 this.type = type; 528 } 529 530 536 public void setValue(Object value) { 537 this.value = value; 538 } 539 540 } 541 542 class Interval { 543 546 public int a; 547 550 public int b; 551 552 558 public Interval(int a, int b) { 559 this.a = a; 560 this.b = b; 561 } 562 563 566 public Interval() { 567 a = -1; 568 b = -1; 569 } 570 571 574 public void reset() { 575 a = -1; 576 b = -2; 577 } 578 } 579 | Popular Tags |