19439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/*
2238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde * Copyright (C) 2015 The Android Open Source Project
3238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde * Copyright (C) 2015 Samsung LSI
49439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Copyright (c) 2008-2009, Motorola, Inc.
59439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
69439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * All rights reserved.
79439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
89439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Redistribution and use in source and binary forms, with or without
99439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * modification, are permitted provided that the following conditions are met:
109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Redistributions of source code must retain the above copyright notice,
129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * this list of conditions and the following disclaimer.
139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Redistributions in binary form must reproduce the above copyright notice,
159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * this list of conditions and the following disclaimer in the documentation
169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * and/or other materials provided with the distribution.
179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * - Neither the name of the Motorola, Inc. nor the names of its contributors
199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * may be used to endorse or promote products derived from this software
209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * without specific prior written permission.
219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * POSSIBILITY OF SUCH DAMAGE.
339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */
349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellypackage javax.obex;
369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
372e0da96e757a977154063f980d3f4e1abd41cf09Nick Pellyimport java.io.ByteArrayOutputStream;
382e0da96e757a977154063f980d3f4e1abd41cf09Nick Pellyimport java.io.IOException;
392e0da96e757a977154063f980d3f4e1abd41cf09Nick Pellyimport java.io.UnsupportedEncodingException;
40929a1c219248b62778807cac8ea256c7ac0fda6aBrian Carlstromimport java.security.MessageDigest;
41929a1c219248b62778807cac8ea256c7ac0fda6aBrian Carlstromimport java.security.NoSuchAlgorithmException;
422e0da96e757a977154063f980d3f4e1abd41cf09Nick Pellyimport java.util.Calendar;
432e0da96e757a977154063f980d3f4e1abd41cf09Nick Pellyimport java.util.Date;
442e0da96e757a977154063f980d3f4e1abd41cf09Nick Pellyimport java.util.TimeZone;
459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
46238e0f934f1f47263b384bc745ae0678c777130dCasper Bondeimport android.util.Log;
47238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/**
492e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly * This class defines a set of helper methods for the implementation of Obex.
502e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly * @hide
519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */
522e0da96e757a977154063f980d3f4e1abd41cf09Nick Pellypublic final class ObexHelper {
532e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly
54238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private static final String TAG = "ObexHelper";
55238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public static final boolean VDBG = false;
569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
5705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Defines the basic packet length used by OBEX. Every OBEX packet has the
583998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun     * same basic format:<BR>
5905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Byte 0: Request or Response Code Byte 1&2: Length of the packet.
609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
613998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int BASE_PACKET_LENGTH = 3;
623998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
633998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    /** Prevent object construction of helper class */
643998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    private ObexHelper() {
653998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    }
669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
672e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly    /**
6805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * The maximum packet size for OBEX packets that this client can handle. At
6905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * present, this must be changed for each port. TODO: The max packet size
7005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * should be the Max incoming MTU minus TODO: L2CAP package headers and
7105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * RFCOMM package headers. TODO: Retrieve the max incoming MTU from TODO:
7205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * LocalDevice.getProperty().
73238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * NOTE: This value must be larger than or equal to the L2CAP SDU
742e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     */
7505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun    /*
7605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * android note set as 0xFFFE to match remote MPS
772e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     */
782e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly    public static final int MAX_PACKET_SIZE_INT = 0xFFFE;
799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
80238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    // The minimum allowed max packet size is 255 according to the OBEX specification
81238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public static final int LOWER_LIMIT_MAX_PACKET_SIZE = 255;
82238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
83e83b744d7d0b3caaf8f5456b795331d5db2495a3Erik Ljungberg    /**
84e83b744d7d0b3caaf8f5456b795331d5db2495a3Erik Ljungberg     * Temporary workaround to be able to push files to Windows 7.
85e83b744d7d0b3caaf8f5456b795331d5db2495a3Erik Ljungberg     * TODO: Should be removed as soon as Microsoft updates their driver.
86e83b744d7d0b3caaf8f5456b795331d5db2495a3Erik Ljungberg     */
87e83b744d7d0b3caaf8f5456b795331d5db2495a3Erik Ljungberg    public static final int MAX_CLIENT_PACKET_SIZE = 0xFC00;
88e83b744d7d0b3caaf8f5456b795331d5db2495a3Erik Ljungberg
89238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public static final int OBEX_OPCODE_FINAL_BIT_MASK = 0x80;
90238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
913998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_OPCODE_CONNECT = 0x80;
923998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
933998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_OPCODE_DISCONNECT = 0x81;
943998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
953998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_OPCODE_PUT = 0x02;
963998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
973998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_OPCODE_PUT_FINAL = 0x82;
983998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
993998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_OPCODE_GET = 0x03;
1003998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1013998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_OPCODE_GET_FINAL = 0x83;
1023998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1033998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_OPCODE_RESERVED = 0x04;
1043998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1053998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_OPCODE_RESERVED_FINAL = 0x84;
1063998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1073998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_OPCODE_SETPATH = 0x85;
1083998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1093998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_OPCODE_ABORT = 0xFF;
1103998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1113998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_AUTH_REALM_CHARSET_ASCII = 0x00;
1123998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1133998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_1 = 0x01;
1143998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1153998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_2 = 0x02;
1163998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1173998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_3 = 0x03;
1183998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1193998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_4 = 0x04;
1203998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1213998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_5 = 0x05;
1223998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1233998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_6 = 0x06;
1243998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1253998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_7 = 0x07;
1263998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1273998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_8 = 0x08;
1283998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1293998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_AUTH_REALM_CHARSET_ISO_8859_9 = 0x09;
1303998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
1313998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun    public static final int OBEX_AUTH_REALM_CHARSET_UNICODE = 0xFF;
1323998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun
133238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public static final byte OBEX_SRM_ENABLE         = 0x01; // For BT we only need enable/disable
134238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public static final byte OBEX_SRM_DISABLE        = 0x00;
135238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public static final byte OBEX_SRM_SUPPORT        = 0x02; // Unused for now
136238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
137238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public static final byte OBEX_SRMP_WAIT          = 0x01; // Only SRMP value used by BT
138238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
1399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
1409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Updates the HeaderSet with the headers received in the byte array
14105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * provided. Invalid headers are ignored.
1429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * <P>
14305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * The first two bits of an OBEX Header specifies the type of object that is
14405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * being sent. The table below specifies the meaning of the high bits.
1459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * <TABLE>
14605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TR>
14705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TH>Bits 8 and 7</TH>
14805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TH>Value</TH>
14905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TH>Description</TH>
15005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * </TR>
15105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TR>
15205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TD>00</TD>
15305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TD>0x00</TD>
15405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TD>Null Terminated Unicode text, prefixed with 2 byte unsigned integer</TD>
15505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * </TR>
15605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TR>
15705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TD>01</TD>
15805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TD>0x40</TD>
15905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TD>Byte Sequence, length prefixed with 2 byte unsigned integer</TD>
16005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * </TR>
16105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TR>
16205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TD>10</TD>
16305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TD>0x80</TD>
16405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TD>1 byte quantity</TD>
16505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * </TR>
16605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TR>
16705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TD>11</TD>
16805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TD>0xC0</TD>
16905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * <TD>4 byte quantity - transmitted in network byte order (high byte first</TD>
17005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * </TR>
1719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * </TABLE>
1729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * This method uses the information in this table to determine the type of
17305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Java object to create and passes that object with the full header to
17405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * setHeader() to update the HeaderSet object. Invalid headers will cause an
17505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * exception to be thrown. When it is thrown, it is ignored.
1769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param header the HeaderSet to update
1779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param headerArray the byte array containing headers
1789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the result of the last start body or end body header provided;
17905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         the first byte in the result will specify if a body or end of
18005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         body is received
1812e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if an invalid header was found
1829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
1839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public static byte[] updateHeaderSet(HeaderSet header, byte[] headerArray) throws IOException {
1849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int index = 0;
1859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int length = 0;
1869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int headerID;
1879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] value = null;
1889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] body = null;
1899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        HeaderSet headerImpl = header;
1909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        try {
1919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            while (index < headerArray.length) {
1929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                headerID = 0xFF & headerArray[index];
1939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                switch (headerID & (0xC0)) {
1949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    /*
1969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                     * 0x00 is a unicode null terminate string with the first
1979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                     * two bytes after the header identifier being the length
1989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                     */
1999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    case 0x00:
2009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        // Fall through
2019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        /*
2029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                         * 0x40 is a byte sequence with the first
2039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                         * two bytes after the header identifier being the length
2049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                         */
2059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    case 0x40:
2069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        boolean trimTail = true;
2079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        index++;
2089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        length = 0xFF & headerArray[index];
2099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        length = length << 8;
2109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        index++;
2119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        length += 0xFF & headerArray[index];
2129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        length -= 3;
2139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        index++;
2149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        value = new byte[length];
2159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        System.arraycopy(headerArray, index, value, 0, length);
2169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        if (length == 0 || (length > 0 && (value[length - 1] != 0))) {
2179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                            trimTail = false;
2189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        }
2199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        switch (headerID) {
2209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                            case HeaderSet.TYPE:
2219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                try {
2229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    // Remove trailing null
2239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    if (trimTail == false) {
2249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                        headerImpl.setHeader(headerID, new String(value, 0,
2259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                                value.length, "ISO8859_1"));
2269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    } else {
2279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                        headerImpl.setHeader(headerID, new String(value, 0,
2289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                                value.length - 1, "ISO8859_1"));
2299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    }
2309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                } catch (UnsupportedEncodingException e) {
2313998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                    throw e;
2329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                }
2339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                break;
2349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2353998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                            case HeaderSet.AUTH_CHALLENGE:
2363998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                headerImpl.mAuthChall = new byte[length];
2373998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                System.arraycopy(headerArray, index, headerImpl.mAuthChall, 0,
2389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                        length);
2399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                break;
2409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2413998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                            case HeaderSet.AUTH_RESPONSE:
2423998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                headerImpl.mAuthResp = new byte[length];
2433998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                System.arraycopy(headerArray, index, headerImpl.mAuthResp, 0,
2443998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                        length);
2459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                break;
2469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2473998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                            case HeaderSet.BODY:
2489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                /* Fall Through */
2493998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                            case HeaderSet.END_OF_BODY:
2509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                body = new byte[length + 1];
2519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                body[0] = (byte)headerID;
2529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                System.arraycopy(headerArray, index, body, 1, length);
2539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                break;
2549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                            case HeaderSet.TIME_ISO_8601:
2569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                try {
2579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    String dateString = new String(value, "ISO8859_1");
2589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    Calendar temp = Calendar.getInstance();
2599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    if ((dateString.length() == 16)
2609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                            && (dateString.charAt(15) == 'Z')) {
2619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                        temp.setTimeZone(TimeZone.getTimeZone("UTC"));
2629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    }
2639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    temp.set(Calendar.YEAR, Integer.parseInt(dateString.substring(
2649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                            0, 4)));
2659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    temp.set(Calendar.MONTH, Integer.parseInt(dateString.substring(
2669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                            4, 6)));
2679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    temp.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateString
2689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                            .substring(6, 8)));
2699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    temp.set(Calendar.HOUR_OF_DAY, Integer.parseInt(dateString
2709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                            .substring(9, 11)));
2719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    temp.set(Calendar.MINUTE, Integer.parseInt(dateString
2729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                            .substring(11, 13)));
2739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    temp.set(Calendar.SECOND, Integer.parseInt(dateString
2749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                            .substring(13, 15)));
2759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    headerImpl.setHeader(HeaderSet.TIME_ISO_8601, temp);
2769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                } catch (UnsupportedEncodingException e) {
2773998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                    throw e;
2789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                }
2799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                break;
2809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                            default:
2823998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                if ((headerID & 0xC0) == 0x00) {
2833998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                    headerImpl.setHeader(headerID, ObexHelper.convertToUnicode(
2843998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                            value, true));
2853998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                } else {
2863998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                    headerImpl.setHeader(headerID, value);
2879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                }
2889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        }
2899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        index += length;
2919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        break;
2929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
2939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    /*
2949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                     * 0x80 is a byte header.  The only valid byte headers are
2959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                     * the 16 user defined byte headers.
2969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                     */
2979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    case 0x80:
2989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        index++;
2999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        try {
3009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                            headerImpl.setHeader(headerID, Byte.valueOf(headerArray[index]));
3019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        } catch (Exception e) {
3029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                            // Not a valid header so ignore
3039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        }
3049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        index++;
3059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        break;
3069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    /*
3089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                     * 0xC0 is a 4 byte unsigned integer header and with the
3099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                     * exception of TIME_4_BYTE will be converted to a Long
3109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                     * and added.
3119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                     */
3129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    case 0xC0:
3139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        index++;
3149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        value = new byte[4];
3159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        System.arraycopy(headerArray, index, value, 0, 4);
3169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        try {
3179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                            if (headerID != HeaderSet.TIME_4_BYTE) {
3189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                // Determine if it is a connection ID.  These
3199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                // need to be handled differently
3203998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                if (headerID == HeaderSet.CONNECTION_ID) {
3213998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                    headerImpl.mConnectionID = new byte[4];
3223998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                                    System.arraycopy(value, 0, headerImpl.mConnectionID, 0, 4);
3239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                } else {
3249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                    headerImpl.setHeader(headerID, Long
3259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                            .valueOf(convertToLong(value)));
3269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                }
3279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                            } else {
3289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                Calendar temp = Calendar.getInstance();
3299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                temp.setTime(new Date(convertToLong(value) * 1000L));
3309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                                headerImpl.setHeader(HeaderSet.TIME_4_BYTE, temp);
3319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                            }
3329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        } catch (Exception e) {
3339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                            // Not a valid header so ignore
334238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                            throw new IOException("Header was not formatted properly", e);
3359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        }
3369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        index += 4;
3379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        break;
3389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
3399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
3419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } catch (IOException e) {
342238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            throw new IOException("Header was not formatted properly", e);
3439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
3449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return body;
3469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
3479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
3499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Creates the header part of OBEX packet based on the header provided.
35005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * TODO: Could use getHeaderList() to get the array of headers to include
35105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * and then use the high two bits to determine the the type of the object
35205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * and construct the byte array from that. This will make the size smaller.
3539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param head the header used to construct the byte array
3549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param nullOut <code>true</code> if the header should be set to
35505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        <code>null</code> once it is added to the array or
35605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        <code>false</code> if it should not be nulled out
3579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the header of an OBEX packet
3589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
3599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public static byte[] createHeader(HeaderSet head, boolean nullOut) {
3609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        Long intHeader = null;
3619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        String stringHeader = null;
3629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        Calendar dateHeader = null;
3639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        Byte byteHeader = null;
3649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        StringBuffer buffer = null;
3659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] value = null;
3669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] result = null;
3679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] lengthArray = new byte[2];
3689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int length;
3699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        HeaderSet headImpl = null;
3709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ByteArrayOutputStream out = new ByteArrayOutputStream();
3719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        headImpl = head;
3729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        try {
3749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            /*
3759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * Determine if there is a connection ID to send.  If there is,
3769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * then it should be the first header in the packet.
3779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             */
3783998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if ((headImpl.mConnectionID != null) && (headImpl.getHeader(HeaderSet.TARGET) == null)) {
3799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3803998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                out.write((byte)HeaderSet.CONNECTION_ID);
3813998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                out.write(headImpl.mConnectionID);
3829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
3839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Count Header
3859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            intHeader = (Long)headImpl.getHeader(HeaderSet.COUNT);
3869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (intHeader != null) {
3879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write((byte)HeaderSet.COUNT);
3882e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly                value = ObexHelper.convertToByteArray(intHeader.longValue());
3899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(value);
3909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
3919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    headImpl.setHeader(HeaderSet.COUNT, null);
3929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
3939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
3949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
3959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Name Header
3969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            stringHeader = (String)headImpl.getHeader(HeaderSet.NAME);
3979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (stringHeader != null) {
3989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write((byte)HeaderSet.NAME);
3992e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly                value = ObexHelper.convertToUnicodeByteArray(stringHeader);
4009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                length = value.length + 3;
4013998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                lengthArray[0] = (byte)(0xFF & (length >> 8));
4023998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                lengthArray[1] = (byte)(0xFF & length);
4039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(lengthArray);
4049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(value);
4059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
4069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    headImpl.setHeader(HeaderSet.NAME, null);
4079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4088949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta            } else if (headImpl.getEmptyNameHeader()) {
4098949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                out.write((byte) HeaderSet.NAME);
4108949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                lengthArray[0] = (byte) 0x00;
4118949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                lengthArray[1] = (byte) 0x03;
4128949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta                out.write(lengthArray);
4139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
4149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Type Header
4169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            stringHeader = (String)headImpl.getHeader(HeaderSet.TYPE);
4179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (stringHeader != null) {
4189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write((byte)HeaderSet.TYPE);
4199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                try {
4209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    value = stringHeader.getBytes("ISO8859_1");
4219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                } catch (UnsupportedEncodingException e) {
4223998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    throw e;
4239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                length = value.length + 4;
4269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[0] = (byte)(255 & (length >> 8));
4279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[1] = (byte)(255 & length);
4289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(lengthArray);
4299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(value);
4309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(0x00);
4319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
4329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    headImpl.setHeader(HeaderSet.TYPE, null);
4339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
4359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Length Header
4379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            intHeader = (Long)headImpl.getHeader(HeaderSet.LENGTH);
4389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (intHeader != null) {
4399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write((byte)HeaderSet.LENGTH);
4402e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly                value = ObexHelper.convertToByteArray(intHeader.longValue());
4419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(value);
4429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
4439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    headImpl.setHeader(HeaderSet.LENGTH, null);
4449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
4469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Time ISO Header
4489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            dateHeader = (Calendar)headImpl.getHeader(HeaderSet.TIME_ISO_8601);
4499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (dateHeader != null) {
4509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                /*
4529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * The ISO Header should take the form YYYYMMDDTHHMMSSZ.  The
4539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * 'Z' will only be included if it is a UTC time.
4549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 */
4559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                buffer = new StringBuffer();
4569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                int temp = dateHeader.get(Calendar.YEAR);
4579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                for (int i = temp; i < 1000; i = i * 10) {
4589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    buffer.append("0");
4599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                buffer.append(temp);
4619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                temp = dateHeader.get(Calendar.MONTH);
4629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (temp < 10) {
4639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    buffer.append("0");
4649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                buffer.append(temp);
4669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                temp = dateHeader.get(Calendar.DAY_OF_MONTH);
4679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (temp < 10) {
4689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    buffer.append("0");
4699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                buffer.append(temp);
4719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                buffer.append("T");
4729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                temp = dateHeader.get(Calendar.HOUR_OF_DAY);
4739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (temp < 10) {
4749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    buffer.append("0");
4759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                buffer.append(temp);
4779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                temp = dateHeader.get(Calendar.MINUTE);
4789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (temp < 10) {
4799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    buffer.append("0");
4809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                buffer.append(temp);
4829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                temp = dateHeader.get(Calendar.SECOND);
4839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (temp < 10) {
4849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    buffer.append("0");
4859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                buffer.append(temp);
4879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (dateHeader.getTimeZone().getID().equals("UTC")) {
4899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    buffer.append("Z");
4909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                try {
4939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    value = buffer.toString().getBytes("ISO8859_1");
4949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                } catch (UnsupportedEncodingException e) {
4953998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    throw e;
4969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
4979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
4989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                length = value.length + 3;
4999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[0] = (byte)(255 & (length >> 8));
5009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[1] = (byte)(255 & length);
5019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(HeaderSet.TIME_ISO_8601);
5029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(lengthArray);
5039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(value);
5049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
5059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    headImpl.setHeader(HeaderSet.TIME_ISO_8601, null);
5069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
5079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Time 4 Byte Header
5109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            dateHeader = (Calendar)headImpl.getHeader(HeaderSet.TIME_4_BYTE);
5119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (dateHeader != null) {
5129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(HeaderSet.TIME_4_BYTE);
5139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                /*
5159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * Need to call getTime() twice.  The first call will return
5169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * a java.util.Date object.  The second call returns the number
5179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * of milliseconds since January 1, 1970.  We need to convert
5189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * it to seconds since the TIME_4_BYTE expects the number of
5199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 * seconds since January 1, 1970.
5209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                 */
5212e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly                value = ObexHelper.convertToByteArray(dateHeader.getTime().getTime() / 1000L);
5229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(value);
5239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
5249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    headImpl.setHeader(HeaderSet.TIME_4_BYTE, null);
5259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
5269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Description Header
5299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            stringHeader = (String)headImpl.getHeader(HeaderSet.DESCRIPTION);
5309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (stringHeader != null) {
5319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write((byte)HeaderSet.DESCRIPTION);
5322e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly                value = ObexHelper.convertToUnicodeByteArray(stringHeader);
5339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                length = value.length + 3;
5349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[0] = (byte)(255 & (length >> 8));
5359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[1] = (byte)(255 & length);
5369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(lengthArray);
5379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(value);
5389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
5399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    headImpl.setHeader(HeaderSet.DESCRIPTION, null);
5409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
5419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Target Header
5449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            value = (byte[])headImpl.getHeader(HeaderSet.TARGET);
5459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (value != null) {
5469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write((byte)HeaderSet.TARGET);
5479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                length = value.length + 3;
5489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[0] = (byte)(255 & (length >> 8));
5499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[1] = (byte)(255 & length);
5509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(lengthArray);
5519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(value);
5529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
5539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    headImpl.setHeader(HeaderSet.TARGET, null);
5549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
5559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // HTTP Header
5589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            value = (byte[])headImpl.getHeader(HeaderSet.HTTP);
5599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (value != null) {
5609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write((byte)HeaderSet.HTTP);
5619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                length = value.length + 3;
5629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[0] = (byte)(255 & (length >> 8));
5639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[1] = (byte)(255 & length);
5649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(lengthArray);
5659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(value);
5669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
5679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    headImpl.setHeader(HeaderSet.HTTP, null);
5689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
5699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Who Header
5729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            value = (byte[])headImpl.getHeader(HeaderSet.WHO);
5739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (value != null) {
5749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write((byte)HeaderSet.WHO);
5759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                length = value.length + 3;
5769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[0] = (byte)(255 & (length >> 8));
5779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[1] = (byte)(255 & length);
5789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(lengthArray);
5799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(value);
5809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
5819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    headImpl.setHeader(HeaderSet.WHO, null);
5829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
5839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Connection ID Header
5869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            value = (byte[])headImpl.getHeader(HeaderSet.APPLICATION_PARAMETER);
5879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (value != null) {
5889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write((byte)HeaderSet.APPLICATION_PARAMETER);
5899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                length = value.length + 3;
5909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[0] = (byte)(255 & (length >> 8));
5919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[1] = (byte)(255 & length);
5929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(lengthArray);
5939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(value);
5949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
5959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    headImpl.setHeader(HeaderSet.APPLICATION_PARAMETER, null);
5969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
5979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
5989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
5999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Object Class Header
6009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            value = (byte[])headImpl.getHeader(HeaderSet.OBJECT_CLASS);
6019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (value != null) {
6029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write((byte)HeaderSet.OBJECT_CLASS);
6039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                length = value.length + 3;
6049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[0] = (byte)(255 & (length >> 8));
6059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[1] = (byte)(255 & length);
6069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(lengthArray);
6079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(value);
6089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
6099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    headImpl.setHeader(HeaderSet.OBJECT_CLASS, null);
6109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
6129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Check User Defined Headers
6149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            for (int i = 0; i < 16; i++) {
6159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                //Unicode String Header
6179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                stringHeader = (String)headImpl.getHeader(i + 0x30);
6189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (stringHeader != null) {
6199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    out.write((byte)i + 0x30);
6202e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly                    value = ObexHelper.convertToUnicodeByteArray(stringHeader);
6219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    length = value.length + 3;
6229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    lengthArray[0] = (byte)(255 & (length >> 8));
6239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    lengthArray[1] = (byte)(255 & length);
6249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    out.write(lengthArray);
6259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    out.write(value);
6269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    if (nullOut) {
6279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        headImpl.setHeader(i + 0x30, null);
6289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
6299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // Byte Sequence Header
6329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                value = (byte[])headImpl.getHeader(i + 0x70);
6339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (value != null) {
6349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    out.write((byte)i + 0x70);
6359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    length = value.length + 3;
6369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    lengthArray[0] = (byte)(255 & (length >> 8));
6379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    lengthArray[1] = (byte)(255 & length);
6389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    out.write(lengthArray);
6399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    out.write(value);
6409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    if (nullOut) {
6419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        headImpl.setHeader(i + 0x70, null);
6429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
6439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // Byte Header
6469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                byteHeader = (Byte)headImpl.getHeader(i + 0xB0);
6479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (byteHeader != null) {
6489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    out.write((byte)i + 0xB0);
6499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    out.write(byteHeader.byteValue());
6509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    if (nullOut) {
6519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        headImpl.setHeader(i + 0xB0, null);
6529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
6539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                // Integer header
6569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                intHeader = (Long)headImpl.getHeader(i + 0xF0);
6579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (intHeader != null) {
6589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    out.write((byte)i + 0xF0);
6592e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly                    out.write(ObexHelper.convertToByteArray(intHeader.longValue()));
6609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    if (nullOut) {
6619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                        headImpl.setHeader(i + 0xF0, null);
6629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    }
6639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
6659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Add the authentication challenge header
6673998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (headImpl.mAuthChall != null) {
6683998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                out.write((byte)HeaderSet.AUTH_CHALLENGE);
6693998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                length = headImpl.mAuthChall.length + 3;
6709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[0] = (byte)(255 & (length >> 8));
6719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[1] = (byte)(255 & length);
6729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(lengthArray);
6733998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                out.write(headImpl.mAuthChall);
6749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
6753998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    headImpl.mAuthChall = null;
6769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
6789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
6799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            // Add the authentication response header
6803998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun            if (headImpl.mAuthResp != null) {
6813998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                out.write((byte)HeaderSet.AUTH_RESPONSE);
6823998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                length = headImpl.mAuthResp.length + 3;
6839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[0] = (byte)(255 & (length >> 8));
6849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lengthArray[1] = (byte)(255 & length);
6859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.write(lengthArray);
6863998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                out.write(headImpl.mAuthResp);
6879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                if (nullOut) {
6883998bf009acaf8cde4d7f837f8b8e41ae0a65141Tao Liejun                    headImpl.mAuthResp = null;
6899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                }
6909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
6919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
692238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // TODO:
693238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // If the SRM and SRMP header is in use, they must be send in the same OBEX packet
694238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // But the current structure of the obex code cannot handle this, and therefore
695238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // it makes sense to put them in the tail of the headers, since we then reduce the
696238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // chance of enabling SRM to soon. The down side is that SRM cannot be used while
697238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // transferring non-body headers
698238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
699238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // Add the SRM header
700238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            byteHeader = (Byte)headImpl.getHeader(HeaderSet.SINGLE_RESPONSE_MODE);
701238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if (byteHeader != null) {
702238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                out.write((byte)HeaderSet.SINGLE_RESPONSE_MODE);
703238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                out.write(byteHeader.byteValue());
704238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                if (nullOut) {
705238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    headImpl.setHeader(HeaderSet.SINGLE_RESPONSE_MODE, null);
706238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                }
707238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            }
708238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
709238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            // Add the SRM parameter header
710238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            byteHeader = (Byte)headImpl.getHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER);
711238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if (byteHeader != null) {
712238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                out.write((byte)HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER);
713238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                out.write(byteHeader.byteValue());
714238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                if (nullOut) {
715238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                    headImpl.setHeader(HeaderSet.SINGLE_RESPONSE_MODE_PARAMETER, null);
716238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                }
717238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            }
718238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
7199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } catch (IOException e) {
7209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } finally {
7219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            result = out.toByteArray();
7229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            try {
7239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                out.close();
7249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } catch (Exception ex) {
7259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
7269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
7279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return result;
7299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
7319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
73305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Determines where the maximum divide is between headers. This method is
7349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * used by put and get operations to separate headers to a size that meets
7359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * the max packet size allowed.
7369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param headerArray the headers to separate
7379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param start the starting index to search
7389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param maxSize the maximum size of a packet
7399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the index of the end of the header block to send or -1 if the
74005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         header could not be divided because the header is too large
7419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
7429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public static int findHeaderEnd(byte[] headerArray, int start, int maxSize) {
7439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int fullLength = 0;
7459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int lastLength = -1;
7469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int index = start;
7479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int length = 0;
7489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
749238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        // TODO: Ensure SRM and SRMP headers are not split into two OBEX packets
750238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
7519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        while ((fullLength < maxSize) && (index < headerArray.length)) {
7529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            int headerID = (headerArray[index] < 0 ? headerArray[index] + 256 : headerArray[index]);
7539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            lastLength = fullLength;
7549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            switch (headerID & (0xC0)) {
7569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                case 0x00:
7589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    // Fall through
7599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                case 0x40:
7609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    index++;
7629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    length = (headerArray[index] < 0 ? headerArray[index] + 256
7639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                            : headerArray[index]);
7649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    length = length << 8;
7659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    index++;
7669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    length += (headerArray[index] < 0 ? headerArray[index] + 256
7679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                            : headerArray[index]);
7689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    length -= 3;
7699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    index++;
7709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    index += length;
7719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    fullLength += length + 3;
7729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    break;
7739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                case 0x80:
7759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    index++;
7779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    index++;
7789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    fullLength += 2;
7799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    break;
7809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                case 0xC0:
7829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    index += 5;
7849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    fullLength += 5;
7859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                    break;
7869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
7889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
7909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
7919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
7929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * Determine if this is the last header or not
7939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         */
7949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (lastLength == 0) {
7959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            /*
7969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * Since this is the last header, check to see if the size of this
7979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * header is less then maxSize.  If it is, return the length of the
7989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * header, otherwise return -1.  The length of the header is
7999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             * returned since it would be the start of the next header
8009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly             */
8019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (fullLength < maxSize) {
8029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return headerArray.length;
8039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            } else {
8049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                return -1;
8059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
8069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
8079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return lastLength + start;
8089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
8099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
8109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
8129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Converts the byte array to a long.
8139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param b the byte array to convert to a long
8149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the byte array as a long
8159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
8169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public static long convertToLong(byte[] b) {
8179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        long result = 0;
8189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        long value = 0;
8199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        long power = 0;
8209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        for (int i = (b.length - 1); i >= 0; i--) {
8229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            value = b[i];
8239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (value < 0) {
8249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                value += 256;
8259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
8269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            result = result | (value << power);
8289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            power += 8;
8299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
8309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return result;
8329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
8339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
83505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Converts the long to a 4 byte array. The long must be non negative.
8369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param l the long to convert
8379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return a byte array that is the same as the long
8389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
8399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public static byte[] convertToByteArray(long l) {
8409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] b = new byte[4];
8419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        b[0] = (byte)(255 & (l >> 24));
8439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        b[1] = (byte)(255 & (l >> 16));
8449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        b[2] = (byte)(255 & (l >> 8));
8459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        b[3] = (byte)(255 & l);
8469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return b;
8489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
8499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
85105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Converts the String to a UNICODE byte array. It will also add the ending
8529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * null characters to the end of the string.
8539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param s the string to convert
8549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the unicode byte array of the string
8559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
8569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public static byte[] convertToUnicodeByteArray(String s) {
8579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (s == null) {
8589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return null;
8599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
8609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        char c[] = s.toCharArray();
8629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] result = new byte[(c.length * 2) + 2];
8639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        for (int i = 0; i < c.length; i++) {
8649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            result[(i * 2)] = (byte)(c[i] >> 8);
8659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            result[((i * 2) + 1)] = (byte)c[i];
8669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
8679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // Add the UNICODE null character
8699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        result[result.length - 2] = 0;
8709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        result[result.length - 1] = 0;
8719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8729439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return result;
8739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
8749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
87605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Retrieves the value from the byte array for the tag value specified. The
8779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * array should be of the form Tag - Length - Value triplet.
8789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param tag the tag to retrieve from the byte array
8799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param triplet the byte sequence containing the tag length value form
8809439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the value of the specified tag
8819439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
8829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public static byte[] getTagValue(byte tag, byte[] triplet) {
8839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int index = findTag(tag, triplet);
8859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (index == -1) {
8869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return null;
8879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
8889439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        index++;
8909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int length = triplet[index] & 0xFF;
8919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] result = new byte[length];
8939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        index++;
8949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        System.arraycopy(triplet, index, result, 0, length);
8959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return result;
8979439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
8989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
8999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
9009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Finds the index that starts the tag value pair in the byte array provide.
9019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param tag the tag to look for
9029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param value the byte array to search
9039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the starting index of the tag or -1 if the tag could not be found
9049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
9059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public static int findTag(byte tag, byte[] value) {
9069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int length = 0;
9079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
9089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (value == null) {
9099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return -1;
9109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
9119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
9129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int index = 0;
9139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
9149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        while ((index < value.length) && (value[index] != tag)) {
9159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            length = value[index + 1] & 0xFF;
9169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            index += length + 2;
9179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
9189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
9199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (index >= value.length) {
9209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return -1;
9219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
9229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
9239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return index;
9249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
9259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
9269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
9279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Converts the byte array provided to a unicode string.
9289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param b the byte array to convert to a string
9299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param includesNull determine if the byte string provided contains the
93005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        UNICODE null character at the end or not; if it does, it will be
93105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        removed
9329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return a Unicode string
93305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @throws IllegalArgumentException if the byte array has an odd length
9349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
9359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public static String convertToUnicode(byte[] b, boolean includesNull) {
9368d95d0a13a278c4bd4dbffb682acf1e457dfb94bTao Liejun        if (b == null || b.length == 0) {
9379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return null;
9389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
9399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int arrayLength = b.length;
9409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (!((arrayLength % 2) == 0)) {
9419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IllegalArgumentException("Byte array not of a valid form");
9429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
9439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        arrayLength = (arrayLength >> 1);
9449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (includesNull) {
9459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            arrayLength -= 1;
9469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
9479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
9489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        char[] c = new char[arrayLength];
9499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        for (int i = 0; i < arrayLength; i++) {
9509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            int upper = b[2 * i];
9519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            int lower = b[(2 * i) + 1];
9529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (upper < 0) {
9539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                upper += 256;
9549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
9559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (lower < 0) {
9569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                lower += 256;
9579439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
9580b309d6ee433d55b7499d7bbd447494366ef1316Jackson Fan            // If upper and lower both equal 0, it should be the end of string.
9590b309d6ee433d55b7499d7bbd447494366ef1316Jackson Fan            // Ignore left bytes from array to avoid potential issues
9600b309d6ee433d55b7499d7bbd447494366ef1316Jackson Fan            if (upper == 0 && lower == 0) {
9610b309d6ee433d55b7499d7bbd447494366ef1316Jackson Fan                return new String(c, 0, i);
9620b309d6ee433d55b7499d7bbd447494366ef1316Jackson Fan            }
9639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
9649439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            c[i] = (char)((upper << 8) | lower);
9659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
9669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
9679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return new String(c);
9689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
9699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
9709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
97105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * Compute the MD5 hash of the byte array provided. Does not accumulate
97205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * input.
9739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param in the byte array to hash
9749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @return the MD5 hash of the byte array
9759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
9762e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly    public static byte[] computeMd5Hash(byte[] in) {
977929a1c219248b62778807cac8ea256c7ac0fda6aBrian Carlstrom        try {
978929a1c219248b62778807cac8ea256c7ac0fda6aBrian Carlstrom            MessageDigest md5 = MessageDigest.getInstance("MD5");
979929a1c219248b62778807cac8ea256c7ac0fda6aBrian Carlstrom            return md5.digest(in);
980929a1c219248b62778807cac8ea256c7ac0fda6aBrian Carlstrom        } catch (NoSuchAlgorithmException e) {
981929a1c219248b62778807cac8ea256c7ac0fda6aBrian Carlstrom            throw new RuntimeException(e);
982929a1c219248b62778807cac8ea256c7ac0fda6aBrian Carlstrom        }
9839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
9849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
9859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    /**
9869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * Computes an authentication challenge header.
98705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @param nonce the challenge that will be provided to the peer; the
98805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        challenge must be 16 bytes long
9899439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param realm a short description that describes what password to use
9909439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param access if <code>true</code> then full access will be granted if
99105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        successful; if <code>false</code> then read only access will be
99205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        granted if successful
9939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     * @param userID if <code>true</code>, a user ID is required in the reply;
99405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *        if <code>false</code>, no user ID is required
99505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     * @throws IllegalArgumentException if the challenge is not 16 bytes long;
99605ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun     *         if the realm can not be encoded in less then 255 bytes
9972e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly     * @throws IOException if the encoding scheme ISO 8859-1 is not supported
9989439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly     */
9999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public static byte[] computeAuthenticationChallenge(byte[] nonce, String realm, boolean access,
10009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            boolean userID) throws IOException {
10019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] authChall = null;
10029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
10039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (nonce.length != 16) {
10049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new IllegalArgumentException("Nonce must be 16 bytes long");
10059439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
10069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
10079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        /*
10089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * The authentication challenge is a byte sequence of the following form
10099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * byte 0: 0x00 - the tag for the challenge
10109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * byte 1: 0x10 - the length of the challenge; must be 16
10119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * byte 2-17: the authentication challenge
10129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * byte 18: 0x01 - the options tag; this is optional in the spec, but
10139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         *                 we are going to include it in every message
10149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * byte 19: 0x01 - length of the options; must be 1
10159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * byte 20: the value of the options; bit 0 is set if user ID is
10169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         *          required; bit 1 is set if access mode is read only
10179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * byte 21: 0x02 - the tag for authentication realm; only included if
10189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         *                 an authentication realm is specified
10199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * byte 22: the length of the authentication realm; only included if
10209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         *          the authentication realm is specified
10219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * byte 23: the encoding scheme of the authentication realm; we will use
10229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         *          the ISO 8859-1 encoding scheme since it is part of the KVM
10239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         * byte 24 & up: the realm if one is specified.
10249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly         */
10259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (realm == null) {
10269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            authChall = new byte[21];
10279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } else {
10289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            if (realm.length() >= 255) {
10299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                throw new IllegalArgumentException("Realm must be less then 255 bytes");
10309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            }
10319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            authChall = new byte[24 + realm.length()];
10329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            authChall[21] = 0x02;
10339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            authChall[22] = (byte)(realm.length() + 1);
10349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            authChall[23] = 0x01; // ISO 8859-1 Encoding
10359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            System.arraycopy(realm.getBytes("ISO8859_1"), 0, authChall, 24, realm.length());
10369439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
10379439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
10389439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // Include the nonce field in the header
10399439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        authChall[0] = 0x00;
10409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        authChall[1] = 0x10;
10419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        System.arraycopy(nonce, 0, authChall, 2, 16);
10429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
10439439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        // Include the options header
10449439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        authChall[18] = 0x01;
10459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        authChall[19] = 0x01;
10469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        authChall[20] = 0x00;
10479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
10489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (!access) {
10499439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            authChall[20] = (byte)(authChall[20] | 0x02);
10509439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
10519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (userID) {
10529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            authChall[20] = (byte)(authChall[20] | 0x01);
10539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
10549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
10559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return authChall;
10569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
1057238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
1058238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    /**
1059238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * Return the maximum allowed OBEX packet to transmit.
1060238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * OBEX packets transmitted must be smaller than this value.
1061238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * @param transport Reference to the ObexTransport in use.
1062238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * @return the maximum allowed OBEX packet to transmit
1063238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     */
1064238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public static int getMaxTxPacketSize(ObexTransport transport) {
1065238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        int size = transport.getMaxTransmitPacketSize();
1066238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        return validateMaxPacketSize(size);
1067238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    }
1068238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
1069238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    /**
1070238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * Return the maximum allowed OBEX packet to receive - used in OBEX connect.
1071238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * @param transport
1072238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     * @return he maximum allowed OBEX packet to receive
1073238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde     */
1074238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    public static int getMaxRxPacketSize(ObexTransport transport) {
1075238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        int size = transport.getMaxReceivePacketSize();
1076238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        return validateMaxPacketSize(size);
1077238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    }
1078238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
1079238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    private static int validateMaxPacketSize(int size) {
1080238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if(VDBG && (size > MAX_PACKET_SIZE_INT)) Log.w(TAG,
1081238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                "The packet size supported for the connection (" + size + ") is larger"
1082238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                + " than the configured OBEX packet size: " + MAX_PACKET_SIZE_INT);
1083238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        if(size != -1) {
1084238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            if(size < LOWER_LIMIT_MAX_PACKET_SIZE) {
1085238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                throw new IllegalArgumentException(size + " is less that the lower limit: "
1086238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde                        + LOWER_LIMIT_MAX_PACKET_SIZE);
1087238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            }
1088238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde            return size;
1089238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        }
1090238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde        return MAX_PACKET_SIZE_INT;
1091238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde    }
10929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly}
1093