1package gov.nist.javax.sip.message;
2
3import gov.nist.javax.sip.header.HeaderFactoryExt;
4import gov.nist.javax.sip.header.HeaderFactoryImpl;
5import gov.nist.javax.sip.parser.StringMsgParser;
6
7import java.text.ParseException;
8import java.util.Iterator;
9import java.util.LinkedList;
10import java.util.List;
11
12import javax.sip.header.ContentDispositionHeader;
13import javax.sip.header.ContentTypeHeader;
14import javax.sip.header.Header;
15import javax.sip.header.HeaderFactory;
16import javax.sip.message.Message;
17
18
19
20/**
21 * Content list for multipart mime content type.
22 *
23 * @author M. Ranganathan
24 *
25 */
26public 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