1 package gov.nist.javax.sip.message; 2 3 import gov.nist.javax.sip.header.HeaderFactoryExt; 4 import gov.nist.javax.sip.header.HeaderFactoryImpl; 5 import gov.nist.javax.sip.parser.StringMsgParser; 6 7 import java.text.ParseException; 8 import java.util.Iterator; 9 import java.util.LinkedList; 10 import java.util.List; 11 12 import javax.sip.header.ContentDispositionHeader; 13 import javax.sip.header.ContentTypeHeader; 14 import javax.sip.header.Header; 15 import javax.sip.header.HeaderFactory; 16 import javax.sip.message.Message; 17 18 19 20 /** 21 * Content list for multipart mime content type. 22 * 23 * @author M. Ranganathan 24 * 25 */ 26 public class MultipartMimeContentImpl implements MultipartMimeContent { 27 private List<Content> contentList = new LinkedList<Content>(); 28 29 private ContentTypeHeader multipartMimeContentTypeHeader; 30 31 private String boundary; 32 33 public static String BOUNDARY = "boundary"; 34 35 /** 36 * Creates a default content list. 37 */ 38 public MultipartMimeContentImpl(ContentTypeHeader contentTypeHeader) { 39 this.multipartMimeContentTypeHeader = contentTypeHeader; 40 this.boundary = contentTypeHeader.getParameter(BOUNDARY); 41 42 } 43 44 /* 45 * (non-Javadoc) 46 * 47 * @see gov.nist.javax.sip.message.MultipartMimeContentExt#add(gov.nist.javax.sip.message.Content) 48 */ 49 public boolean add(Content content) { 50 return contentList.add((ContentImpl) content); 51 } 52 53 /* 54 * (non-Javadoc) 55 * 56 * @see gov.nist.javax.sip.message.MultipartMimeContentExt#getContentTypeHeader() 57 */ 58 public ContentTypeHeader getContentTypeHeader() { 59 return multipartMimeContentTypeHeader; 60 } 61 62 /* 63 * (non-Javadoc) 64 * 65 * @see gov.nist.javax.sip.message.MultipartMimeContentExt#toString() 66 */ 67 @Override 68 public String toString() { 69 StringBuffer stringBuffer = new StringBuffer(); 70 71 for (Content content : this.contentList) { 72 stringBuffer.append(content.toString()); 73 } 74 return stringBuffer.toString(); 75 76 } 77 78 /** 79 * unpack a multipart mime packet and return a list of content packets. 80 * 81 * @return -- an iterator of Content blocks. 82 * 83 */ 84 public void createContentList(String body) throws ParseException { 85 try { 86 HeaderFactoryExt headerFactory = new HeaderFactoryImpl(); 87 String delimiter = this.getContentTypeHeader().getParameter(BOUNDARY); 88 89 if (delimiter == null) { 90 this.contentList = new LinkedList<Content>(); 91 ContentImpl content = new ContentImpl(body, delimiter); 92 content.setContentTypeHeader(this.getContentTypeHeader()); 93 this.contentList.add(content); 94 return; 95 } 96 97 String[] fragments = body.split("--" + delimiter + "\r\n"); 98 99 100 for (String nextPart : fragments) { 101 // NOTE - we are not hanlding line folding for the sip header here. 102 103 if (nextPart == null) { 104 return; 105 } 106 StringBuffer strbuf = new StringBuffer(nextPart); 107 while (strbuf.length() > 0 108 && (strbuf.charAt(0) == '\r' || strbuf.charAt(0) == '\n')) 109 strbuf.deleteCharAt(0); 110 111 if (strbuf.length() == 0) 112 continue; 113 nextPart = strbuf.toString(); 114 int position = nextPart.indexOf("\r\n\r\n"); 115 int off = 4; 116 if (position == -1) { 117 position = nextPart.indexOf("\n"); 118 off = 2; 119 } 120 if (position == -1) 121 throw new ParseException("no content type header found in " + nextPart, 0); 122 String rest = nextPart.substring(position + off); 123 124 if (rest == null) 125 throw new ParseException("No content [" + nextPart + "]", 0); 126 // logger.debug("rest = [[" + rest + "]]"); 127 String headers = nextPart.substring(0, position); 128 ContentImpl content = new ContentImpl(rest, boundary); 129 130 String[] headerArray = headers.split("\r\n"); 131 for (String hdr : headerArray) { 132 Header header = headerFactory.createHeader(hdr); 133 if (header instanceof ContentTypeHeader) { 134 content.setContentTypeHeader((ContentTypeHeader) header); 135 } else if (header instanceof ContentDispositionHeader) { 136 content.setContentDispositionHeader((ContentDispositionHeader) header); 137 } else { 138 throw new ParseException("Unexpected header type " + header.getName(), 0); 139 } 140 contentList.add(content); 141 } 142 143 } 144 } catch (StringIndexOutOfBoundsException ex) { 145 throw new ParseException("Invalid Multipart mime format", 0); 146 } 147 } 148 149 /* 150 * (non-Javadoc) 151 * 152 * @see gov.nist.javax.sip.message.MultipartMimeContentExt#getContentByType(java.lang.String, 153 * java.lang.String) 154 */ 155 public Content getContentByType(String contentType, String contentSubtype) { 156 Content retval = null; 157 if (contentList == null) 158 return null; 159 for (Content content : contentList) { 160 if (content.getContentTypeHeader().getContentType().equalsIgnoreCase(contentType) 161 && content.getContentTypeHeader().getContentSubType().equalsIgnoreCase( 162 contentSubtype)) { 163 retval = content; 164 break; 165 } 166 167 } 168 return retval; 169 } 170 171 /* 172 * (non-Javadoc) 173 * 174 * @see gov.nist.javax.sip.message.MultipartMimeContentExt#setContent(java.lang.String, 175 * java.lang.String, gov.nist.javax.sip.message.Content) 176 */ 177 public void addContent(Content content) { 178 this.add(content); 179 } 180 181 public Iterator<Content> getContents() { 182 return this.contentList.iterator(); 183 } 184 185 186 public int getContentCount() { 187 return this.contentList.size(); 188 } 189 190 } 191