View Javadoc

1   /* ***** BEGIN LICENSE BLOCK *****
2    * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3    *
4    * The contents of this file are subject to the Mozilla Public License Version
5    * 1.1 (the "License"); you may not use this file except in compliance with
6    * the License. You may obtain a copy of the License at
7    * http://www.mozilla.org/MPL/
8    *
9    * Software distributed under the License is distributed on an "AS IS" basis,
10   * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11   * for the specific language governing rights and limitations under the
12   * License.
13   *
14   * The Original Code is "SMS Library for the Java platform".
15   *
16   * The Initial Developer of the Original Code is Markus Eriksson.
17   * Portions created by the Initial Developer are Copyright (C) 2002
18   * the Initial Developer. All Rights Reserved.
19   *
20   * Contributor(s):
21   *
22   * Alternatively, the contents of this file may be used under the terms of
23   * either the GNU General Public License Version 2 or later (the "GPL"), or
24   * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
25   * in which case the provisions of the GPL or the LGPL are applicable instead
26   * of those above. If you wish to allow use of your version of this file only
27   * under the terms of either the GPL or the LGPL, and not to allow others to
28   * use your version of this file under the terms of the MPL, indicate your
29   * decision by deleting the provisions above and replace them with the notice
30   * and other provisions required by the GPL or the LGPL. If you do not delete
31   * the provisions above, a recipient may use your version of this file under
32   * the terms of any one of the MPL, the GPL or the LGPL.
33   *
34   * ***** END LICENSE BLOCK ***** */
35  package org.marre.wap;
36  
37  import java.io.ByteArrayOutputStream;
38  import java.io.IOException;
39  import java.io.OutputStream;
40  import java.util.HashMap;
41  import java.util.Map;
42  
43  import org.marre.mime.MimeHeader;
44  import org.marre.mime.MimeHeaderParam;
45  
46  /***
47   * 
48   * @author Markus Eriksson
49   * @version $Id: WspUtil.java,v 1.2 2004/11/20 19:03:04 c95men Exp $
50   */
51  public final class WspUtil
52  {
53      private static Map myWspHeaders;
54      private static Map myWspContentTypes;
55      private static Map myWspParameters;
56      private static Map myWspPushAppTypes;
57      
58      /* Maps a header id to a well known id */
59      private static final int[] WELL_KNOWN_HEADER_ID_WSP_11 = {
60          0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
61          0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
62          0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, -1,
63          -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
64          -1
65      };
66              
67      private static final int[] WELL_KNOWN_HEADER_ID_WSP_12 = {
68          0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
69          0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
70          0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
71          0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  
72          -1
73      };
74      
75      private static final int[] WELL_KNOWN_HEADER_ID_WSP_13 = {
76          0x00, 0x3B, 0x3C, 0x03, 0x04, 0x05, 0x06, 0x07, 0x3D, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
77          0x3e, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
78          0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
79          0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3F, 0x40, 0x41, 0x42, 0x43,
80          -1
81      };
82      
83      private static final int[] WELL_KNOWN_HEADER_ID_WSP_14 = {
84          0x00, 0x3B, 0x3C, 0x03, 0x04, 0x05, 0x06, 0x07, 0x47, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
85          0x3e, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
86          0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x45, 0x2F,
87          0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x44, 0x38, 0x39, 0x3A, 0x3F, 0x40, 0x41, 0x42, 0x43,
88          0x46
89      };
90  
91      /* Maps a parameter id to a well known id */
92      private static final int[] WELL_KNOWN_PARAMETER_ID_WSP_11 = {
93          0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07, 0x08, -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
94          -1,   -1,   -1,   -1,   -1,   -1
95      };
96              
97      private static final int[] WELL_KNOWN_PARAMETER_ID_WSP_12 = {
98          0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, -1,   -1,   -1,   -1,   -1,
99          -1,   -1,   -1,   -1,   -1,   -1
100     };
101     
102     private static final int[] WELL_KNOWN_PARAMETER_ID_WSP_13 = {
103         0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
104         -1,   -1,   -1,   -1,   -1,   -1
105     };
106     
107     private static final int[] WELL_KNOWN_PARAMETER_ID_WSP_14 = {
108         0x00, 0x01, 0x02, 0x03, 0x17, 0x18, 0x07, 0x08, 0x09, 0x19, 0x1A, 0x1B, 0x1C, 0x0E, 0x1D, 0x10,
109         0x11, 0x12, 0x13, 0x14, 0x15, 0x16
110     };
111     
112     /* Maps a well known parameter id to a parameter type */
113     private static final int[] PARAMETER_TYPES = {
114         WapConstants.WSP_PARAMETER_TYPE_Q_VALUE,
115         WapConstants.WSP_PARAMETER_TYPE_WELL_KNOWN_CHARSET,
116         WapConstants.WSP_PARAMETER_TYPE_VERSION_VALUE,
117         WapConstants.WSP_PARAMETER_TYPE_INTEGER_VALUE,
118         -1,
119         WapConstants.WSP_PARAMETER_TYPE_TEXT_STRING,
120         WapConstants.WSP_PARAMETER_TYPE_TEXT_STRING,
121         WapConstants.WSP_PARAMETER_TYPE_FIELD_NAME,
122         WapConstants.WSP_PARAMETER_TYPE_SHORT_INTEGER,
123         
124         WapConstants.WSP_PARAMETER_TYPE_CONSTRAINED_ENCODING,
125         WapConstants.WSP_PARAMETER_TYPE_TEXT_STRING,
126         WapConstants.WSP_PARAMETER_TYPE_TEXT_STRING,
127         
128         WapConstants.WSP_PARAMETER_TYPE_TEXT_STRING,
129         WapConstants.WSP_PARAMETER_TYPE_TEXT_STRING,
130         WapConstants.WSP_PARAMETER_TYPE_DELTA_SECONDS_VALUE,
131         WapConstants.WSP_PARAMETER_TYPE_TEXT_STRING,
132         WapConstants.WSP_PARAMETER_TYPE_NO_VALUE,
133         
134         WapConstants.WSP_PARAMETER_TYPE_SHORT_INTEGER,
135         WapConstants.WSP_PARAMETER_TYPE_TEXT_VALUE,
136         WapConstants.WSP_PARAMETER_TYPE_DATE_VALUE,
137         WapConstants.WSP_PARAMETER_TYPE_DATE_VALUE,
138         WapConstants.WSP_PARAMETER_TYPE_DATE_VALUE,
139         WapConstants.WSP_PARAMETER_TYPE_INTEGER_VALUE,
140         WapConstants.WSP_PARAMETER_TYPE_TEXT_VALUE,
141         WapConstants.WSP_PARAMETER_TYPE_TEXT_VALUE,
142         WapConstants.WSP_PARAMETER_TYPE_TEXT_VALUE,
143         WapConstants.WSP_PARAMETER_TYPE_TEXT_VALUE,
144         WapConstants.WSP_PARAMETER_TYPE_TEXT_VALUE,
145         WapConstants.WSP_PARAMETER_TYPE_TEXT_VALUE,
146         WapConstants.WSP_PARAMETER_TYPE_TEXT_VALUE,
147     };
148     
149     static {
150         // WSP 1.1
151         myWspHeaders = new HashMap();
152         myWspHeaders.put("accept",               new Integer(WapConstants.HEADER_ACCEPT));
153         myWspHeaders.put("accept-charset",       new Integer(WapConstants.HEADER_ACCEPT_CHARSET));
154         myWspHeaders.put("accept-encoding",      new Integer(WapConstants.HEADER_ACCEPT_ENCODING));
155         myWspHeaders.put("accept-language",      new Integer(WapConstants.HEADER_ACCEPT_LANGUAGE));
156         myWspHeaders.put("accept-ranges",        new Integer(WapConstants.HEADER_ACCEPT_RANGES));
157         myWspHeaders.put("age",                  new Integer(WapConstants.HEADER_AGE));
158         myWspHeaders.put("allow",                new Integer(WapConstants.HEADER_ALLOW));
159         myWspHeaders.put("authorization",        new Integer(WapConstants.HEADER_AUTHORIZATION));
160         myWspHeaders.put("cache-control",        new Integer(WapConstants.HEADER_CACHE_CONTROL));
161         myWspHeaders.put("connection",           new Integer(WapConstants.HEADER_CONNECTION));
162         myWspHeaders.put("content-base",         new Integer(WapConstants.HEADER_CONTENT_BASE));
163         myWspHeaders.put("content-encoding",     new Integer(WapConstants.HEADER_CONTENT_ENCODING));
164         myWspHeaders.put("content-language",     new Integer(WapConstants.HEADER_CONTENT_LANGUAGE));
165         myWspHeaders.put("content-length",       new Integer(WapConstants.HEADER_CONTENT_LENGTH));
166         myWspHeaders.put("content-location",     new Integer(WapConstants.HEADER_CONTENT_LOCATION));
167         myWspHeaders.put("content-md5",          new Integer(WapConstants.HEADER_CONTENT_MD5));
168         myWspHeaders.put("content-range",        new Integer(WapConstants.HEADER_CONTENT_RANGE));
169         myWspHeaders.put("content-type",         new Integer(WapConstants.HEADER_CONTENT_TYPE));
170         myWspHeaders.put("date",                 new Integer(WapConstants.HEADER_DATE));
171         myWspHeaders.put("etag",                 new Integer(WapConstants.HEADER_ETAG));
172         myWspHeaders.put("expires",              new Integer(WapConstants.HEADER_EXPIRES));
173         myWspHeaders.put("from",                 new Integer(WapConstants.HEADER_FROM));
174         myWspHeaders.put("host",                 new Integer(WapConstants.HEADER_HOST));
175         myWspHeaders.put("if-modified-since",    new Integer(WapConstants.HEADER_IF_MODIFIED_SINCE));
176         myWspHeaders.put("if-match",             new Integer(WapConstants.HEADER_IF_MATCH));
177         myWspHeaders.put("if-none-match",        new Integer(WapConstants.HEADER_IF_NONE_MATCH));
178         myWspHeaders.put("if-range",             new Integer(WapConstants.HEADER_IF_RANGE));
179         myWspHeaders.put("if-unmodified-since",  new Integer(WapConstants.HEADER_IF_UNMODIFIED_SINCE));
180         myWspHeaders.put("location",             new Integer(WapConstants.HEADER_LOCATION));
181         myWspHeaders.put("last-modified",        new Integer(WapConstants.HEADER_LAST_MODIFIED));
182         myWspHeaders.put("max-forwards",         new Integer(WapConstants.HEADER_MAX_FORWARDS));
183         myWspHeaders.put("pragma",               new Integer(WapConstants.HEADER_PRAGMA));
184         myWspHeaders.put("proxy-authenticate",   new Integer(WapConstants.HEADER_PROXY_AUTHENTICATE));
185         myWspHeaders.put("proxy-authorization",  new Integer(WapConstants.HEADER_PROXY_AUTHORIZATION));
186         myWspHeaders.put("public",               new Integer(WapConstants.HEADER_PUBLIC));
187         myWspHeaders.put("range",                new Integer(WapConstants.HEADER_RANGE));
188         myWspHeaders.put("referer",              new Integer(WapConstants.HEADER_REFERER));
189         myWspHeaders.put("retry-after",          new Integer(WapConstants.HEADER_RETRY_AFTER));
190         myWspHeaders.put("server",               new Integer(WapConstants.HEADER_SERVER));
191         myWspHeaders.put("transfer-encoding",    new Integer(WapConstants.HEADER_TRANSFER_ENCODING));
192         myWspHeaders.put("upgrade",              new Integer(WapConstants.HEADER_UPGRADE));
193         myWspHeaders.put("user-agent",           new Integer(WapConstants.HEADER_USER_AGENT));
194         myWspHeaders.put("vary",                 new Integer(WapConstants.HEADER_VARY));
195         myWspHeaders.put("via",                  new Integer(WapConstants.HEADER_VIA));
196         myWspHeaders.put("warning",              new Integer(WapConstants.HEADER_WARNING));
197         myWspHeaders.put("www-authenticate",     new Integer(WapConstants.HEADER_WWW_AUTHENTICATE));
198         myWspHeaders.put("content-disposition",  new Integer(WapConstants.HEADER_CONTENT_DISPOSITION));
199         
200         // WSP 1.2
201         myWspHeaders.put("accept",               new Integer(WapConstants.HEADER_ACCEPT));
202         myWspHeaders.put("x-wap-application-id", new Integer(WapConstants.HEADER_X_WAP_APPLICATION_ID));
203         myWspHeaders.put("x-wap-content-uri",    new Integer(WapConstants.HEADER_X_WAP_CONTENT_URI));
204         myWspHeaders.put("x-wap-initiator-uri",  new Integer(WapConstants.HEADER_X_WAP_INITIATOR_URI));
205         myWspHeaders.put("bearer-indication",    new Integer(WapConstants.HEADER_BEARER_INDICATION));
206         myWspHeaders.put("accept-application",   new Integer(WapConstants.HEADER_ACCEPT_APPLICATION));
207         myWspHeaders.put("push-flag",            new Integer(WapConstants.HEADER_PUSH_FLAG));
208         myWspHeaders.put("profile",              new Integer(WapConstants.HEADER_PROFILE));
209         myWspHeaders.put("profile-diff",         new Integer(WapConstants.HEADER_PROFILE_DIFF));
210         myWspHeaders.put("profile-warning",      new Integer(WapConstants.HEADER_PROFILE_WARNING));
211         
212         // WSP 1.3
213         myWspHeaders.put("expect",               new Integer(WapConstants.HEADER_EXPECT));
214         myWspHeaders.put("te",                   new Integer(WapConstants.HEADER_TE));
215         myWspHeaders.put("trailer",              new Integer(WapConstants.HEADER_TRAILER));
216         myWspHeaders.put("accept-charset",       new Integer(WapConstants.HEADER_ACCEPT_CHARSET));
217         myWspHeaders.put("accept-encoding",      new Integer(WapConstants.HEADER_ACCEPT_ENCODING));
218         myWspHeaders.put("cache-control",        new Integer(WapConstants.HEADER_CACHE_CONTROL));
219         myWspHeaders.put("content-range",        new Integer(WapConstants.HEADER_CONTENT_RANGE));
220         myWspHeaders.put("x-wap-tod",            new Integer(WapConstants.HEADER_X_WAP_TOD));
221         myWspHeaders.put("content-id",           new Integer(WapConstants.HEADER_CONTENT_ID));
222         myWspHeaders.put("set-cookie",           new Integer(WapConstants.HEADER_SET_COOKIE));
223         myWspHeaders.put("cookie",               new Integer(WapConstants.HEADER_COOKIE));
224         myWspHeaders.put("encoding-version",     new Integer(WapConstants.HEADER_ENCODING_VERSION));
225         
226         // WSP 1.4
227         myWspHeaders.put("profile-warning",      new Integer(WapConstants.HEADER_PROFILE_WARNING));
228         myWspHeaders.put("content-disposition",  new Integer(WapConstants.HEADER_CONTENT_DISPOSITION));
229         myWspHeaders.put("x-wap-security",       new Integer(WapConstants.HEADER_X_WAP_SECURITY));
230         myWspHeaders.put("cache-control",        new Integer(WapConstants.HEADER_CACHE_CONTROL));
231         
232         // http://www.wapforum.org/wina/wsp-content-type.htm
233         // WSP 1.1
234         myWspContentTypes = new HashMap();        
235         myWspContentTypes.put("*/*",                                            new Integer(0x00));
236         myWspContentTypes.put("text/*",                                         new Integer(0x01));
237         myWspContentTypes.put("text/html",                                      new Integer(0x02));
238         myWspContentTypes.put("text/plain",                                     new Integer(0x03));
239         myWspContentTypes.put("text/x-hdml",                                    new Integer(0x04));
240         myWspContentTypes.put("text/x-ttml",                                    new Integer(0x05));
241         myWspContentTypes.put("text/x-vCalendar",                               new Integer(0x06));
242         myWspContentTypes.put("text/x-vCard",                                   new Integer(0x07));
243         myWspContentTypes.put("text/vnd.wap.wml",                               new Integer(0x08));
244         myWspContentTypes.put("text/vnd.wap.wmlscript",                         new Integer(0x09));
245         myWspContentTypes.put("text/vnd.wap.wta-event",                         new Integer(0x0A));
246         myWspContentTypes.put("multipart/*",                                    new Integer(0x0B));
247         myWspContentTypes.put("multipart/mixed",                                new Integer(0x0C));
248         myWspContentTypes.put("multipart/form-data",                            new Integer(0x0D));
249         myWspContentTypes.put("multipart/byteranges",                           new Integer(0x0E));
250         myWspContentTypes.put("multipart/alternative",                          new Integer(0x0F));
251         myWspContentTypes.put("application/*",                                  new Integer(0x10));
252         myWspContentTypes.put("application/java-vm",                            new Integer(0x11));
253         myWspContentTypes.put("application/x-www-form-urlencoded",              new Integer(0x12));
254         myWspContentTypes.put("application/x-hdmlc",                            new Integer(0x13));
255         myWspContentTypes.put("application/vnd.wap.wmlc",                       new Integer(0x14));
256         myWspContentTypes.put("application/vnd.wap.wmlscriptc",                 new Integer(0x15));
257         myWspContentTypes.put("application/vnd.wap.wta-eventc",                 new Integer(0x16));
258         myWspContentTypes.put("application/vnd.wap.uaprof",                     new Integer(0x17));
259         myWspContentTypes.put("application/vnd.wap.wtls-ca-certificate",        new Integer(0x18));
260         myWspContentTypes.put("application/vnd.wap.wtls-user-certificate",      new Integer(0x19));
261         myWspContentTypes.put("application/x-x509-ca-cert",                     new Integer(0x1A));
262         myWspContentTypes.put("application/x-x509-user-cert",                   new Integer(0x1B));
263         myWspContentTypes.put("image/*",                                        new Integer(0x1C));
264         myWspContentTypes.put("image/gif",                                      new Integer(0x1D));
265         myWspContentTypes.put("image/jpeg",                                     new Integer(0x1E));
266         myWspContentTypes.put("image/tiff",                                     new Integer(0x1F));
267         myWspContentTypes.put("image/png",                                      new Integer(0x20));
268         myWspContentTypes.put("image/vnd.wap.wbmp",                             new Integer(0x21));
269         myWspContentTypes.put("application/vnd.wap.multipart.*",                new Integer(0x22));
270         myWspContentTypes.put("application/vnd.wap.multipart.mixed",            new Integer(0x23));
271         myWspContentTypes.put("application/vnd.wap.multipart.form-data",        new Integer(0x24));
272         myWspContentTypes.put("application/vnd.wap.multipart.byteranges",       new Integer(0x25));
273         myWspContentTypes.put("application/vnd.wap.multipart.alternative",      new Integer(0x26));
274         myWspContentTypes.put("application/xml",                                new Integer(0x27));
275         myWspContentTypes.put("text/xml",                                       new Integer(0x28));
276         myWspContentTypes.put("application/vnd.wap.wbxml",                      new Integer(0x29));
277         myWspContentTypes.put("application/x-x968-cross-cert",                  new Integer(0x2A));
278         myWspContentTypes.put("application/x-x968-ca-cert",                     new Integer(0x2B));
279         myWspContentTypes.put("application/x-x968-user-cert",                   new Integer(0x2C));
280         myWspContentTypes.put("text/vnd.wap.si",                                new Integer(0x2D));
281 
282         // WSP 1.2
283         myWspContentTypes.put("application/vnd.wap.sic",                        new Integer(0x2E));
284         myWspContentTypes.put("text/vnd.wap.sl",                                new Integer(0x2F));
285         myWspContentTypes.put("application/vnd.wap.slc",                        new Integer(0x30));
286         myWspContentTypes.put("text/vnd.wap.co",                                new Integer(0x31));
287         myWspContentTypes.put("application/vnd.wap.coc",                        new Integer(0x32));
288         myWspContentTypes.put("application/vnd.wap.multipart.related",          new Integer(0x33));
289         myWspContentTypes.put("application/vnd.wap.sia",                        new Integer(0x34));
290                 
291         // WSP 1.3
292         myWspContentTypes.put("text/vnd.wap.connectivity-xml",                  new Integer(0x35));
293         myWspContentTypes.put("application/vnd.wap.connectivity-wbxml",         new Integer(0x36));
294         
295         // WSP 1.4
296         myWspContentTypes.put("application/pkcs7-mime",                         new Integer(0x37));
297         myWspContentTypes.put("application/vnd.wap.hashed-certificate",         new Integer(0x38));
298         myWspContentTypes.put("application/vnd.wap.signed-certificate",         new Integer(0x39));
299         myWspContentTypes.put("application/vnd.wap.cert-response",              new Integer(0x3A));
300         myWspContentTypes.put("application/xhtml+xml",                          new Integer(0x3B));
301         myWspContentTypes.put("application/wml+xml",                            new Integer(0x3C));
302         myWspContentTypes.put("text/css",                                       new Integer(0x3D));
303         myWspContentTypes.put("application/vnd.wap.mms-message",                new Integer(0x3E));
304         myWspContentTypes.put("application/vnd.wap.rollover-certificate",       new Integer(0x3F));
305         
306         // WSP 1.5
307         myWspContentTypes.put("application/vnd.wap.locc+wbxml",                 new Integer(0x40));
308         myWspContentTypes.put("application/vnd.wap.loc+xml",                    new Integer(0x41));
309         myWspContentTypes.put("application/vnd.syncml.dm+wbxml",                new Integer(0x42));
310         myWspContentTypes.put("application/vnd.syncml.dm+xml",                  new Integer(0x43));
311         myWspContentTypes.put("application/vnd.syncml.notification",            new Integer(0x44));
312         myWspContentTypes.put("application/vnd.wap.xhtml+xml",                  new Integer(0x45));
313         myWspContentTypes.put("application/vnd.wv.csp.cir",                     new Integer(0x46));
314         myWspContentTypes.put("application/vnd.oma.dd+xml",                     new Integer(0x47));
315         myWspContentTypes.put("application/vnd.oma.drm.message",                new Integer(0x48));
316         myWspContentTypes.put("application/vnd.oma.drm.content",                new Integer(0x49));
317         myWspContentTypes.put("application/vnd.oma.drm.rights+xml",             new Integer(0x4A));
318         myWspContentTypes.put("application/vnd.oma.drm.rights+wbxml",           new Integer(0x4B));
319         
320         // WSP 1.1
321         myWspParameters = new HashMap();
322         myWspParameters.put("q",                    new Integer(WapConstants.PARAMETER_Q));
323         myWspParameters.put("charset",              new Integer(WapConstants.PARAMETER_CHARSET));
324         myWspParameters.put("level",                new Integer(WapConstants.PARAMETER_LEVEL));
325         myWspParameters.put("type",                 new Integer(WapConstants.PARAMETER_TYPE));
326         myWspParameters.put("name",                 new Integer(WapConstants.PARAMETER_NAME));
327         myWspParameters.put("filename",             new Integer(WapConstants.PARAMETER_FILENAME));
328         myWspParameters.put("differences",          new Integer(WapConstants.PARAMETER_DIFFERENCES));
329         myWspParameters.put("padding",              new Integer(WapConstants.PARAMETER_PADDING));
330             
331         // WSP 1.2
332         myWspParameters.put("type",                 new Integer(WapConstants.PARAMETER_TYPE_MULTIPART_RELATED));
333         myWspParameters.put("start",                new Integer(WapConstants.PARAMETER_START_MULTIPART_RELATED));
334         myWspParameters.put("start-info",           new Integer(WapConstants.PARAMETER_START_INFO_MULTIPART_RELATED));
335             
336         // WSP 1.3
337         myWspParameters.put("comment",              new Integer(WapConstants.PARAMETER_COMMENT));
338         myWspParameters.put("domain",               new Integer(WapConstants.PARAMETER_DOMAIN));
339         myWspParameters.put("max-age",              new Integer(WapConstants.PARAMETER_MAX_AGE));
340         myWspParameters.put("path",                 new Integer(WapConstants.PARAMETER_PATH));
341         myWspParameters.put("secure",               new Integer(WapConstants.PARAMETER_SECURE));
342             
343         // WSP 1.4
344         myWspParameters.put("sec",                  new Integer(WapConstants.PARAMETER_SEC_CONNECTIVITY));
345         myWspParameters.put("mac",                  new Integer(WapConstants.PARAMETER_MAC_CONNECTIVITY));
346         myWspParameters.put("creation-date",        new Integer(WapConstants.PARAMETER_CREATION_DATE));
347         myWspParameters.put("modification-date",    new Integer(WapConstants.PARAMETER_MODIFICATION_DATE));
348         myWspParameters.put("read-date",            new Integer(WapConstants.PARAMETER_READ_DATE));
349         myWspParameters.put("size",                 new Integer(WapConstants.PARAMETER_SIZE));
350         myWspParameters.put("name",                 new Integer(WapConstants.PARAMETER_NAME));
351         myWspParameters.put("filename",             new Integer(WapConstants.PARAMETER_FILENAME));
352         myWspParameters.put("start",                new Integer(WapConstants.PARAMETER_START_MULTIPART_RELATED));
353         myWspParameters.put("start-info",           new Integer(WapConstants.PARAMETER_START_INFO_MULTIPART_RELATED));
354         myWspParameters.put("comment",              new Integer(WapConstants.PARAMETER_COMMENT));
355         myWspParameters.put("domain",               new Integer(WapConstants.PARAMETER_DOMAIN));
356         myWspParameters.put("path",                 new Integer(WapConstants.PARAMETER_PATH));
357         
358         // http://www.wapforum.org/wina/push-app-id.htm
359         myWspPushAppTypes = new HashMap();
360         myWspPushAppTypes.put("x-wap-application:*",            new Integer(0x00));
361         myWspPushAppTypes.put("x-wap-application:push.sia",     new Integer(0x01));
362         myWspPushAppTypes.put("x-wap-application:wml.ua",       new Integer(0x02));
363         myWspPushAppTypes.put("x-wap-application:wta.ua",       new Integer(0x03));
364         myWspPushAppTypes.put("x-wap-application:mms.ua",       new Integer(0x04));
365         myWspPushAppTypes.put("x-wap-application:push.syncml",  new Integer(0x05));
366         myWspPushAppTypes.put("x-wap-application:loc.ua",       new Integer(0x06));
367         myWspPushAppTypes.put("x-wap-application:syncml.dm",    new Integer(0x07));
368         myWspPushAppTypes.put("x-wap-application:drm.ua",       new Integer(0x08));
369         myWspPushAppTypes.put("x-wap-application:emn.ua",       new Integer(0x09));
370         myWspPushAppTypes.put("x-wap-application:wv.ua",        new Integer(0x0A));
371         
372         myWspPushAppTypes.put("x-wap-microsoft:localcontent.ua",    new Integer(0x8000));
373         myWspPushAppTypes.put("x-wap-microsoft:imclient.ua ",       new Integer(0x8001));
374         myWspPushAppTypes.put("x-wap-docomo:imode.mail.ua ",        new Integer(0x8002));
375         myWspPushAppTypes.put("x-wap-docomo:imode.mr.ua",           new Integer(0x8003));
376         myWspPushAppTypes.put("x-wap-docomo:imode.mf.ua",           new Integer(0x8004));
377         myWspPushAppTypes.put("x-motorola:location.ua ",            new Integer(0x8005));
378         myWspPushAppTypes.put("x-motorola:now.ua",                  new Integer(0x8006));
379         myWspPushAppTypes.put("x-motorola:otaprov.ua",              new Integer(0x8007));
380         myWspPushAppTypes.put("x-motorola:browser.ua",              new Integer(0x8008));
381         myWspPushAppTypes.put("x-motorola:splash.ua",               new Integer(0x8009));
382         myWspPushAppTypes.put("x-wap-nai:mvsw.command ",            new Integer(0x800B));
383         myWspPushAppTypes.put("x-wap-openwave:iota.ua",             new Integer(0x8010));
384     }
385     
386     private WspUtil()
387     {
388     }
389 
390     /***
391      * Converts a header name to a header type (WapConstants.HEADER_*).
392      * 
393      * The header name to be found must be in lower case (for performance reasons).
394      * 
395      * @param headerName The name of the header.
396      * @return The header type, or -1 if not found.
397      */
398     public static int getHeaderType(String headerName)
399     {
400         Integer headerType = (Integer) myWspHeaders.get(headerName);
401         
402         return (headerType != null) ? (headerType.intValue()) : (-1);
403     }
404    
405     /***
406      * Converts a header type (WapConstants.HEADER_*) to a well known header id.
407      * 
408      * @param wspEncodingVersion The requested wsp encoding version
409      * @param headerType The header type
410      * @return A well known header id or -1 if not found.
411      */
412     public static int getWellKnownHeaderId(byte wspEncodingVersion, int headerType)
413     {
414         int wellKnownHeaderId;
415 
416         switch (wspEncodingVersion)
417         {
418         case WapConstants.WSP_ENCODING_VERSION_1_1:
419             wellKnownHeaderId = WELL_KNOWN_HEADER_ID_WSP_11[headerType];
420             break;
421         case WapConstants.WSP_ENCODING_VERSION_1_2:
422             wellKnownHeaderId = WELL_KNOWN_HEADER_ID_WSP_12[headerType];
423             break;
424             
425         case WapConstants.WSP_ENCODING_VERSION_1_3:
426             wellKnownHeaderId = WELL_KNOWN_HEADER_ID_WSP_13[headerType];
427             break;
428             
429         case WapConstants.WSP_ENCODING_VERSION_1_4:
430         case WapConstants.WSP_ENCODING_VERSION_1_5:
431             wellKnownHeaderId = WELL_KNOWN_HEADER_ID_WSP_14[headerType];
432             break;
433         
434         default:
435             wellKnownHeaderId = -1;
436         }
437 
438         return wellKnownHeaderId;
439     }
440     
441     /***
442      * Converts a content type to a WINA "well-known" content type id.
443      * 
444      * http://www.wapforum.org/wina/wsp-content-type.htm
445      * 
446      * @param wspEncodingVersion The requested wsp encoding version
447      * @param contentType The content type
448      * @return A well known content type id or -1 if not found.
449      */
450     public static int getWellKnownContentTypeId(byte wspEncodingVersion, String contentType)
451     {
452         Integer contentTypeIdInt = (Integer) myWspContentTypes.get(contentType);        
453 
454         if (contentTypeIdInt == null)
455         {
456             return -1;
457         }
458         
459         int wellKnownContentTypeId = contentTypeIdInt.intValue();
460         
461         if ( (wspEncodingVersion >= WapConstants.WSP_ENCODING_VERSION_1_1) && (wellKnownContentTypeId <= 0x2D) )
462         {
463             return wellKnownContentTypeId;
464         }
465         else if ( (wspEncodingVersion >= WapConstants.WSP_ENCODING_VERSION_1_2) && (wellKnownContentTypeId <= 0x34) )
466         {
467             return wellKnownContentTypeId;
468         }
469         else if ( (wspEncodingVersion >= WapConstants.WSP_ENCODING_VERSION_1_3) && (wellKnownContentTypeId <= 0x36) )
470         {
471             return wellKnownContentTypeId;
472         }
473         else if ( (wspEncodingVersion >= WapConstants.WSP_ENCODING_VERSION_1_4) && (wellKnownContentTypeId <= 0x3F) )
474         {
475             return wellKnownContentTypeId;
476         }
477         else if ( (wspEncodingVersion >= WapConstants.WSP_ENCODING_VERSION_1_5) && (wellKnownContentTypeId <= 0x4B) )
478         {
479             return wellKnownContentTypeId;
480         }
481         else
482         {
483             return -1;
484         }
485     }
486     
487     /***
488      * Converts a parameter name to a parameter type (WapConstants.PARAMETER_*).
489      * 
490      * The header name to be found must be in lower case (for performance reasons).
491      * 
492      * @param parameterName The name of the parameter.
493      * @return The parameter type, or -1 if not found.
494      */
495     public static int getParameterType(String parameterName)
496     {
497         Integer parameterType = (Integer) myWspParameters.get(parameterName);
498         
499         return (parameterType != null) ? (parameterType.intValue()) : (-1);
500     }
501 
502     /***
503      * Converts a parameter name to a parameter type (WapConstants.WSP_PARAMETER_TYPE_*).
504      * 
505      * @param wellKnownParameterId The well known parameter id to lookup.
506      * @return The parameter type, or -1 if not found.
507      */
508     public static int getWspParameterType(int wellKnownParameterId)
509     {
510         return PARAMETER_TYPES[wellKnownParameterId];
511     }
512     
513     /***
514      * Converts a parameter type (WapConstants.PARAMETER_*) to a well known parameter id.
515      * 
516      * @param wspEncodingVersion The requested wsp encoding version
517      * @param parameterType The header type
518      * @return A well known parameter id or -1 if not found.
519      */
520     public static int getWellKnownParameterId(byte wspEncodingVersion, int parameterType)
521     {
522         int wellKnownParameterId = -1;
523 
524         if (parameterType >= 0)
525         {
526             switch (wspEncodingVersion)
527             {
528             case WapConstants.WSP_ENCODING_VERSION_1_1:
529                 wellKnownParameterId = WELL_KNOWN_PARAMETER_ID_WSP_11[parameterType];
530                 break;
531             case WapConstants.WSP_ENCODING_VERSION_1_2:
532                 wellKnownParameterId = WELL_KNOWN_PARAMETER_ID_WSP_12[parameterType];
533                 break;
534                 
535             case WapConstants.WSP_ENCODING_VERSION_1_3:
536                 wellKnownParameterId = WELL_KNOWN_PARAMETER_ID_WSP_13[parameterType];
537                 break;
538                 
539             case WapConstants.WSP_ENCODING_VERSION_1_4:
540             case WapConstants.WSP_ENCODING_VERSION_1_5:
541                 wellKnownParameterId = WELL_KNOWN_PARAMETER_ID_WSP_14[parameterType];
542                 break;
543             
544             default:
545             }
546         }
547         
548         return wellKnownParameterId;
549     }
550     
551     /***
552      * Converts a push app to a WINA "well-known" push app id.
553      * 
554      * http://www.wapforum.org/wina/push-app-id.htm
555      * 
556      * @param pushApp The push app
557      * @return A well known push app id or -1 if not found.
558      */
559     public static int getWellKnownPushAppId(String pushApp)
560     {
561         Integer pushAppIdInt = (Integer) myWspPushAppTypes.get(pushApp);        
562 
563         if (pushAppIdInt == null)
564         {
565             return -1;
566         }
567         
568         return pushAppIdInt.intValue();
569     }
570     
571     /***
572      * Writes a "uint8" in wsp format to the given output stream.
573      * 
574      * @param theOs
575      *            Stream to write to
576      * @param theValue
577      *            Value to write
578      */
579     public static void writeUint8(OutputStream theOs, int theValue) throws IOException
580     {
581         theOs.write(theValue);
582     }
583 
584     /***
585      * Writes a "Uintvar" in wsp format to the given output stream.
586      * 
587      * @param theOs
588      *            Stream to write to
589      * @param theValue
590      *            Value to write
591      */
592     public static void writeUintvar(OutputStream theOs, long theValue) throws IOException
593     {
594         int nOctets = 1;
595         while ((theValue >> (7 * nOctets)) > 0)
596         {
597             nOctets++;
598         }
599 
600         for (int i = nOctets; i > 0; i--)
601         {
602             byte octet = (byte) (theValue >> (7 * (i - 1)));
603             byte byteValue = (byte) ((byte) octet & (byte) 0x7f);
604             if (i > 1)
605             {
606                 byteValue = (byte) (byteValue | (byte) 0x80);
607             }
608             theOs.write(byteValue);
609         }
610     }
611 
612     /***
613      * Writes a "long integer" in wsp format to the given output stream.
614      * 
615      * @param theOs
616      *            Stream to write to
617      * @param theValue
618      *            Value to write
619      */
620     public static void writeLongInteger(OutputStream theOs, long theValue) throws IOException
621     {
622         int nOctets = 0;
623         while ((theValue >> (8 * nOctets)) > 0)
624         {
625             nOctets++;
626         }
627         theOs.write((byte) nOctets);
628 
629         for (int i = nOctets; i > 0; i--)
630         {
631             byte octet = (byte) (theValue >> (8 * (i - 1)));
632             byte byteValue = (byte) ((byte) octet & (byte) (0xff));
633             theOs.write(byteValue);
634         }
635     }
636 
637     /***
638      * Writes an "integer" in wsp format to the given output stream.
639      * 
640      * @param theOs
641      * @param theValue
642      */
643     public static void writeInteger(OutputStream theOs, long theValue) throws IOException
644     {
645         if (theValue < 128)
646         {
647             writeShortInteger(theOs, (int) theValue);
648         }
649         else
650         {
651             writeLongInteger(theOs, theValue);
652         }
653     }
654 
655     /***
656      * Writes a "short integer" in wsp format to the given output stream.
657      * 
658      * @param theOs
659      *            Stream to write to
660      * @param theValue
661      *            Value to write
662      */
663     public static void writeShortInteger(OutputStream theOs, int theValue) throws IOException
664     {
665         theOs.write((byte) (theValue | (byte) 0x80));
666     }
667 
668     public static void writeValueLength(OutputStream theOs, long theValue) throws IOException
669     {
670         // ShortLength | (Length-quote Length)
671 
672         if (theValue <= 30)
673         {
674             // Short-length
675             theOs.write((int) theValue);
676         }
677         else
678         {
679             // Length-quote == Octet 31
680             theOs.write(31);
681             writeUintvar(theOs, theValue);
682         }
683     }
684 
685     /***
686      * Writes an "extension media" in pdu format to the given output stream. It
687      * currently only handles ASCII chars, but should be extended to work with
688      * other charsets.
689      * 
690      * @param theOs
691      *            Stream to write to
692      * @param theStr
693      *            Text to write
694      */
695     public static void writeExtensionMedia(OutputStream theOs, String theStr) throws IOException
696     {
697         theOs.write(theStr.getBytes("ISO-8859-1"));
698         theOs.write((byte) 0x00);
699     }
700 
701     public static void writeTextString(OutputStream theOs, String theStr) throws IOException
702     {
703         /*
704          * Text-string = [Quote] *TEXT End-of-string ; If the first character in
705          * the TEXT is in the range of 128-255, a Quote character must precede
706          * it. ; Otherwise the Quote character must be omitted. The Quote is not
707          * part of the contents. Quote = <Octet 127> End-of-string = <Octet 0>
708          */
709 
710         byte[] strBytes = theStr.getBytes("ISO-8859-1");
711 
712         if ((strBytes[0] & 0x80) > 0x00)
713         {
714             theOs.write(0x7f);
715         }
716 
717         theOs.write(strBytes);
718         theOs.write(0x00);
719     }
720 
721     public static void writeQuotedString(OutputStream theOs, String theStr) throws IOException
722     {
723         /*
724          * Quoted-string = <Octet 34> *TEXT End-of-string ;The TEXT encodes an
725          * RFC2616 Quoted-string with the enclosing quotation-marks <"> removed
726          */
727 
728         // <Octet 34>
729         theOs.write(34);
730 
731         theOs.write(theStr.getBytes("ISO-8859-1"));
732         theOs.write(0x00);
733     }
734 
735     public static void writeTokenText(OutputStream theOs, String theStr) throws IOException
736     {
737         /*
738          * Token-Text = Token End-of-string
739          */
740         // TODO: Token => RFC2616
741         theOs.write(theStr.getBytes("ISO-8859-1"));
742         theOs.write(0x00);
743     }
744 
745     public static void writeTextValue(OutputStream theOs, String theStr) throws IOException
746     {
747         /*
748          * // No-value | Token-text | Quoted-string
749          */
750         // FIXME: Verify
751         writeQuotedString(theOs, theStr);
752     }
753 
754     /***
755      * Writes a wsp encoded content-type as specified in
756      * WAP-230-WSP-20010705-a.pdf.
757      * <p>
758      * Uses the "constrained media" format. <br>
759      * Note! This method can only be used on simple content types (like
760      * "text/plain" or "image/gif"). If a more complex content-type is needed
761      * (like "image/gif; start=cid; parameter=value;") you must use the
762      * MimeContentType class.
763      * 
764      * @param theOs
765      * @param theContentType
766      * @throws IOException
767      */
768     public static void writeContentType(byte wspEncodingVersion, OutputStream theOs, String theContentType) throws IOException
769     {
770         int wellKnownContentType = WspUtil.getWellKnownContentTypeId(wspEncodingVersion, theContentType.toLowerCase());
771 
772         if (wellKnownContentType == -1)
773         {
774             writeValueLength(theOs, theContentType.length() + 1);
775             writeExtensionMedia(theOs, theContentType);
776         }
777         else
778         {
779             writeShortInteger(theOs, wellKnownContentType);
780         }
781     }
782 
783     /***
784      * Writes a wsp encoded content-type as specified in
785      * WAP-230-WSP-20010705-a.pdf.
786      * <p>
787      * This method automatically chooses the most compact way to represent the
788      * given content type.
789      * 
790      * @param theOs
791      * @param theContentType
792      * @throws IOException
793      */
794     public static void writeContentType(byte wspEncodingVersion, OutputStream theOs, MimeHeader theContentType) throws IOException
795     {
796         if (theContentType.getParamCount() == 0)
797         {
798             // Simple content type, use "constrained-media" format
799             writeContentType(wspEncodingVersion, theOs, theContentType.getValue());
800         }
801         else
802         {
803             String theContentTypeStr = theContentType.getValue();
804             // Complex, use "content-general-form"
805             int wellKnownContentType = WspUtil.getWellKnownContentTypeId(wspEncodingVersion, theContentTypeStr.toLowerCase());
806 
807             // Create parameter byte array of
808             // well-known-media (integer) or extension media
809             // 0 or more parameters
810             ByteArrayOutputStream baos = new ByteArrayOutputStream();
811             if (wellKnownContentType == -1)
812             {
813                 writeExtensionMedia(baos, theContentType.getValue());
814             }
815             else
816             {
817                 // well-known-media (integer)
818                 writeInteger(baos, wellKnownContentType);
819             }
820 
821             // Add Parameters
822             for (int i = 0; i < theContentType.getParamCount(); i++)
823             {
824                 MimeHeaderParam headerParam = theContentType.getParam(i);
825                 writeParameter(wspEncodingVersion, baos, headerParam.getName(), headerParam.getValue());
826             }
827             baos.close();
828 
829             // Write to stream
830 
831             // content-general-form
832             // value length
833             writeValueLength(theOs, baos.size());
834             // Write parameter byte array
835             theOs.write(baos.toByteArray());
836         }
837     }
838 
839     public static void writeTypedValue(byte wspEncodingVersion, OutputStream os, int wspParamType, String value) throws IOException
840     {
841         switch (wspParamType)
842         {
843         // "Used to indicate that the parameter actually have no value,
844         // eg, as the parameter "bar" in ";foo=xxx; bar; baz=xyzzy"."
845         case WapConstants.WSP_PARAMETER_TYPE_NO_VALUE:
846             os.write(0x00);
847             break;
848 
849         case WapConstants.WSP_PARAMETER_TYPE_TEXT_VALUE:
850             writeTextValue(os, value);
851             break;
852 
853         case WapConstants.WSP_PARAMETER_TYPE_INTEGER_VALUE:
854             writeInteger(os, Long.parseLong(value));
855             break;
856 
857         case WapConstants.WSP_PARAMETER_TYPE_DATE_VALUE:
858             /*
859              * ; The encoding of dates shall be done in number of seconds from ;
860              * 1970-01-01, 00:00:00 GMT.
861              */
862             Long l = Long.valueOf(value);
863             writeLongInteger(os, l.longValue());
864             break;
865 
866         case WapConstants.WSP_PARAMETER_TYPE_DELTA_SECONDS_VALUE:
867             // Integer-Value
868             Integer i = Integer.valueOf(value);
869             writeInteger(os, i.intValue());
870             break;
871 
872         case WapConstants.WSP_PARAMETER_TYPE_Q_VALUE:
873             // TODO: Implement
874             /*
875              * ; The encoding is the same as in Uintvar-integer, but with
876              * restricted size. When quality factor 0 ; and quality factors with
877              * one or two decimal digits are encoded, they shall be multiplied
878              * by 100 ; and incremented by one, so that they encode as a
879              * one-octet value in range 1-100, ; ie, 0.1 is encoded as 11 (0x0B)
880              * and 0.99 encoded as 100 (0x64). Three decimal quality ; factors
881              * shall be multiplied with 1000 and incremented by 100, and the
882              * result shall be encoded ; as a one-octet or two-octet uintvar,
883              * eg, 0.333 shall be encoded as 0x83 0x31. ; Quality factor 1 is
884              * the default value and shall never be sent.
885              */
886             writeTextString(os, value);
887             break;
888 
889         case WapConstants.WSP_PARAMETER_TYPE_VERSION_VALUE:
890             // TODO: Implement
891             /*
892              * ; The three most significant bits of the Short-integer value are
893              * interpreted to encode a major ; version number in the range 1-7,
894              * and the four least significant bits contain a minor version ;
895              * number in the range 0-14. If there is only a major version
896              * number, this is encoded by ; placing the value 15 in the four
897              * least significant bits. If the version to be encoded fits these ;
898              * constraints, a Short-integer must be used, otherwise a
899              * Text-string shall be used.
900              */
901             writeTextString(os, value);
902             break;
903 
904         case WapConstants.WSP_PARAMETER_TYPE_URI_VALUE:
905             // Text-String
906             // TODO: Verify
907             /*
908              * ; URI value should be encoded per [RFC2616], but service user may
909              * use a different format.
910              */
911             writeTextString(os, value);
912             break;
913 
914         case WapConstants.WSP_PARAMETER_TYPE_TEXT_STRING:
915             writeTextString(os, value);
916             break;
917 
918         case WapConstants.WSP_PARAMETER_TYPE_WELL_KNOWN_CHARSET:
919             // Any-Charset | Integer-Value
920             // ; Both are encoded using values from Character Set Assignments
921             // table in Assigned Numbers
922             // TODO: Implement correctly. Currently we always say "UTF8"
923             writeInteger(os, WapConstants.MIB_ENUM_UTF_8);
924             break;
925 
926         case WapConstants.WSP_PARAMETER_TYPE_FIELD_NAME:
927             // Token-text | Well-known-field-name
928             // TODO: Implement
929             writeTextString(os, value);
930             break;
931 
932         case WapConstants.WSP_PARAMETER_TYPE_SHORT_INTEGER:
933             writeShortInteger(os, Integer.parseInt(value));
934             break;
935 
936         case WapConstants.WSP_PARAMETER_TYPE_CONSTRAINED_ENCODING:
937             // Constrained-Encoding == Content-type
938             writeContentType(wspEncodingVersion, os, value);
939             break;
940 
941         default:
942             // TODO: Implement
943             writeTextString(os, value);
944             break;
945         }
946     }
947 
948     public static void writeParameter(byte wspEncodingVersion, OutputStream os, String name, String value) throws IOException
949     {
950         int parameterType = WspUtil.getParameterType(name);
951         int wellKnownParameter = WspUtil.getWellKnownParameterId(wspEncodingVersion, parameterType);
952 
953         if (wellKnownParameter == -1)
954         {
955             // Untyped-parameter
956             // Token-Text
957             writeTokenText(os, name);
958 
959             // Untyped-value == Integer-Value | Text-value
960             writeTextString(os, value);
961         }
962         else
963         {                        
964             // Typed-parameter
965 
966             // Well-known-parameter-token == Integer-value
967             writeInteger(os, wellKnownParameter);
968             // Typed-value
969             writeTypedValue(wspEncodingVersion, os, getWspParameterType(wellKnownParameter), value);
970         }
971     }
972 
973     /***
974      * Converts from a "multipart/" content type to "vnd.wap..." content type.
975      * 
976      * @param ct
977      * @return
978      */
979     public static String convertMultipartContentType(String ct)
980     {
981         if (ct.equalsIgnoreCase("multipart/*"))
982         {
983             return "application/vnd.wap.multipart.*";
984         }
985         else if (ct.equalsIgnoreCase("multipart/mixed"))
986         {
987             return "application/vnd.wap.multipart.mixed";
988         }
989         else if (ct.equalsIgnoreCase("multipart/form-data"))
990         {
991             return "application/vnd.wap.multipart.form-data";
992         }
993         else if (ct.equalsIgnoreCase("multipart/byteranges"))
994         {
995             return "application/vnd.wap.multipart.byteranges";
996         }
997         else if (ct.equalsIgnoreCase("multipart/alternative"))
998         {
999             return "application/vnd.wap.multipart.alternative";
1000         }
1001         else if (ct.equalsIgnoreCase("multipart/related"))
1002         {
1003             return "application/vnd.wap.multipart.related";
1004         }
1005         else
1006         {
1007             return ct;
1008         }
1009     }
1010 }