All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.nist.javax.sip.parser.chars.HostNameParser Maven / Gradle / Ivy

The newest version!
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2011, Red Hat, Inc. and individual contributors
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

/*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain.  As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS."  NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY.  NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
* .
*
*/
/*
 *
 * IPv6 Support added by Emil Ivov ([email protected])
* Network Research Team (http://www-r2.u-strasbg.fr))
* Louis Pasteur University - Strasbourg - France
* *Bug fixes for corner cases were contributed by Thomas Froment. */ package android.gov.nist.javax.sip.parser.chars; import android.gov.nist.core.Host; import android.gov.nist.core.HostPort; import android.gov.nist.javax.sdp.parser.Lexer; import java.text.ParseException; /** * Parser for host names. * *@version 1.2 * *@author M. Ranganathan */ public class HostNameParser extends ParserCore { /** * Determines whether or not we should tolerate and strip address scope * zones from IPv6 addresses. Address scope zones are sometimes returned * at the end of IPv6 addresses generated by InetAddress.getHostAddress(). * They are however not part of the SIP semantics so basically this method * determines whether or not the parser should be stripping them (as * opposed simply being blunt and throwing an exception). */ private static boolean stripAddressScopeZones = false; static { stripAddressScopeZones = Boolean.getBoolean("android.gov.nist.core.STRIP_ADDR_SCOPES"); } public HostNameParser(char[] hname) { this.lexer = new LexerCore("charLexer", hname); } /** * The lexer is initialized with the buffer. */ public HostNameParser(LexerCore lexer) { this.lexer = lexer; lexer.selectLexer("charLexer"); } private static final char[] VALID_DOMAIN_LABEL_CHAR = new char[] {LexerCore.ALPHADIGIT_VALID_CHARS, '-', '.'}; protected void consumeDomainLabel() throws ParseException { if (debug) dbg_enter("domainLabel"); try { lexer.consumeValidChars(VALID_DOMAIN_LABEL_CHAR); } finally { if (debug) dbg_leave("domainLabel"); } } protected String ipv6Reference() throws ParseException { StringBuilder retval = new StringBuilder(); if (debug) dbg_enter("ipv6Reference"); try { if(stripAddressScopeZones){ while (lexer.hasMoreChars()) { char la = lexer.lookAhead(0); //'%' is ipv6 address scope zone. see detail at //java.sun.com/j2se/1.5.0/docs/api/java/net/Inet6Address.html if (LexerCore.isHexDigit(la) || la == '.' || la == ':' || la == '[' ) { lexer.consume(1); retval.append(la); } else if (la == ']') { lexer.consume(1); retval.append(la); return retval.toString(); } else if (la == '%'){ //we need to strip the address scope zone. lexer.consume(1); String rest = lexer.getRest(); if(rest == null || rest.length() == 0){ //head for the parse exception break; } //we strip everything until either the end of the string //or a closing square bracket (]) int stripLen = rest.indexOf(']'); if (stripLen == -1){ //no square bracket -> not a valid ipv6 reference break; } lexer.consume(stripLen+1); retval.append("]"); return retval.toString(); } else break; } } else { while (lexer.hasMoreChars()) { char la = lexer.lookAhead(0); if (LexerCore.isHexDigit(la) || la == '.' || la == ':' || la == '[') { lexer.consume(1); retval.append(la); } else if (la == ']') { lexer.consume(1); retval.append(la); return retval.toString(); } else break; } } throw new ParseException( lexer.getBuffer() + ": Illegal Host name ", lexer.getPtr()); } finally { if (debug) dbg_leave("ipv6Reference"); } } public Host host() throws ParseException { if (debug) dbg_enter("host"); try { String hostname; //IPv6 referene if (lexer.lookAhead(0) == '[') { hostname = ipv6Reference(); } //IPv6 address (i.e. missing square brackets) else if( isIPv6Address(lexer.getRest()) ) { int startPtr = lexer.getPtr(); lexer.consumeValidChars( new char[] {LexerCore.ALPHADIGIT_VALID_CHARS, ':'}); hostname = new StringBuilder("[").append( lexer.getSubBuffer(startPtr, lexer.getPtr())) .append("]").toString(); } //IPv4 address or hostname else { int startPtr = lexer.getPtr(); consumeDomainLabel(); hostname = String.valueOf(lexer.getSubBuffer(startPtr, lexer.getPtr())); } if (hostname.length() == 0) throw new ParseException( lexer.getBuffer() + ": Missing host name", lexer.getPtr()); else return new Host(hostname); } finally { if (debug) dbg_leave("host"); } } /** * Tries to determine whether the address in uriHeader could be * an IPv6 address by counting the number of colons that appear in it. * * @param uriHeader the string (supposedly the value of a URI header) that * we have received for parsing. * * @return true if the host part of uriHeader could be an IPv6 * address (i.e. contains at least two colons) and false otherwise. */ private boolean isIPv6Address(String uriHeader) { // Issue 275 https://jain-sip.dev.java.net/issues/show_bug.cgi?id=275 // we check if the uriHeader includes a comma, if that's the case we are potentially parsing // a multi header so strip everything after it String hostName = uriHeader; int indexOfComma = uriHeader.indexOf(","); if(indexOfComma != -1) { hostName = uriHeader.substring(0, indexOfComma); } // approximately detect the end the host part. //first check if we have an uri param int hostEnd = hostName.indexOf(Lexer.QUESTION); //if not or if it appears after a semi-colon then the end of the //address would be a header param. int semiColonIndex = hostName.indexOf(Lexer.SEMICOLON); if ( hostEnd == -1 || (semiColonIndex!= -1 && hostEnd > semiColonIndex) ) hostEnd = semiColonIndex; //if there was no header param either the address //continues until the end of the string if ( hostEnd == -1 ) hostEnd = hostName.length(); //extract the address String host = hostName.substring(0, hostEnd); int firstColonIndex = host.indexOf(Lexer.COLON); if(firstColonIndex == -1) return false; int secondColonIndex = host.indexOf(Lexer.COLON, firstColonIndex + 1); if(secondColonIndex == -1) return false; return true; } /** * Parses a host:port string * * @param allowWS - whether whitespace is allowed around ':', only true for Via headers * @return * @throws ParseException */ public HostPort hostPort( boolean allowWS ) throws ParseException { if (debug) dbg_enter("hostPort"); try { Host host = this.host(); HostPort hp = new HostPort(); hp.setHost(host); // Has a port? if (allowWS) lexer.SPorHT(); // white space before ":port" should be accepted if (lexer.hasMoreChars()) { char la = lexer.lookAhead(0); switch (la) { case ':': lexer.consume(1); if (allowWS) lexer.SPorHT(); // white space before port number should be accepted try { String port = lexer.number(); hp.setPort(Integer.parseInt(port)); } catch (NumberFormatException nfe) { throw new ParseException( lexer.getBuffer() + " :Error parsing port ", lexer.getPtr()); } break; case ',': // allowed in case of multi-headers, e.g. Route // Could check that current header is a multi hdr case ';': // OK, can appear in URIs (parameters) case '?': // same, header parameters case '>': // OK, can appear in headers case ' ': // OK, allow whitespace case '\t': case '\r': case '\n': case '/': // e.g. http://[::1]/xyz.html break; case '%': if(stripAddressScopeZones){ break;//OK,allow IPv6 address scope zone } default: if (!allowWS) { throw new ParseException( lexer.getBuffer() + " Illegal character in hostname:" + lexer.lookAhead(0), lexer.getPtr() ); } } } return hp; } finally { if (debug) dbg_leave("hostPort"); } } public static void main(String args[]) throws ParseException { String hostNames[] = { "foo.bar.com:1234", "proxima.chaplin.bt.co.uk", "129.6.55.181:2345", ":1234", "foo.bar.com: 1234", "foo.bar.com : 1234 ", "MIK_S:1234" }; for (int i = 0; i < hostNames.length; i++) { try { HostNameParser hnp = new HostNameParser(hostNames[i].toCharArray()); HostPort hp = hnp.hostPort(true); System.out.println("["+hp.encode()+"]"); } catch (ParseException ex) { System.out.println("exception text = " + ex.getMessage()); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy