1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.javax.sip.message; 2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.HeaderFactoryExt; 4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.header.HeaderFactoryImpl; 5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.parser.StringMsgParser; 6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.text.ParseException; 8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Iterator; 9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.LinkedList; 10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.List; 11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ContentDispositionHeader; 13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ContentTypeHeader; 14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.Header; 15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.HeaderFactory; 16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.Message; 17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/** 21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Content list for multipart mime content type. 22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan 24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic class MultipartMimeContentImpl implements MultipartMimeContent { 27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private List<Content> contentList = new LinkedList<Content>(); 28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private ContentTypeHeader multipartMimeContentTypeHeader; 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private String boundary; 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public static String BOUNDARY = "boundary"; 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Creates a default content list. 37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public MultipartMimeContentImpl(ContentTypeHeader contentTypeHeader) { 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.multipartMimeContentTypeHeader = contentTypeHeader; 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.boundary = contentTypeHeader.getParameter(BOUNDARY); 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (non-Javadoc) 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see gov.nist.javax.sip.message.MultipartMimeContentExt#add(gov.nist.javax.sip.message.Content) 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public boolean add(Content content) { 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return contentList.add((ContentImpl) content); 51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (non-Javadoc) 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see gov.nist.javax.sip.message.MultipartMimeContentExt#getContentTypeHeader() 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public ContentTypeHeader getContentTypeHeader() { 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return multipartMimeContentTypeHeader; 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (non-Javadoc) 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see gov.nist.javax.sip.message.MultipartMimeContentExt#toString() 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang @Override 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public String toString() { 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StringBuffer stringBuffer = new StringBuffer(); 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (Content content : this.contentList) { 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang stringBuffer.append(content.toString()); 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return stringBuffer.toString(); 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * unpack a multipart mime packet and return a list of content packets. 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return -- an iterator of Content blocks. 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void createContentList(String body) throws ParseException { 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang HeaderFactoryExt headerFactory = new HeaderFactoryImpl(); 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String delimiter = this.getContentTypeHeader().getParameter(BOUNDARY); 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (delimiter == null) { 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.contentList = new LinkedList<Content>(); 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContentImpl content = new ContentImpl(body, delimiter); 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang content.setContentTypeHeader(this.getContentTypeHeader()); 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.contentList.add(content); 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String[] fragments = body.split("--" + delimiter + "\r\n"); 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (String nextPart : fragments) { 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // NOTE - we are not hanlding line folding for the sip header here. 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (nextPart == null) { 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return; 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StringBuffer strbuf = new StringBuffer(nextPart); 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (strbuf.length() > 0 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && (strbuf.charAt(0) == '\r' || strbuf.charAt(0) == '\n')) 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang strbuf.deleteCharAt(0); 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (strbuf.length() == 0) 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang continue; 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang nextPart = strbuf.toString(); 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int position = nextPart.indexOf("\r\n\r\n"); 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int off = 4; 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (position == -1) { 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang position = nextPart.indexOf("\n"); 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang off = 2; 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (position == -1) 121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("no content type header found in " + nextPart, 0); 122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String rest = nextPart.substring(position + off); 123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (rest == null) 125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("No content [" + nextPart + "]", 0); 126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // logger.debug("rest = [[" + rest + "]]"); 127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String headers = nextPart.substring(0, position); 128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ContentImpl content = new ContentImpl(rest, boundary); 129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String[] headerArray = headers.split("\r\n"); 131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (String hdr : headerArray) { 132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Header header = headerFactory.createHeader(hdr); 133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (header instanceof ContentTypeHeader) { 134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang content.setContentTypeHeader((ContentTypeHeader) header); 135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (header instanceof ContentDispositionHeader) { 136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang content.setContentDispositionHeader((ContentDispositionHeader) header); 137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else { 138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("Unexpected header type " + header.getName(), 0); 139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang contentList.add(content); 141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (StringIndexOutOfBoundsException ex) { 145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException("Invalid Multipart mime format", 0); 146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (non-Javadoc) 151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see gov.nist.javax.sip.message.MultipartMimeContentExt#getContentByType(java.lang.String, 153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * java.lang.String) 154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Content getContentByType(String contentType, String contentSubtype) { 156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Content retval = null; 157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (contentList == null) 158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return null; 159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (Content content : contentList) { 160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (content.getContentTypeHeader().getContentType().equalsIgnoreCase(contentType) 161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang && content.getContentTypeHeader().getContentSubType().equalsIgnoreCase( 162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang contentSubtype)) { 163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval = content; 164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval; 169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /* 172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * (non-Javadoc) 173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @see gov.nist.javax.sip.message.MultipartMimeContentExt#setContent(java.lang.String, 175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * java.lang.String, gov.nist.javax.sip.message.Content) 176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public void addContent(Content content) { 178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.add(content); 179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Iterator<Content> getContents() { 182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.contentList.iterator(); 183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public int getContentCount() { 187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return this.contentList.size(); 188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 191