PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/servers/jain-sip-ext/src/main/java/gov/nist/javax/sip/parser/chars/URLParser.java

http://mobicents.googlecode.com/
Java | 855 lines | 694 code | 54 blank | 107 comment | 165 complexity | 99324b591345deb33a59fd6e1cce2367 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, GPL-2.0, CC-BY-SA-3.0, CC0-1.0, Apache-2.0, BSD-3-Clause
  1. /*
  2. * JBoss, Home of Professional Open Source
  3. * Copyright 2011, Red Hat, Inc. and individual contributors
  4. * by the @authors tag. See the copyright.txt in the distribution for a
  5. * full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. /*
  23. * Conditions Of Use
  24. *
  25. * This software was developed by employees of the National Institute of
  26. * Standards and Technology (NIST), an agency of the Federal Government.
  27. * Pursuant to title 15 Untied States Code Section 105, works of NIST
  28. * employees are not subject to copyright protection in the United States
  29. * and are considered to be in the public domain. As a result, a formal
  30. * license is not needed to use the software.
  31. *
  32. * This software is provided by NIST as a service and is expressly
  33. * provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
  34. * OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
  35. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
  36. * AND DATA ACCURACY. NIST does not warrant or make any representations
  37. * regarding the use of the software or the results thereof, including but
  38. * not limited to the correctness, accuracy, reliability or usefulness of
  39. * the software.
  40. *
  41. * Permission to use this software is contingent upon your acceptance
  42. * of the terms of this agreement
  43. *
  44. * .
  45. *
  46. */
  47. package gov.nist.javax.sip.parser.chars;
  48. import gov.nist.core.HostPort;
  49. import gov.nist.core.NameValue;
  50. import gov.nist.core.NameValueList;
  51. import gov.nist.javax.sip.address.GenericURI;
  52. import gov.nist.javax.sip.address.SipUri;
  53. import gov.nist.javax.sip.address.TelURLImpl;
  54. import gov.nist.javax.sip.address.TelephoneNumber;
  55. import java.text.ParseException;
  56. /**
  57. * Parser For SIP and Tel URLs. Other kinds of URL's are handled by the
  58. * J2SE 1.4 URL class.
  59. * @version 1.2 $Revision: 1.27 $ $Date: 2009/10/22 10:27:39 $
  60. *
  61. * @author M. Ranganathan <br/>
  62. *
  63. *
  64. */
  65. public class URLParser extends Parser {
  66. public URLParser(char[] url) {
  67. this.lexer = new Lexer("sip_urlLexer", url);
  68. }
  69. // public tag added - issued by Miguel Freitas
  70. public URLParser(Lexer lexer) {
  71. this.lexer = lexer;
  72. this.lexer.selectLexer("sip_urlLexer");
  73. }
  74. protected static boolean isMark(char next) {
  75. switch (next) {
  76. case '-':
  77. case '_':
  78. case '.':
  79. case '!':
  80. case '~':
  81. case '*':
  82. case '\'':
  83. case '(':
  84. case ')':
  85. return true;
  86. default:
  87. return false;
  88. }
  89. }
  90. protected static boolean isUnreserved(char next) {
  91. return Lexer.isAlphaDigit(next) || isMark(next);
  92. }
  93. protected static boolean isReservedNoSlash(char next) {
  94. switch (next) {
  95. case ';':
  96. case '?':
  97. case ':':
  98. case '@':
  99. case '&':
  100. case '+':
  101. case '$':
  102. case ',':
  103. return true;
  104. default:
  105. return false;
  106. }
  107. }
  108. // Missing '=' bug in character set - discovered by interop testing
  109. // at SIPIT 13 by Bob Johnson and Scott Holben.
  110. // change . to ; by Bruno Konik
  111. protected static boolean isUserUnreserved(char la) {
  112. switch (la) {
  113. case '&':
  114. case '?':
  115. case '+':
  116. case '$':
  117. case '#':
  118. case '/':
  119. case ',':
  120. case ';':
  121. case '=':
  122. return true;
  123. default:
  124. return false;
  125. }
  126. }
  127. protected String unreserved() throws ParseException {
  128. char next = lexer.lookAhead(0);
  129. if (isUnreserved(next)) {
  130. lexer.consume(1);
  131. return String.valueOf(next);
  132. } else
  133. throw createParseException("unreserved");
  134. }
  135. /** Name or value of a parameter.
  136. */
  137. protected String paramNameOrValue() throws ParseException {
  138. int startIdx = lexer.getPtr();
  139. while (lexer.hasMoreChars()) {
  140. char next = lexer.lookAhead(0);
  141. boolean isValidChar = false;
  142. switch (next) {
  143. case '[':
  144. case ']':// JvB: fixed this one
  145. case '/':
  146. case ':':
  147. case '&':
  148. case '+':
  149. case '$':
  150. isValidChar = true;
  151. }
  152. if (isValidChar || isUnreserved(next)) {
  153. lexer.consume(1);
  154. } else if (isEscaped()) {
  155. lexer.consume(3);
  156. } else
  157. break;
  158. }
  159. return String.valueOf(lexer.getSubBuffer(startIdx, lexer.getPtr()));
  160. }
  161. private NameValue uriParam() throws ParseException {
  162. if (debug)
  163. dbg_enter("uriParam");
  164. try {
  165. String pvalue = "";
  166. String pname = paramNameOrValue();
  167. char next = lexer.lookAhead(0);
  168. boolean isFlagParam = true;
  169. if (next == '=') {
  170. lexer.consume(1);
  171. pvalue = paramNameOrValue();
  172. isFlagParam = false;
  173. }
  174. if (pname.length() == 0 &&
  175. ( pvalue == null ||
  176. pvalue.length() == 0))
  177. return null;
  178. else return new NameValue(pname, pvalue, isFlagParam);
  179. } finally {
  180. if (debug)
  181. dbg_leave("uriParam");
  182. }
  183. }
  184. protected static boolean isReserved(char next) {
  185. switch (next) {
  186. case ';':
  187. case '/':
  188. case '?':
  189. case ':':
  190. case '=': // Bug fix by Bruno Konik
  191. case '@':
  192. case '&':
  193. case '+':
  194. case '$':
  195. case ',':
  196. return true;
  197. default:
  198. return false;
  199. }
  200. }
  201. protected String reserved() throws ParseException {
  202. char next = lexer.lookAhead(0);
  203. if (isReserved(next)) {
  204. lexer.consume(1);
  205. return new StringBuilder().append(next).toString();
  206. } else
  207. throw createParseException("reserved");
  208. }
  209. protected boolean isEscaped() {
  210. try {
  211. return lexer.lookAhead(0) == '%' &&
  212. Lexer.isHexDigit(lexer.lookAhead(1)) &&
  213. Lexer.isHexDigit(lexer.lookAhead(2));
  214. } catch (Exception ex) {
  215. return false;
  216. }
  217. }
  218. protected String escaped() throws ParseException {
  219. if (debug)
  220. dbg_enter("escaped");
  221. try {
  222. StringBuilder retval = new StringBuilder();
  223. char next = lexer.lookAhead(0);
  224. char next1 = lexer.lookAhead(1);
  225. char next2 = lexer.lookAhead(2);
  226. if (next == '%'
  227. && Lexer.isHexDigit(next1)
  228. && Lexer.isHexDigit(next2)) {
  229. lexer.consume(3);
  230. retval.append(next);
  231. retval.append(next1);
  232. retval.append(next2);
  233. } else
  234. throw createParseException("escaped");
  235. return retval.toString();
  236. } finally {
  237. if (debug)
  238. dbg_leave("escaped");
  239. }
  240. }
  241. protected String mark() throws ParseException {
  242. if (debug)
  243. dbg_enter("mark");
  244. try {
  245. char next = lexer.lookAhead(0);
  246. if (isMark(next)) {
  247. lexer.consume(1);
  248. return String.valueOf( new char[]{next} );
  249. } else
  250. throw createParseException("mark");
  251. } finally {
  252. if (debug)
  253. dbg_leave("mark");
  254. }
  255. }
  256. protected String uric() {
  257. if (debug)
  258. dbg_enter("uric");
  259. try {
  260. try {
  261. char la = lexer.lookAhead(0);
  262. if (isUnreserved(la)) {
  263. lexer.consume(1);
  264. return Lexer.charAsString(la);
  265. } else if (isReserved(la)) {
  266. lexer.consume(1);
  267. return Lexer.charAsString(la);
  268. } else if (isEscaped()) {
  269. String retval = lexer.charAsString(3);
  270. lexer.consume(3);
  271. return retval;
  272. } else
  273. return null;
  274. } catch (Exception ex) {
  275. return null;
  276. }
  277. } finally {
  278. if (debug)
  279. dbg_leave("uric");
  280. }
  281. }
  282. protected String uricNoSlash() {
  283. if (debug)
  284. dbg_enter("uricNoSlash");
  285. try {
  286. try {
  287. char la = lexer.lookAhead(0);
  288. if (isEscaped()) {
  289. String retval = lexer.charAsString(3);
  290. lexer.consume(3);
  291. return retval;
  292. } else if (isUnreserved(la)) {
  293. lexer.consume(1);
  294. return Lexer.charAsString(la);
  295. } else if (isReservedNoSlash(la)) {
  296. lexer.consume(1);
  297. return Lexer.charAsString(la);
  298. } else
  299. return null;
  300. } catch (ParseException ex) {
  301. return null;
  302. }
  303. } finally {
  304. if (debug)
  305. dbg_leave("uricNoSlash");
  306. }
  307. }
  308. protected String uricString() throws ParseException {
  309. StringBuilder retval = new StringBuilder();
  310. while (true) {
  311. String next = uric();
  312. if (next == null) {
  313. char la = lexer.lookAhead(0);
  314. // JvB: allow IPv6 addresses in generic URI strings
  315. // e.g. http://[::1]
  316. if ( la == '[' ) {
  317. HostNameParser hnp = new HostNameParser(this.getLexer());
  318. HostPort hp = hnp.hostPort( false );
  319. retval.append(hp.toString());
  320. continue;
  321. }
  322. break;
  323. }
  324. retval.append(next);
  325. }
  326. return retval.toString();
  327. }
  328. /**
  329. * Parse and return a structure for a generic URL.
  330. * Note that non SIP URLs are just stored as a string (not parsed).
  331. * @return URI is a URL structure for a SIP url.
  332. * @throws ParseException if there was a problem parsing.
  333. */
  334. public GenericURI uriReference( boolean inBrackets ) throws ParseException {
  335. if (debug)
  336. dbg_enter("uriReference");
  337. GenericURI retval = null;
  338. Token[] tokens = lexer.peekNextToken(2);
  339. Token t1 = (Token) tokens[0];
  340. Token t2 = (Token) tokens[1];
  341. try {
  342. if (t1.getTokenType() == TokenTypes.SIP ||
  343. t1.getTokenType() == TokenTypes.SIPS) {
  344. if (t2.getTokenType() == ':')
  345. retval = sipURL( inBrackets );
  346. else
  347. throw createParseException("Expecting \':\'");
  348. } else if (t1.getTokenType() == TokenTypes.TEL) {
  349. if (t2.getTokenType() == ':') {
  350. retval = telURL( inBrackets );
  351. } else
  352. throw createParseException("Expecting \':\'");
  353. } else {
  354. String urlString = uricString();
  355. try {
  356. retval = new GenericURI(urlString);
  357. } catch (ParseException ex) {
  358. throw createParseException(ex.getMessage());
  359. }
  360. }
  361. } finally {
  362. if (debug)
  363. dbg_leave("uriReference");
  364. }
  365. return retval;
  366. }
  367. /**
  368. * Parser for the base phone number.
  369. */
  370. private String base_phone_number() throws ParseException {
  371. StringBuilder s = new StringBuilder();
  372. if (debug)
  373. dbg_enter("base_phone_number");
  374. try {
  375. int lc = 0;
  376. while (lexer.hasMoreChars()) {
  377. char w = lexer.lookAhead(0);
  378. if (Lexer.isDigit(w)
  379. || w == '-'
  380. || w == '.'
  381. || w == '('
  382. || w == ')') {
  383. lexer.consume(1);
  384. s.append(w);
  385. lc++;
  386. } else if (lc > 0)
  387. break;
  388. else
  389. throw createParseException("unexpected " + w);
  390. }
  391. return s.toString();
  392. } finally {
  393. if (debug)
  394. dbg_leave("base_phone_number");
  395. }
  396. }
  397. /**
  398. * Parser for the local phone #.
  399. */
  400. private String local_number() throws ParseException {
  401. StringBuilder s = new StringBuilder();
  402. if (debug)
  403. dbg_enter("local_number");
  404. try {
  405. int lc = 0;
  406. while (lexer.hasMoreChars()) {
  407. char la = lexer.lookAhead(0);
  408. if (la == '*'
  409. || la == '#'
  410. || la == '-'
  411. || la == '.'
  412. || la == '('
  413. || la == ')'
  414. // JvB: allow 'A'..'F', should be uppercase
  415. || Lexer.isHexDigit(la)) {
  416. lexer.consume(1);
  417. s.append(la);
  418. lc++;
  419. } else if (lc > 0)
  420. break;
  421. else
  422. throw createParseException("unexepcted " + la);
  423. }
  424. return s.toString();
  425. } finally {
  426. if (debug)
  427. dbg_leave("local_number");
  428. }
  429. }
  430. /**
  431. * Parser for telephone subscriber.
  432. *
  433. * @return the parsed telephone number.
  434. */
  435. public final TelephoneNumber parseTelephoneNumber( boolean inBrackets )
  436. throws ParseException {
  437. TelephoneNumber tn;
  438. if (debug)
  439. dbg_enter("telephone_subscriber");
  440. lexer.selectLexer("charLexer");
  441. try {
  442. char c = lexer.lookAhead(0);
  443. if (c == '+')
  444. tn = global_phone_number( inBrackets );
  445. else if (
  446. Lexer.isHexDigit(c)// see RFC3966
  447. || c == '#'
  448. || c == '*'
  449. || c == '-'
  450. || c == '.'
  451. || c == '('
  452. || c == ')' ) {
  453. tn = local_phone_number( inBrackets );
  454. } else
  455. throw createParseException("unexpected char " + c);
  456. return tn;
  457. } finally {
  458. if (debug)
  459. dbg_leave("telephone_subscriber");
  460. }
  461. }
  462. private final TelephoneNumber global_phone_number( boolean inBrackets ) throws ParseException {
  463. if (debug)
  464. dbg_enter("global_phone_number");
  465. try {
  466. TelephoneNumber tn = new TelephoneNumber();
  467. tn.setGlobal(true);
  468. NameValueList nv = null;
  469. this.lexer.match(PLUS);
  470. String b = base_phone_number();
  471. tn.setPhoneNumber(b);
  472. if (lexer.hasMoreChars()) {
  473. char tok = lexer.lookAhead(0);
  474. if (tok == ';' && inBrackets) {
  475. this.lexer.consume(1);
  476. nv = tel_parameters();
  477. tn.setParameters(nv);
  478. }
  479. }
  480. return tn;
  481. } finally {
  482. if (debug)
  483. dbg_leave("global_phone_number");
  484. }
  485. }
  486. private TelephoneNumber local_phone_number( boolean inBrackets ) throws ParseException {
  487. if (debug)
  488. dbg_enter("local_phone_number");
  489. TelephoneNumber tn = new TelephoneNumber();
  490. tn.setGlobal(false);
  491. NameValueList nv = null;
  492. String b = null;
  493. try {
  494. b = local_number();
  495. tn.setPhoneNumber(b);
  496. if (lexer.hasMoreChars()) {
  497. Token tok = this.lexer.peekNextToken();
  498. switch (tok.getTokenType()) {
  499. case SEMICOLON:
  500. {
  501. if (inBrackets) {
  502. this.lexer.consume(1);
  503. nv = tel_parameters();
  504. tn.setParameters(nv);
  505. }
  506. break;
  507. }
  508. default :
  509. {
  510. break;
  511. }
  512. }
  513. }
  514. } finally {
  515. if (debug)
  516. dbg_leave("local_phone_number");
  517. }
  518. return tn;
  519. }
  520. private NameValueList tel_parameters() throws ParseException {
  521. NameValueList nvList = new NameValueList();
  522. // JvB: Need to handle 'phone-context' specially
  523. // 'isub' (or 'ext') MUST appear first, but we accept any order here
  524. NameValue nv;
  525. while ( true ) {
  526. String pname = paramNameOrValue();
  527. // Handle 'phone-context' specially, it may start with '+'
  528. if ( pname.equalsIgnoreCase("phone-context")) {
  529. nv = phone_context();
  530. } else {
  531. if (lexer.lookAhead(0) == '=') {
  532. lexer.consume(1);
  533. String value = paramNameOrValue();
  534. nv = new NameValue( pname, value, false );
  535. } else {
  536. nv = new NameValue( pname, "", true );// flag param
  537. }
  538. }
  539. nvList.set( nv );
  540. if ( lexer.lookAhead(0) == ';' ) {
  541. lexer.consume(1);
  542. } else {
  543. return nvList;
  544. }
  545. }
  546. }
  547. /**
  548. * Parses the 'phone-context' parameter in tel: URLs
  549. * @throws ParseException
  550. */
  551. private NameValue phone_context() throws ParseException {
  552. lexer.match('=');
  553. char la = lexer.lookAhead(0);
  554. Object value;
  555. if (la=='+') {// global-number-digits
  556. lexer.consume(1);// skip '+'
  557. value = "+" + base_phone_number();
  558. } else if ( Lexer.isAlphaDigit(la) ) {
  559. Token t = lexer.match( Lexer.ID );// more broad than allowed
  560. value = t.getTokenValue();
  561. } else {
  562. throw new ParseException( "Invalid phone-context:" + la , -1 );
  563. }
  564. return new NameValue( "phone-context", value, false );
  565. }
  566. /**
  567. * Parse and return a structure for a Tel URL.
  568. * @return a parsed tel url structure.
  569. */
  570. public TelURLImpl telURL( boolean inBrackets ) throws ParseException {
  571. lexer.match(TokenTypes.TEL);
  572. lexer.match(':');
  573. TelephoneNumber tn = this.parseTelephoneNumber(inBrackets);
  574. TelURLImpl telUrl = new TelURLImpl();
  575. telUrl.setTelephoneNumber(tn);
  576. return telUrl;
  577. }
  578. /**
  579. * Parse and return a structure for a SIP URL.
  580. * @return a URL structure for a SIP url.
  581. * @throws ParseException if there was a problem parsing.
  582. */
  583. public SipUri sipURL( boolean inBrackets ) throws ParseException {
  584. if (debug)
  585. dbg_enter("sipURL");
  586. SipUri retval = new SipUri();
  587. // pmusgrave - handle sips case
  588. Token nextToken = lexer.peekNextToken();
  589. int sipOrSips = TokenTypes.SIP;
  590. String scheme = TokenNames.SIP;
  591. if ( nextToken.getTokenType() == TokenTypes.SIPS)
  592. {
  593. sipOrSips = TokenTypes.SIPS;
  594. scheme = TokenNames.SIPS;
  595. }
  596. try {
  597. lexer.match(sipOrSips);
  598. lexer.match(':');
  599. retval.setScheme(scheme);
  600. int startOfUser = lexer.markInputPosition();
  601. String userOrHost = user();// Note: user may contain ';', host may not...
  602. String passOrPort = null;
  603. // name:password or host:port
  604. if ( lexer.lookAhead() == ':' ) {
  605. lexer.consume(1);
  606. passOrPort = password();
  607. }
  608. // name@hostPort
  609. if ( lexer.lookAhead() == '@' ) {
  610. lexer.consume(1);
  611. retval.setUser( userOrHost );
  612. if (passOrPort!=null) retval.setUserPassword( passOrPort );
  613. } else {
  614. // then userOrHost was a host, backtrack just in case a ';' was eaten...
  615. lexer.rewindInputPosition( startOfUser );
  616. }
  617. HostNameParser hnp = new HostNameParser(this.getLexer());
  618. HostPort hp = hnp.hostPort( false );
  619. retval.setHostPort(hp);
  620. lexer.selectLexer("charLexer");
  621. while (lexer.hasMoreChars()) {
  622. // If the URI is not enclosed in brackets, parameters belong to header
  623. if (lexer.lookAhead(0) != ';' || !inBrackets)
  624. break;
  625. lexer.consume(1);
  626. NameValue parms = uriParam();
  627. if (parms != null) retval.setUriParameter(parms);
  628. }
  629. if (lexer.hasMoreChars() && lexer.lookAhead(0) == '?') {
  630. lexer.consume(1);
  631. while (lexer.hasMoreChars()) {
  632. NameValue parms = qheader();
  633. retval.setQHeader(parms);
  634. if (lexer.hasMoreChars() && lexer.lookAhead(0) != '&')
  635. break;
  636. else
  637. lexer.consume(1);
  638. }
  639. }
  640. return retval;
  641. } finally {
  642. if (debug)
  643. dbg_leave("sipURL");
  644. }
  645. }
  646. public String peekScheme() throws ParseException {
  647. Token[] tokens = lexer.peekNextToken(1);
  648. if (tokens.length == 0)
  649. return null;
  650. String scheme = ((Token) tokens[0]).getTokenValue();
  651. return scheme;
  652. }
  653. /**
  654. * Get a name value for a given query header (ie one that comes
  655. * after the ?).
  656. */
  657. protected NameValue qheader() throws ParseException {
  658. String name = lexer.getNextToken('=');
  659. lexer.consume(1);
  660. String value = hvalue();
  661. return new NameValue(name, value, false);
  662. }
  663. protected String hvalue() throws ParseException {
  664. StringBuilder retval = new StringBuilder();
  665. while (lexer.hasMoreChars()) {
  666. char la = lexer.lookAhead(0);
  667. // Look for a character that can terminate a URL.
  668. boolean isValidChar = false;
  669. switch (la) {
  670. case '+':
  671. case '?':
  672. case ':':
  673. case '[':
  674. case ']':
  675. case '/':
  676. case '$':
  677. case '_':
  678. case '-':
  679. case '"':
  680. case '!':
  681. case '~':
  682. case '*':
  683. case '.':
  684. case '(':
  685. case ')':
  686. isValidChar = true;
  687. }
  688. if (isValidChar || Lexer.isAlphaDigit(la)) {
  689. lexer.consume(1);
  690. retval.append(la);
  691. } else if (la == '%') {
  692. retval.append(escaped());
  693. } else
  694. break;
  695. }
  696. return retval.toString();
  697. }
  698. /**
  699. * Scan forward until you hit a terminating character for a URL.
  700. * We do not handle non sip urls in this implementation.
  701. * @return the string that takes us to the end of this URL (i.e. to
  702. * the next delimiter).
  703. */
  704. protected String urlString() throws ParseException {
  705. StringBuilder retval = new StringBuilder();
  706. lexer.selectLexer("charLexer");
  707. while (lexer.hasMoreChars()) {
  708. char la = lexer.lookAhead(0);
  709. // Look for a character that can terminate a URL.
  710. if (la == ' '
  711. || la == '\t'
  712. || la == '\n'
  713. || la == '>'
  714. || la == '<')
  715. break;
  716. lexer.consume(0);
  717. retval.append(la);
  718. }
  719. return retval.toString();
  720. }
  721. protected String user() throws ParseException {
  722. if (debug)
  723. dbg_enter("user");
  724. try {
  725. int startIdx = lexer.getPtr();
  726. while (lexer.hasMoreChars()) {
  727. char la = lexer.lookAhead(0);
  728. if (isUnreserved(la) || isUserUnreserved(la)) {
  729. lexer.consume(1);
  730. } else if (isEscaped()) {
  731. lexer.consume(3);
  732. } else
  733. break;
  734. }
  735. return String.valueOf(lexer.getSubBuffer(startIdx, lexer.getPtr()));
  736. } finally {
  737. if (debug)
  738. dbg_leave("user");
  739. }
  740. }
  741. protected String password() throws ParseException {
  742. int startIdx = lexer.getPtr();
  743. while (true) {
  744. char la = lexer.lookAhead(0);
  745. boolean isValidChar = false;
  746. switch (la) {
  747. case '&':
  748. case '=':
  749. case '+':
  750. case '$':
  751. case ',':
  752. isValidChar = true;
  753. }
  754. if (isValidChar || isUnreserved(la)) {
  755. lexer.consume(1);
  756. } else if (isEscaped()) {
  757. lexer.consume(3); // bug reported by
  758. // Jeff Haynie
  759. } else
  760. break;
  761. }
  762. return String.valueOf(lexer.getSubBuffer(startIdx, lexer.getPtr()));
  763. }
  764. /**
  765. * Default parse method. This method just calls uriReference.
  766. */
  767. public GenericURI parse() throws ParseException {
  768. return uriReference( true );
  769. }
  770. // quick test routine for debugging type assignment
  771. public static void main(String[] args) throws ParseException
  772. {
  773. // quick test for sips parsing
  774. String[] test = { "sip:alice@example.com",
  775. "sips:alice@examples.com" ,
  776. "sip:3Zqkv5dajqaaas0tCjCxT0xH2ZEuEMsFl0xoasip%3A%2B3519116786244%40siplab.domain.com@213.0.115.163:7070"};
  777. for ( int i = 0; i < test.length; i++)
  778. {
  779. URLParser p = new URLParser(test[i].toCharArray());
  780. GenericURI uri = p.parse();
  781. System.out.println("uri type returned " + uri.getClass().getName());
  782. System.out.println(test[i] + " is SipUri? " + uri.isSipURI()
  783. + ">" + uri.encode());
  784. }
  785. }
  786. /**
  787. **/
  788. }