urlrewritercallback.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 451 行

JAVA
451
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source 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, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * *   Free Software Foundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Emil Ong */package com.caucho.quercus.lib;import com.caucho.quercus.env.*;import com.caucho.util.URLUtil;import java.lang.reflect.Method;import java.net.URI;import java.net.URISyntaxException;import java.util.ArrayList;import java.util.HashMap;/** * Implements the built-in URL rewriter for passing session ids and other * variables. */public class UrlRewriterCallback extends CallbackFunction {  private StringBuilder _rewriterQuery = new StringBuilder();  private ArrayList<String[]> _rewriterVars = new ArrayList<String[]>();  public UrlRewriterCallback(Env env)  {    super(env, "URL-Rewriter");    try {      Method rewriterMethod =         UrlRewriterCallback.class.getMethod("_internal_url_rewriter",                                            Env.class, Value.class);      setFunction(new JavaMethod(env.getModuleContext(), rewriterMethod));    } catch (NoSuchMethodException e) {    } catch (SecurityException e) {    }  }  /**   * Returns the unique rewriter.   */  public static UrlRewriterCallback getInstance(Env env)  {    OutputBuffer ob = env.getOutputBuffer();    for (; ob != null; ob = ob.getNext()) {      Callback callback = ob.getCallback();      if (callback instanceof UrlRewriterCallback)        return (UrlRewriterCallback)callback;    }    return null;  }  /**   * Adds a rewrite variable.  Intended for    * <code>output_add_rewrite_var()</code>.   */  public void addRewriterVar(String var, String value)  {    if (_rewriterQuery.length() > 0)      _rewriterQuery.append("&");    String encodedVar = URLUtil.encodeURL(var.replaceAll(" ", "+"));    String encodedValue = URLUtil.encodeURL(value.replaceAll(" ", "+"));    _rewriterQuery.append(encodedVar + "=" + encodedValue);    _rewriterVars.add(new String[] {encodedVar, encodedValue});  }  /**   * Resets (clears) all the rewrite variables.  Intended for    * <code>output_reset_rewrite_vars()</code>.   */  public void resetRewriterVars()  {    _rewriterQuery = new StringBuilder();    _rewriterVars.clear();  }    /**   * Callback function to rewrite URLs to include session information.   * Note that this function should return BooleanValue.FALSE in the   * case where data should be discarded.   */  public static Value _internal_url_rewriter(Env env, Value buffer)  {    Value result;    UrlRewriterCallback rewriter = getInstance(env);    // We should never have been called in this case, but     // return the buffer unmodified anyway.    if (rewriter == null)      result = buffer;    else {      // Return the buffer unmodified when no urls are rewritten      // php/1k6x      Parser parser = rewriter.new Parser(buffer.toString(), env);      result = parser.parse();      if (result.isNull())        result = buffer;    }    return result;  }  private class Parser {    private Env _env;    private boolean _includeSessionInfo = false;    private String _sessionName = null;    private String _sessionId = null;    private String _javaSessionName = null;    private String _javaSessionId = null;    private int _index;    private String _value;    private boolean _quoted;    private String _input;    private StringValue _output;    public Parser(String input, Env env)    {      _input = input;      _env = env;      _index = 0;      _output = env.createUnicodeBuilder();    }    public Value parse()    {      if (_env.getSession() != null && _env.getJavaSession() != null &&          _env.getIni("session.use_trans_sid").toBoolean()) {        _includeSessionInfo = true;        _sessionName = _env.getIni("session.name").toString();        _sessionId = _env.getSession().getId();	_javaSessionName = _env.getQuercus().getCookieName();        _javaSessionId = _env.getJavaSession().getId();      }      if (_includeSessionInfo == false && _rewriterVars.isEmpty())        return NullValue.NULL;      String [] tagPairs =         _env.getIni("url_rewriter.tags").toString().split(",");      HashMap<String,String> tags = new HashMap<String,String>();      for (String tagPair : tagPairs) {        String [] tagAttribute = tagPair.split("=");        switch (tagAttribute.length) {          case 1:            tags.put(tagAttribute[0], null);            break;          case 2:            tags.put(tagAttribute[0], tagAttribute[1]);            break;          default:            break;        }      }      for (String tag = getNextTag(); tag != null; tag = getNextTag()) {        if (tags.containsKey(tag)) {          String attribute = tags.get(tag);                    if (attribute == null) {            consumeToEndOfTag();                        if (_includeSessionInfo) {              String phpSessionInputTag =                 "<input type=\"hidden\" name=\"" + _sessionName + "\"" +                " value=\"" + _sessionId + "\" />";              _output.append(phpSessionInputTag );            }            for (String[] entry : _rewriterVars) {              String inputTag =                 "<input type=\"hidden\" name=\"" + entry[0] + "\"" +                " value=\"" + entry[1] + "\" />";              _output.append(inputTag);            }          } else {            int valueEnd = 0;            for (valueEnd = getNextAttribute(attribute);                 valueEnd == 0;                 valueEnd = getNextAttribute(attribute))            {}            if (valueEnd > 0) {              _output.append(rewriteUrl(_value));              if (_quoted)                consumeOneCharacter();            }          }        }      }      return _output;    }    /**     * Finds the next tag in the string returns it.     */    private String getNextTag()    {      int tagStart = _input.indexOf('<', _index);      if (tagStart < 0) {        _output.append(_input.substring(_index));        return null;      }      // consume everything upto the tag opening      _output.append(_input.substring(_index, tagStart + 1));      // skip the '<'      _index = tagStart + 1;            consumeNonWhiteSpace();      return _input.substring(tagStart + 1, _index);    }    /**     * Finds the next attribute matching the given name.     *     * @return -1 if no more valid attributes can be found, 0 if the next     * attribute is not the one sought, and 1 if the attribute was found.       *     * The _index pointer will refer to the end position for the value     * in the _input in the final case, but only those characters up to      * the beginning of the value will have been copied to the output.     */    private int getNextAttribute(String attribute)    {      consumeWhiteSpace();      int attributeStart = _index;      while (_index < _input.length() &&             isValidAttributeCharacter(_input.charAt(_index)))        consumeOneCharacter();              // no valid attribute was found (we're probably at the end of the tag)      if (_index == attributeStart)        return -1;      String foundAttribute = _input.substring(attributeStart, _index);      consumeWhiteSpace();      // Any attributes that we will affect are of the form attr=value      if (_input.length() <= _index || _input.charAt(_index) != '=')        return -1;      consumeOneCharacter();      consumeWhiteSpace();      // check for quoting      char quote = ' ';            if (_input.charAt(_index) == '"' || _input.charAt(_index) == '\'') {        _quoted = true;        quote = _input.charAt(_index);        consumeOneCharacter();      }      int valueEnd = _index;            if (_quoted) {        valueEnd = _input.indexOf(quote, _index);              // try to account for unclosed quotes        int tagEnd = _input.indexOf('>', _index);        if (valueEnd < 0) {          if (tagEnd > 0)             valueEnd = tagEnd;          else            valueEnd = _input.length();        }      } else {        // skip to the end of the value        for (valueEnd = _index;              valueEnd < _input.length() &&             _input.charAt(valueEnd) != '/' &&             _input.charAt(valueEnd) != '>' &&             _input.charAt(valueEnd) != ' ';             valueEnd++) {}      }      if (foundAttribute.equals(attribute)) {        _value = _input.substring(_index, valueEnd);        _index = valueEnd;        return 1;      } else {        // make sure to skip the complete attribute if it's not the        // one we're looking for.        if (_quoted)          valueEnd += 1;        _output.append(_input.substring(_index, valueEnd));        _index = valueEnd;        return 0;      }    }    private void consumeOneCharacter()    {      if (_index < _input.length()) {        _output.append(_input.charAt(_index));        _index += 1;      }    }    private void consumeWhiteSpace()    {      while (_index < _input.length() &&              Character.isWhitespace(_input.charAt(_index)))        consumeOneCharacter();    }    private void consumeNonWhiteSpace()    {      while (_index < _input.length() &&              !Character.isWhitespace(_input.charAt(_index)))        consumeOneCharacter();    }    private void consumeToEndOfTag()    {      while (_input.charAt(_index) != '>')        consumeOneCharacter();      // consume the '>'      consumeOneCharacter();    }    private boolean isValidAttributeCharacter(char ch)    {      return Character.isLetterOrDigit(ch) ||              (ch == '-') || (ch == '.') || (ch == '_') || (ch == ':');    }    private String rewriteUrl(String urlString)    {      // according to php documentation, it only adds tags to the      // end of relative URLs, but according to RFC 2396, any      // URI beginning with '/' (e.g. <a href="/foo">link</a>) is      // absolute.  Nonetheless, php does add session ids to these      // links.  Thus php must be defining "relative" as relative      // to the host, not the hierarchy.  Thus we only check to make      // sure that the scheme and authority are undefined, not that      // the first character of the path begins with '/'.      URI uri;      try {        uri = new URI(urlString);      } catch (URISyntaxException e) {        return urlString;      }      if ((uri.getScheme() != null) || (uri.getAuthority() != null)) {        return urlString;      }      StringBuilder query = new StringBuilder();      if (uri.getQuery() != null) {        query.append("?");        query.append(uri.getQuery());        query.append("&");      }       else        query.append("?");      if (_includeSessionInfo) {        query.append(_sessionName);        query.append("=");        query.append(_sessionId);      }      if (_rewriterQuery.length() != 0) {        if (_includeSessionInfo)          query.append("&");        query.append(_rewriterQuery);      }      StringBuilder newUri = new StringBuilder();      if (uri.getPath() != null)        newUri.append(uri.getPath());      newUri.append(query);      if (uri.getFragment() != null) {        newUri.append("#");        newUri.append(uri.getFragment());      }      return newUri.toString();    }  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?