]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSShared/Java/TXTRecord.java
mDNSResponder-66.3.tar.gz
[apple/mdnsresponder.git] / mDNSShared / Java / TXTRecord.java
1 /*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24
25 Change History (most recent first):
26
27 $Log: TXTRecord.java,v $
28 Revision 1.2 2004/04/30 21:48:27 rpantos
29 Change line endings for CVS.
30
31 Revision 1.1 2004/04/30 16:29:35 rpantos
32 First checked in.
33
34 To do:
35 - implement remove()
36 - fix set() to replace existing values
37 */
38
39
40 package com.apple.dnssd;
41
42
43 /**
44 Object used to construct and parse DNS-SD format TXT records.
45 For more info see <a href="http://www.zeroconf.org/Rendezvous/txtrecords.html">DNS-SD TXT record format</a>.
46 */
47
48 public class TXTRecord
49 {
50 /*
51 DNS-SD specifies that a TXT record corresponding to an SRV record consist of
52 a packed array of bytes, each preceded by a length byte. Each string
53 is an attribute-value pair.
54
55 The TXTRecord object stores the entire TXT data as a single byte array, traversing it
56 as need be to implement its various methods.
57 */
58
59 static final protected byte kAttrSep = '=';
60
61 protected byte[] fBytes;
62
63 /** Constructs a new, empty TXT record. */
64 public TXTRecord()
65 { fBytes = new byte[0]; }
66
67 /** Constructs a new TXT record from a byte array in the standard format. */
68 public TXTRecord( byte[] initBytes)
69 { fBytes = (byte[]) initBytes.clone(); }
70
71 /** Set a key/value pair in the TXT record. Setting an existing key will replace its value.<P>
72 @param key
73 The key name. Must be ASCII, with no '=' characters.
74 <P>
75 @param value
76 Value to be encoded into bytes using the default platform character set.
77 */
78 public void set( String key, String value)
79 {
80 byte[] valBytes = (value != null) ? value.getBytes() : null;
81 this.set( key, valBytes);
82 }
83
84 /** Set a key/value pair in the TXT record. Setting an existing key will replace its value.<P>
85 @param key
86 The key name. Must be ASCII, with no '=' characters.
87 <P>
88 @param value
89 Binary representation of the value.
90 */
91 public void set( String key, byte[] value)
92 {
93 byte[] oldBytes = fBytes;
94 byte[] keyBytes;
95 int valLen = (value != null) ? value.length : 0;
96 byte newLen;
97
98 try {
99 keyBytes = key.getBytes( "US-ASCII");
100 }
101 catch ( java.io.UnsupportedEncodingException uee) {
102 throw new IllegalArgumentException();
103 }
104
105 for ( int i=0; i < keyBytes.length; i++)
106 if ( keyBytes[i] == '=')
107 throw new IllegalArgumentException();
108
109 if ( keyBytes.length + valLen >= 255)
110 throw new ArrayIndexOutOfBoundsException();
111 newLen = (byte) ( keyBytes.length + valLen + (valLen > 0 ? 1 : 0));
112
113 fBytes = new byte[ oldBytes.length + newLen + 1];
114 System.arraycopy( oldBytes, 0, fBytes, 0, oldBytes.length);
115 fBytes[ oldBytes.length] = newLen;
116 System.arraycopy( keyBytes, 0, fBytes, oldBytes.length + 1, keyBytes.length);
117 if ( valLen > 0)
118 {
119 fBytes[ oldBytes.length + 1 + keyBytes.length] = kAttrSep;
120 System.arraycopy( value, 0, fBytes, oldBytes.length + keyBytes.length + 2, value.length);
121 }
122 }
123
124 /** Return the number of keys in the TXT record. */
125 public int size()
126 {
127 int i, avStart;
128
129 for ( i=0, avStart=0; avStart < fBytes.length; i++)
130 avStart += fBytes[ avStart] + 1;
131 return i;
132 }
133
134 /** Return true if key is present in the TXT record, false if not. */
135 public boolean contains( String key)
136 {
137 String s = null;
138
139 for ( int i=0; null != ( s = this.getKey( i)); i++)
140 if ( 0 == key.compareToIgnoreCase( s))
141 return true;
142 return false;
143 }
144
145 /** Return a key in the TXT record by zero-based index. Returns null if index exceeds the total number of keys. */
146 public String getKey( int index)
147 {
148 int avStart = 0;
149
150 for ( int i=0; i < index && avStart < fBytes.length; i++)
151 avStart += fBytes[ avStart] + 1;
152
153 if ( avStart < fBytes.length)
154 {
155 int avLen = fBytes[ avStart];
156 int aLen = 0;
157
158 for ( aLen=0; aLen < avLen; aLen++)
159 if ( fBytes[ avStart + aLen + 1] == kAttrSep)
160 break;
161 return new String( fBytes, avStart + 1, aLen);
162 }
163 return null;
164 }
165
166 /**
167 Look up a key in the TXT record by zero-based index and return its value. <P>
168 Returns null if index exceeds the total number of keys.
169 Returns null if the key is present with no value.
170 */
171 public byte[] getValue( int index)
172 {
173 int avStart = 0;
174 byte[] value = null;
175
176 for ( int i=0; i < index && avStart < fBytes.length; i++)
177 avStart += fBytes[ avStart] + 1;
178
179 if ( avStart < fBytes.length)
180 {
181 int avLen = fBytes[ avStart];
182 int aLen = 0;
183
184 for ( aLen=0; aLen < avLen; aLen++)
185 {
186 if ( fBytes[ avStart + aLen + 1] == kAttrSep)
187 {
188 value = new byte[ avLen - aLen - 1];
189 System.arraycopy( fBytes, avStart + aLen + 2, value, 0, avLen - aLen - 1);
190 }
191 }
192 }
193 return value;
194 }
195
196 /** Converts the result of getValue() to a string in the platform default character set. */
197 public String getValueAsString( int index)
198 {
199 byte[] value = this.getValue( index);
200 return value != null ? new String( value) : null;
201 }
202
203 /** Get the value associated with a key. Will be null if the key is not defined.
204 Array will have length 0 if the key is defined with an = but no value.<P>
205
206 @param forKey
207 The left-hand side of the key-value pair.
208 <P>
209 @return The binary representation of the value.
210 */
211 public byte[] getValue( String forKey)
212 {
213 String s = null;
214 int i;
215
216 for ( i=0; null != ( s = this.getKey( i)); i++)
217 if ( 0 == forKey.compareToIgnoreCase( s))
218 return this.getValue( i);
219 return null;
220 }
221
222 /** Converts the result of getValue() to a string in the platform default character set.<P>
223
224 @param forKey
225 The left-hand side of the key-value pair.
226 <P>
227 @return The value represented in the default platform character set.
228 */
229 public String getValueAsString( String forKey)
230 {
231 byte[] val = this.getValue( forKey);
232 return val != null ? new String( val) : null;
233 }
234
235 /** Return the contents of the TXT record as raw bytes. */
236 public byte[] getRawBytes() { return (byte[]) fBytes.clone(); }
237 }
238