1 /*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 /*
27 * @(#)MimeMultipart.java 1.31 03/01/29
28 */
29
30
31
32 package com.sun.xml.internal.messaging.saaj.packaging.mime.internet;
33
34 import java.io.*;
35 import java.util.BitSet;
36
37 import javax.activation.DataSource;
38
39 import com.sun.xml.internal.messaging.saaj.packaging.mime.*;
40 import com.sun.xml.internal.messaging.saaj.packaging.mime.util.*;
41
42 import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
43 import com.sun.xml.internal.messaging.saaj.util.FinalArrayList;
44
45 /**
46 * The MimeMultipart class is an implementation of the abstract Multipart
47 * class that uses MIME conventions for the multipart data. <p>
48 *
49 * A MimeMultipart is obtained from a MimePart whose primary type
50 * is "multipart" (by invoking the part's <code>getContent()</code> method)
51 * or it can be created by a client as part of creating a new MimeMessage. <p>
52 *
53 * The default multipart subtype is "mixed". The other multipart
54 * subtypes, such as "alternative", "related", and so on, can be
55 * implemented as subclasses of MimeMultipart with additional methods
56 * to implement the additional semantics of that type of multipart
57 * content. The intent is that service providers, mail JavaBean writers
58 * and mail clients will write many such subclasses and their Command
59 * Beans, and will install them into the JavaBeans Activation
60 * Framework, so that any JavaMail implementation and its clients can
61 * transparently find and use these classes. Thus, a MIME multipart
62 * handler is treated just like any other type handler, thereby
63 * decoupling the process of providing multipart handlers from the
376 temp = is.read();
377 if (temp == -1) {
378 eof.flip(0);
379 if (sin != null) {
380 posVector[0] = pos;
381 }
382 break;
383 }
384 buffer[i] = (byte)temp;
385 }
386 bufferLength=i;
387 }
388 return bufferLength;
389 }
390
391 public boolean find(InputStream is, byte[] pattern, SharedInputStream sin)
392 throws Exception {
393 int i;
394 int l = pattern.length;
395 int lx = l -1;
396 int bufferLength = 0;
397 BitSet eof = new BitSet(1);
398 long[] posVector = new long[1];
399
400 while (true) {
401 is.mark(l);
402 bufferLength = readNext(is, buffer, l, eof, posVector, sin);
403 if (eof.get(0)) {
404 // End of stream
405 return false;
406 }
407
408 /*
409 if (bufferLength < l) {
410 //is.reset();
411 return false;
412 }*/
413
414 for(i = lx; i >= 0; i--) {
415 if (buffer[i] != pattern[i]) {
416 break;
417 }
418 }
419
420 if (i < 0) {
421 // found the boundary, skip *LWSP-char and CRLF
422 if (!skipLWSPAndCRLF(is)) {
544 }
545 } else {
546 throw new Exception(
547 "Boundary characters encountered in part Body " +
548 "without a preceeding CRLF");
549 }
550 }
551 }
552 // found the boundary, skip *LWSP-char and CRLF
553 if (!skipLWSPAndCRLF(is)) {
554 //throw new Exception(
555 // "Boundary does not terminate with CRLF");
556 }
557 return true;
558 }
559
560 if ((s > 0) && (sin == null)) {
561 if (prevBuffer[s-1] == (byte)13) {
562 // if buffer[0] == (byte)10
563 if (buffer[0] == (byte)10) {
564 int j=lx-1;
565 for(j = lx-1; j > 0; j--) {
566 if (buffer[j+1] != pattern[j]) {
567 break;
568 }
569 }
570 if (j == 0) {
571 // matched the pattern excluding the last char of the pattern
572 // so dont write the CR into stream
573 out.write(prevBuffer,0,s-1);
574 } else {
575 out.write(prevBuffer,0,s);
576 }
577 } else {
578 out.write(prevBuffer, 0, s);
579 }
580 } else {
581 out.write(prevBuffer, 0, s);
582 }
583 }
584
678 // pattern[j..len] is a good suffix
679 gss[j - 1] = i;
680 } else {
681 // No match. The array has already been
682 // filled up with correct values before.
683 continue NEXT;
684 }
685 }
686 while (j > 0) {
687 gss[--j] = i;
688 }
689 }
690 gss[l - 1] = 1;
691 }
692
693
694 /**
695 * Iterates through all the parts and outputs each Mime part
696 * separated by a boundary.
697 */
698 byte[] buf = new byte[1024];
699
700 public void writeTo(OutputStream os)
701 throws IOException, MessagingException {
702
703 // inputStream was not null
704 if (in != null) {
705 contentType.setParameter("boundary", this.boundary);
706 }
707
708 String bnd = "--" + contentType.getParameter("boundary");
709 for (int i = 0; i < parts.size(); i++) {
710 OutputUtil.writeln(bnd, os); // put out boundary
711 ((MimeBodyPart)parts.get(i)).writeTo(os);
712 OutputUtil.writeln(os); // put out empty line
713 }
714
715 if (in != null) {
716 OutputUtil.writeln(bnd, os); // put out boundary
717 if ((os instanceof ByteOutputStream) && lazyAttachments) {
718 ((ByteOutputStream)os).write(in);
719 } else {
720 ByteOutputStream baos = new ByteOutputStream(in.available());
721 baos.write(in);
722 baos.writeTo(os);
723 // reset the inputstream so that we can support a
724 //getAttachment later
725 in = baos.newInputStream();
726 }
727
728 // this will endup writing the end boundary
729 } else {
730 // put out last boundary
731 OutputUtil.writeAsAscii(bnd, os);
732 OutputUtil.writeAsAscii("--", os);
733 }
734 }
735
736 public void setInputStream(InputStream is) {
737 this.in = is;
738 }
739
740 public InputStream getInputStream() {
741 return this.in;
742 }
743
744 public void setBoundary(String bnd) {
745 this.boundary = bnd;
|
1 /*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 /*
27 * @(#)MimeMultipart.java 1.31 03/01/29
28 */
29
30
31
32 package com.sun.xml.internal.messaging.saaj.packaging.mime.internet;
33
34 import java.io.*;
35 import java.util.BitSet;
36
37 import javax.activation.DataSource;
38
39 import com.sun.xml.internal.messaging.saaj.packaging.mime.*;
40 import com.sun.xml.internal.messaging.saaj.packaging.mime.util.*;
41
42 import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
43
44 /**
45 * The MimeMultipart class is an implementation of the abstract Multipart
46 * class that uses MIME conventions for the multipart data. <p>
47 *
48 * A MimeMultipart is obtained from a MimePart whose primary type
49 * is "multipart" (by invoking the part's <code>getContent()</code> method)
50 * or it can be created by a client as part of creating a new MimeMessage. <p>
51 *
52 * The default multipart subtype is "mixed". The other multipart
53 * subtypes, such as "alternative", "related", and so on, can be
54 * implemented as subclasses of MimeMultipart with additional methods
55 * to implement the additional semantics of that type of multipart
56 * content. The intent is that service providers, mail JavaBean writers
57 * and mail clients will write many such subclasses and their Command
58 * Beans, and will install them into the JavaBeans Activation
59 * Framework, so that any JavaMail implementation and its clients can
60 * transparently find and use these classes. Thus, a MIME multipart
61 * handler is treated just like any other type handler, thereby
62 * decoupling the process of providing multipart handlers from the
375 temp = is.read();
376 if (temp == -1) {
377 eof.flip(0);
378 if (sin != null) {
379 posVector[0] = pos;
380 }
381 break;
382 }
383 buffer[i] = (byte)temp;
384 }
385 bufferLength=i;
386 }
387 return bufferLength;
388 }
389
390 public boolean find(InputStream is, byte[] pattern, SharedInputStream sin)
391 throws Exception {
392 int i;
393 int l = pattern.length;
394 int lx = l -1;
395 BitSet eof = new BitSet(1);
396 long[] posVector = new long[1];
397
398 while (true) {
399 is.mark(l);
400 readNext(is, buffer, l, eof, posVector, sin);
401 if (eof.get(0)) {
402 // End of stream
403 return false;
404 }
405
406 /*
407 if (bufferLength < l) {
408 //is.reset();
409 return false;
410 }*/
411
412 for(i = lx; i >= 0; i--) {
413 if (buffer[i] != pattern[i]) {
414 break;
415 }
416 }
417
418 if (i < 0) {
419 // found the boundary, skip *LWSP-char and CRLF
420 if (!skipLWSPAndCRLF(is)) {
542 }
543 } else {
544 throw new Exception(
545 "Boundary characters encountered in part Body " +
546 "without a preceeding CRLF");
547 }
548 }
549 }
550 // found the boundary, skip *LWSP-char and CRLF
551 if (!skipLWSPAndCRLF(is)) {
552 //throw new Exception(
553 // "Boundary does not terminate with CRLF");
554 }
555 return true;
556 }
557
558 if ((s > 0) && (sin == null)) {
559 if (prevBuffer[s-1] == (byte)13) {
560 // if buffer[0] == (byte)10
561 if (buffer[0] == (byte)10) {
562 int j;
563 for(j = lx-1; j > 0; j--) {
564 if (buffer[j+1] != pattern[j]) {
565 break;
566 }
567 }
568 if (j == 0) {
569 // matched the pattern excluding the last char of the pattern
570 // so dont write the CR into stream
571 out.write(prevBuffer,0,s-1);
572 } else {
573 out.write(prevBuffer,0,s);
574 }
575 } else {
576 out.write(prevBuffer, 0, s);
577 }
578 } else {
579 out.write(prevBuffer, 0, s);
580 }
581 }
582
676 // pattern[j..len] is a good suffix
677 gss[j - 1] = i;
678 } else {
679 // No match. The array has already been
680 // filled up with correct values before.
681 continue NEXT;
682 }
683 }
684 while (j > 0) {
685 gss[--j] = i;
686 }
687 }
688 gss[l - 1] = 1;
689 }
690
691
692 /**
693 * Iterates through all the parts and outputs each Mime part
694 * separated by a boundary.
695 */
696
697 public void writeTo(OutputStream os)
698 throws IOException, MessagingException {
699
700 // inputStream was not null
701 if (in != null) {
702 contentType.setParameter("boundary", this.boundary);
703 }
704
705 String bnd = "--" + contentType.getParameter("boundary");
706 for (int i = 0; i < parts.size(); i++) {
707 OutputUtil.writeln(bnd, os); // put out boundary
708 ((MimeBodyPart)parts.get(i)).writeTo(os);
709 OutputUtil.writeln(os); // put out empty line
710 }
711
712 if (in != null) {
713 OutputUtil.writeln(bnd, os); // put out boundary
714 if ((os instanceof ByteOutputStream) && lazyAttachments) {
715 ((ByteOutputStream) os).write(in);
716 } else {
717 ByteOutputStream baos = null;
718 try {
719 baos = new ByteOutputStream(in.available());
720 baos.write(in);
721 baos.writeTo(os);
722 // reset the inputstream so that we can support a
723 // getAttachment later
724 in = baos.newInputStream();
725 } finally {
726 if (baos != null)
727 baos.close();
728 }
729 }
730
731 // this will endup writing the end boundary
732 } else {
733 // put out last boundary
734 OutputUtil.writeAsAscii(bnd, os);
735 OutputUtil.writeAsAscii("--", os);
736 }
737 }
738
739 public void setInputStream(InputStream is) {
740 this.in = is;
741 }
742
743 public InputStream getInputStream() {
744 return this.in;
745 }
746
747 public void setBoundary(String bnd) {
748 this.boundary = bnd;
|