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