1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* Conditions Of Use 3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* 4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* This software was developed by employees of the National Institute of 5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* Standards and Technology (NIST), an agency of the Federal Government. 6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* Pursuant to title 15 Untied States Code Section 105, works of NIST 7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* employees are not subject to copyright protection in the United States 8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* and are considered to be in the public domain. As a result, a formal 9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* license is not needed to use the software. 10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* 11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* This software is provided by NIST as a service and is expressly 12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED 13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF 14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT 15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* AND DATA ACCURACY. NIST does not warrant or make any representations 16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* regarding the use of the software or the results thereof, including but 17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* not limited to the correctness, accuracy, reliability or usefulness of 18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* the software. 19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* 20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* Permission to use this software is contingent upon your acceptance 21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* of the terms of this agreement 22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* 23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* . 24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang* 25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang*/ 26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/* 27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * IPv6 Support added by Emil Ivov (emil_ivov@yahoo.com)<br/> 29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Network Research Team (http://www-r2.u-strasbg.fr))<br/> 30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Louis Pasteur University - Strasbourg - France<br/> 31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *Bug fixes for corner cases were contributed by Thomas Froment. 33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.core; 35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 362fea0dd4d93ae38af69622213b7904d1c213a5ceChia-chi Yeh// BEGIN android-deleted 372fea0dd4d93ae38af69622213b7904d1c213a5ceChia-chi Yeh//import gov.nist.javax.sdp.parser.Lexer; 382fea0dd4d93ae38af69622213b7904d1c213a5ceChia-chi Yeh// END android-deleted 39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.text.ParseException; 41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/** 43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parser for host names. 44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *@version 1.2 46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *@author M. Ranganathan 48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic class HostNameParser extends ParserCore { 512fea0dd4d93ae38af69622213b7904d1c213a5ceChia-chi Yeh// BEGIN android-added 522fea0dd4d93ae38af69622213b7904d1c213a5ceChia-chi Yeh private static LexerCore Lexer; 532fea0dd4d93ae38af69622213b7904d1c213a5ceChia-chi Yeh// END android-added 54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Determines whether or not we should tolerate and strip address scope 57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * zones from IPv6 addresses. Address scope zones are sometimes returned 58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * at the end of IPv6 addresses generated by InetAddress.getHostAddress(). 59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * They are however not part of the SIP semantics so basically this method 60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * determines whether or not the parser should be stripping them (as 61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * opposed simply being blunt and throwing an exception). 62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private boolean stripAddressScopeZones = false; 64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public HostNameParser(String hname) { 66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.lexer = new LexerCore("charLexer", hname); 67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang stripAddressScopeZones 69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES"); 70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The lexer is initialized with the buffer. 74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public HostNameParser(LexerCore lexer) { 76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang this.lexer = lexer; 77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.selectLexer("charLexer"); 78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang stripAddressScopeZones 80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang = Boolean.getBoolean("gov.nist.core.STRIP_ADDR_SCOPES"); 81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private static final char[] VALID_DOMAIN_LABEL_CHAR = 84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang new char[] {LexerCore.ALPHADIGIT_VALID_CHARS, '-', '.'}; 85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected void consumeDomainLabel() throws ParseException { 86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (debug) 87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dbg_enter("domainLabel"); 88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.consumeValidChars(VALID_DOMAIN_LABEL_CHAR); 90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (debug) 92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dbg_leave("domainLabel"); 93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang protected String ipv6Reference() throws ParseException { 97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang StringBuffer retval = new StringBuffer(); 98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (debug) 99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dbg_enter("ipv6Reference"); 100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if(stripAddressScopeZones){ 104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (lexer.hasMoreChars()) { 105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang char la = lexer.lookAhead(0); 106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //'%' is ipv6 address scope zone. see detail at 107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //java.sun.com/j2se/1.5.0/docs/api/java/net/Inet6Address.html 108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (LexerCore.isHexDigit(la) || la == '.' || la == ':' 109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || la == '[' ) { 110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.consume(1); 111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(la); 112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (la == ']') { 113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.consume(1); 114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(la); 115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval.toString(); 116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (la == '%'){ 117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //we need to strip the address scope zone. 118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.consume(1); 119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String rest = lexer.getRest(); 121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if(rest == null || rest.length() == 0){ 123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //head for the parse exception 124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //we strip everything until either the end of the string 128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //or a closing square bracket (]) 129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int stripLen = rest.indexOf(']'); 130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (stripLen == -1){ 132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //no square bracket -> not a valid ipv6 reference 133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.consume(stripLen+1); 137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append("]"); 138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval.toString(); 139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else 141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang { 146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang while (lexer.hasMoreChars()) 147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang { 148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang char la = lexer.lookAhead(0); 149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (LexerCore.isHexDigit(la) || la == '.' 150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || la == ':' || la == '[') { 151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.consume(1); 152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(la); 153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else if (la == ']') { 154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.consume(1); 155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang retval.append(la); 156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return retval.toString(); 157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } else 158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException( 163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.getBuffer() + ": Illegal Host name ", 164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.getPtr()); 165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (debug) 167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dbg_leave("ipv6Reference"); 168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public Host host() throws ParseException { 172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (debug) 173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dbg_enter("host"); 174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String hostname; 176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //IPv6 referene 178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (lexer.lookAhead(0) == '[') { 179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hostname = ipv6Reference(); 180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //IPv6 address (i.e. missing square brackets) 182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else if( isIPv6Address(lexer.getRest()) ) 183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang { 184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int startPtr = lexer.getPtr(); 185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.consumeValidChars( 186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang new char[] {LexerCore.ALPHADIGIT_VALID_CHARS, ':'}); 187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hostname 188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang = new StringBuffer("[").append( 189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.getBuffer().substring(startPtr, lexer.getPtr())) 190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang .append("]").toString(); 191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //IPv4 address or hostname 193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else { 194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int startPtr = lexer.getPtr(); 195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang consumeDomainLabel(); 196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hostname = lexer.getBuffer().substring(startPtr, lexer.getPtr()); 197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (hostname.length() == 0) 200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException( 201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.getBuffer() + ": Missing host name", 202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.getPtr()); 203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang else 204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return new Host(hostname); 205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (debug) 207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dbg_leave("host"); 208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Tries to determine whether the address in <tt>uriHeader</tt> could be 213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * an IPv6 address by counting the number of colons that appear in it. 214600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 215600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param uriHeader the string (supposedly the value of a URI header) that 216600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * we have received for parsing. 217600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return true if the host part of <tt>uriHeader</tt> could be an IPv6 219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * address (i.e. contains at least two colons) and false otherwise. 220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang private boolean isIPv6Address(String uriHeader) 222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang { 223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // approximately detect the end the host part. 224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //first check if we have an uri param 225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int hostEnd = uriHeader.indexOf(Lexer.QUESTION); 226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //if not or if it appears after a semi-colon then the end of the 228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //address would be a header param. 229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int semiColonIndex = uriHeader.indexOf(Lexer.SEMICOLON); 230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ( hostEnd == -1 231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang || (semiColonIndex!= -1 && hostEnd > semiColonIndex) ) 232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hostEnd = semiColonIndex; 233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //if there was no header param either the address 235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //continues until the end of the string 236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if ( hostEnd == -1 ) 237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hostEnd = uriHeader.length(); 238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang //extract the address 240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String host = uriHeader.substring(0, hostEnd); 241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int firstColonIndex = host.indexOf(Lexer.COLON); 243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if(firstColonIndex == -1) 245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang int secondColonIndex = host.indexOf(Lexer.COLON, firstColonIndex + 1); 248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if(secondColonIndex == -1) 250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return false; 251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return true; 253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang /** 255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Parses a host:port string 256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * 257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @param allowWS - whether whitespace is allowed around ':', only true for Via headers 258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @return 259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @throws ParseException 260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */ 261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public HostPort hostPort( boolean allowWS ) throws ParseException { 262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (debug) 263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dbg_enter("hostPort"); 264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang Host host = this.host(); 266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang HostPort hp = new HostPort(); 267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hp.setHost(host); 268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Has a port? 269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (allowWS) lexer.SPorHT(); // white space before ":port" should be accepted 270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (lexer.hasMoreChars()) { 271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang char la = lexer.lookAhead(0); 272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang switch (la) 273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang { 274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang case ':': 275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.consume(1); 276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (allowWS) lexer.SPorHT(); // white space before port number should be accepted 277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String port = lexer.number(); 279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang hp.setPort(Integer.parseInt(port)); 280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (NumberFormatException nfe) { 281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException( 282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.getBuffer() + " :Error parsing port ", 283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.getPtr()); 284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang case ',': // allowed in case of multi-headers, e.g. Route 288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang // Could check that current header is a multi hdr 289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang case ';': // OK, can appear in URIs (parameters) 291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang case '?': // same, header parameters 292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang case '>': // OK, can appear in headers 293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang case ' ': // OK, allow whitespace 294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang case '\t': 295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang case '\r': 296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang case '\n': 297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang case '/': // e.g. http://[::1]/xyz.html 298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break; 299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang case '%': 300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if(stripAddressScopeZones){ 301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang break;//OK,allow IPv6 address scope zone 302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang default: 305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (!allowWS) { 306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang throw new ParseException( lexer.getBuffer() + 307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang " Illegal character in hostname:" + lexer.lookAhead(0), 308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang lexer.getPtr() ); 309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang return hp; 313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } finally { 314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang if (debug) 315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang dbg_leave("hostPort"); 316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang public static void main(String args[]) throws ParseException { 320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang String hostNames[] = 321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang { 322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "foo.bar.com:1234", 323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "proxima.chaplin.bt.co.uk", 324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "129.6.55.181:2345", 325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang ":1234", 326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "foo.bar.com: 1234", 327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "foo.bar.com : 1234 ", 328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang "MIK_S:1234" 329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang }; 330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang for (int i = 0; i < hostNames.length; i++) { 332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang try { 333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang HostNameParser hnp = new HostNameParser(hostNames[i]); 334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang HostPort hp = hnp.hostPort(true); 335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang System.out.println("["+hp.encode()+"]"); 336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } catch (ParseException ex) { 337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang System.out.println("exception text = " + ex.getMessage()); 338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang 341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang } 342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang} 343