zoukankan      html  css  js  c++  java
  • 关于urlDecode和tomcat一些源码

    1. 看下面源码,找到%号,每次加2,然后将16进制转换为int,也就是%号后两位加2得到16进制,转换为int

                       while ( ((i+2) < numChars) && (c=='%')) {
                            int v = Integer.parseInt(s.substring(i+1,i+3),16);
                            if (v < 0)
                                throw new IllegalArgumentException("URLDecoder: Illegal hex characters in escape (%) pattern - negative value");
                            bytes[pos++] = (byte) v;
                            i+= 3;
                            if (i < numChars)
                                c = s.charAt(i);
                        }

    这就是为什么url中不能有%号的原因,

    2. 下面错就有可能url中有特殊字符,比如 %

    Note that the name and value quoted here may be corrupted due to the failed decoding. Use debug level logging to see the original, non-corrupted values.
    Note: further occurrences of Parameter errors will be logged at DEBUG level.

    3. request.getParameter("Json");这个获得的是 null,urldecode之后的,因为urldecode出错了,所以会是null

    4. request.getQueryString();这个得到的是,没有urldecode的,也就是原始的

    二、 关于看tomcat源码的一些知识点,这是一个链接到达tomcat之后,要执行的过程,为什么要总结呢,request.getParameter("Json");中,如果Json中有特殊符号,如%,服务器会的到null,就是因为urldecode导致,看了源码什么都懂了

    String an = request.getQueryString();   //获取没有被urldecode的参数值

    String an = request.getParameter("Json"); //获取被urldecode解码后的参数值

    1.  org.apache.catalina.connector.Connector  ,其中还有很多关于配置的在这个类中,自己看

     public Connector(String protocol) {
            setProtocol(protocol);
            // Instantiate protocol handler
            try {
                Class<?> clazz = Class.forName(protocolHandlerClassName);
                this.protocolHandler = (ProtocolHandler) clazz.newInstance();
            } catch (Exception e) {
                log.error(sm.getString(
                        "coyoteConnector.protocolHandlerInstantiationFailed"), e);
            }
        }

    构造函数中  protocol  对应  server.xml  protocol="HTTP/1.1"   所以构造函数中的 protocol 值为 HTTP/1.1

      <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" maxHttpHeaderSize="1048576"/>

    2. org.apache.catalina.connector.RequestFacade implements HttpServletRequest

     public String getParameter(String name) { //不是这个方法,下面那个方法
    
            if (request == null) {
                throw new IllegalStateException(
                                sm.getString("requestFacade.nullRequest"));
            }
    
            if (Globals.IS_SECURITY_ENABLED){
                return AccessController.doPrivileged(
                    new GetParameterPrivilegedAction(name));
            } else {
                return request.getParameter(name);
            }
        }
     @Override
        public Map<String,String[]> getParameterMap() {//这个方法
    
            if (request == null) {
                throw new IllegalStateException(
                                sm.getString("requestFacade.nullRequest"));
            }
    
            if (Globals.IS_SECURITY_ENABLED){
                return AccessController.doPrivileged(
                    new GetParameterMapPrivilegedAction());
            } else {
                return request.getParameterMap();
            }
        }
     public Map<String, String[]> getParameterMap() {
    
            if (parameterMap.isLocked()) {
                return parameterMap;
            }
    
            Enumeration<String> enumeration = getParameterNames();
            while (enumeration.hasMoreElements()) {
                String name = enumeration.nextElement();
                String[] values = getParameterValues(name);
                parameterMap.put(name, values);
            }
    
            parameterMap.setLocked(true);
    
            return parameterMap;
    
        }
     public Enumeration<String> getParameterNames() {
    
            if (!parametersParsed) {
                parseParameters();
            }
    
            return coyoteRequest.getParameters().getParameterNames();
    
        }

    3. org.apache.catalina.connector.Request implements HttpServletRequest

     public String getParameter(String name) {
    
            if (!parametersParsed) {
                parseParameters();
            }
    
            return coyoteRequest.getParameters().getParameter(name);
    
        }

    4. org.apache.catalina.connector.Request implements HttpServletRequest

    protected void parseParameters() {
    
            parametersParsed = true;
    
            Parameters parameters = coyoteRequest.getParameters();
            boolean success = false;
            try {
                // Set this every time in case limit has been changed via JMX
                parameters.setLimit(getConnector().getMaxParameterCount());  //参数的数量最多为10000
    
                // getCharacterEncoding() may have been overridden to search for
                // hidden form field containing request encoding
                String enc = getCharacterEncoding();
    
                boolean useBodyEncodingForURI = connector.getUseBodyEncodingForURI();
                if (enc != null) {
                    parameters.setEncoding(enc);
                    if (useBodyEncodingForURI) {
                        parameters.setQueryStringEncoding(enc);
                    }
                } else {
                    parameters.setEncoding
                        (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING);
                    if (useBodyEncodingForURI) {
                        parameters.setQueryStringEncoding
                            (org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING);
                    }
                }
    
                parameters.handleQueryParameters();
    
                if (usingInputStream || usingReader) {
                    success = true;
                    return;
                }
    
                if( !getConnector().isParseBodyMethod(getMethod()) ) {
                    success = true;
                    return;
                }
    
                String contentType = getContentType();
                if (contentType == null) {
                    contentType = "";
                }
                int semicolon = contentType.indexOf(';');
                if (semicolon >= 0) {
                    contentType = contentType.substring(0, semicolon).trim();
                } else {
                    contentType = contentType.trim();
                }
    
                if ("multipart/form-data".equals(contentType)) {
                    parseParts();
                    success = true;
                    return;
                }
    
                if (!("application/x-www-form-urlencoded".equals(contentType))) {
                    success = true;
                    return;
                }
    
                int len = getContentLength();
    
                if (len > 0) {
                    int maxPostSize = connector.getMaxPostSize();
                    if ((maxPostSize > 0) && (len > maxPostSize)) {
                        if (context.getLogger().isDebugEnabled()) {
                            context.getLogger().debug(
                                    sm.getString("coyoteRequest.postTooLarge"));
                        }
                        checkSwallowInput();
                        return;
                    }
                    byte[] formData = null;
                    if (len < CACHED_POST_LEN) {
                        if (postData == null) {
                            postData = new byte[CACHED_POST_LEN];
                        }
                        formData = postData;
                    } else {
                        formData = new byte[len];
                    }
                    try {
                        if (readPostBody(formData, len) != len) {
                            return;
                        }
                    } catch (IOException e) {
                        // Client disconnect
                        if (context.getLogger().isDebugEnabled()) {
                            context.getLogger().debug(
                                    sm.getString("coyoteRequest.parseParameters"), e);
                        }
                        return;
                    }
                    parameters.processParameters(formData, 0, len);
                } else if ("chunked".equalsIgnoreCase(
                        coyoteRequest.getHeader("transfer-encoding"))) {
                    byte[] formData = null;
                    try {
                        formData = readChunkedPostBody();
                    } catch (IOException e) {
                        // Client disconnect or chunkedPostTooLarge error
                        if (context.getLogger().isDebugEnabled()) {
                            context.getLogger().debug(
                                    sm.getString("coyoteRequest.parseParameters"), e);
                        }
                        return;
                    }
                    if (formData != null) {
                        parameters.processParameters(formData, 0, formData.length);
                    }
                }
                success = true;
            } finally {
                if (!success) {
                    parameters.setParseFailed(true);
                }
            }
    
        }

    5. org.apache.tomcat.util.http.Parameters  中  processParameters

             

      private void processParameters(byte bytes[], int start, int len,
                                      Charset charset) {
    
            if(log.isDebugEnabled()) {
                log.debug(sm.getString("parameters.bytes",
                        new String(bytes, start, len, DEFAULT_CHARSET)));
            }
    
            int decodeFailCount = 0;
    
            int pos = start;
            int end = start + len;
    
            while(pos < end) {
                int nameStart = pos;
                int nameEnd = -1;
                int valueStart = -1;
                int valueEnd = -1;
    
                boolean parsingName = true;
                boolean decodeName = false;
                boolean decodeValue = false;
                boolean parameterComplete = false;
    
                do {
                    switch(bytes[pos]) {
                        case '=':
                            if (parsingName) {
                                // Name finished. Value starts from next character
                                nameEnd = pos;
                                parsingName = false;
                                valueStart = ++pos;
                            } else {
                                // Equals character in value
                                pos++;
                            }
                            break;
                        case '&':
                            if (parsingName) {
                                // Name finished. No value.
                                nameEnd = pos;
                            } else {
                                // Value finished
                                valueEnd  = pos;
                            }
                            parameterComplete = true;
                            pos++;
                            break;
                        case '%':
                        case '+':
                            // Decoding required
                            if (parsingName) {
                                decodeName = true;
                            } else {
                                decodeValue = true;
                            }
                            pos ++;
                            break;
                        default:
                            pos ++;
                            break;
                    }
                } while (!parameterComplete && pos < end);
    
                if (pos == end) {
                    if (nameEnd == -1) {
                        nameEnd = pos;
                    } else if (valueStart > -1 && valueEnd == -1){
                        valueEnd = pos;
                    }
                }
    
                if (log.isDebugEnabled() && valueStart == -1) {
                    log.debug(sm.getString("parameters.noequal",
                            Integer.valueOf(nameStart), Integer.valueOf(nameEnd),
                            new String(bytes, nameStart, nameEnd-nameStart,
                                    DEFAULT_CHARSET)));
                }
    
                if (nameEnd <= nameStart ) {
                    if (valueStart == -1) {
                        // &&
                        if (log.isDebugEnabled()) {
                            log.debug(sm.getString("parameters.emptyChunk"));
                        }
                        // Do not flag as error
                        continue;
                    }
                    // &=foo&
                    UserDataHelper.Mode logMode = userDataLog.getNextMode();
                    if (logMode != null) {
                        String extract;
                        if (valueEnd > nameStart) {
                            extract = new String(bytes, nameStart, valueEnd
                                    - nameStart, DEFAULT_CHARSET);
                        } else {
                            extract = "";
                        }
                        String message = sm.getString("parameters.invalidChunk",
                                Integer.valueOf(nameStart),
                                Integer.valueOf(valueEnd), extract);
                        switch (logMode) {
                            case INFO_THEN_DEBUG:
                                message += sm.getString("parameters.fallToDebug");
                                //$FALL-THROUGH$
                            case INFO:
                                log.info(message);
                                break;
                            case DEBUG:
                                log.debug(message);
                        }
                    }
                    parseFailed = true;
                    continue;
                    // invalid chunk - it's better to ignore
                }
    
                tmpName.setBytes(bytes, nameStart, nameEnd - nameStart);
                if (valueStart >= 0) {
                    tmpValue.setBytes(bytes, valueStart, valueEnd - valueStart);
                } else {
                    tmpValue.setBytes(bytes, 0, 0);
                }
    
                // Take copies as if anything goes wrong originals will be
                // corrupted. This means original values can be logged.
                // For performance - only done for debug
                if (log.isDebugEnabled()) {
                    try {
                        origName.append(bytes, nameStart, nameEnd - nameStart);
                        if (valueStart >= 0) {
                            origValue.append(bytes, valueStart, valueEnd - valueStart);
                        } else {
                            origValue.append(bytes, 0, 0);
                        }
                    } catch (IOException ioe) {
                        // Should never happen...
                        log.error(sm.getString("parameters.copyFail"), ioe);
                    }
                }
    
                try {
                    String name;
                    String value;
    
                    if (decodeName) {
                        urlDecode(tmpName);
                    }
                    tmpName.setCharset(charset);
                    name = tmpName.toString();
    
                    if (valueStart >= 0) {
                        if (decodeValue) {
                            urlDecode(tmpValue);
                        }
                        tmpValue.setCharset(charset); //ISO-8859-1
                        value = tmpValue.toString();
                    } else {
                        value = "";
                    }
    
                    try {
                        addParameter(name, value);  // 添加到参数集合中
                    } catch (IllegalStateException ise) {
                        // Hitting limit stops processing further params but does
                        // not cause request to fail.
                        parseFailed = true;
                        UserDataHelper.Mode logMode = maxParamCountLog.getNextMode();
                        if (logMode != null) {
                            String message = ise.getMessage();
                            switch (logMode) {
                                case INFO_THEN_DEBUG:
                                    message += sm.getString(
                                            "parameters.maxCountFail.fallToDebug");
                                    //$FALL-THROUGH$
                                case INFO:
                                    log.info(message);
                                    break;
                                case DEBUG:
                                    log.debug(message);
                            }
                        }
                        break;
                    }
                } catch (IOException e) {
                    parseFailed = true;
                    decodeFailCount++;
                    if (decodeFailCount == 1 || log.isDebugEnabled()) {
                        if (log.isDebugEnabled()) {
                            log.debug(sm.getString("parameters.decodeFail.debug",
                                    origName.toString(), origValue.toString()), e);
                        } else if (log.isInfoEnabled()) {
                            UserDataHelper.Mode logMode = userDataLog.getNextMode();
                            if (logMode != null) {
                                String message = sm.getString(
                                        "parameters.decodeFail.info",
                                        tmpName.toString(), tmpValue.toString());
                                switch (logMode) {
                                    case INFO_THEN_DEBUG:
                                        message += sm.getString("parameters.fallToDebug");
                                        //$FALL-THROUGH$
                                    case INFO:
                                        log.info(message);
                                        break;
                                    case DEBUG:
                                        log.debug(message);
                                }
                            }
                        }
                    }
                }
    
                tmpName.recycle();
                tmpValue.recycle();
                // Only recycle copies if we used them
                if (log.isDebugEnabled()) {
                    origName.recycle();
                    origValue.recycle();
                }
            }
    
            if (decodeFailCount > 1 && !log.isDebugEnabled()) {
                UserDataHelper.Mode logMode = userDataLog.getNextMode();
                if (logMode != null) {
                    String message = sm.getString(
                            "parameters.multipleDecodingFail",
                            Integer.valueOf(decodeFailCount));
                    switch (logMode) {
                        case INFO_THEN_DEBUG:
                            message += sm.getString("parameters.fallToDebug");
                            //$FALL-THROUGH$
                        case INFO:
                            log.info(message);
                            break;
                        case DEBUG:
                            log.debug(message);
                    }
                }
            }
        }

    6. org.apache.tomcat.util.buf.UDecoder

        

    public final String convert(String str, boolean query)
        {
            if (str == null) {
                return  null;
            }
    
            if( (!query || str.indexOf( '+' ) < 0) && str.indexOf( '%' ) < 0 ) {
                return str;
            }
    
            final boolean noSlash = !(ALLOW_ENCODED_SLASH || query);
    
            StringBuilder dec = new StringBuilder();    // decoded string output
            int strPos = 0;
            int strLen = str.length();
    
            dec.ensureCapacity(str.length());
            while (strPos < strLen) {
                int laPos;        // lookahead position
    
                // look ahead to next URLencoded metacharacter, if any
                for (laPos = strPos; laPos < strLen; laPos++) {
                    char laChar = str.charAt(laPos);
                    if ((laChar == '+' && query) || (laChar == '%')) {
                        break;
                    }
                }
    
                // if there were non-metacharacters, copy them all as a block
                if (laPos > strPos) {
                    dec.append(str.substring(strPos,laPos));
                    strPos = laPos;
                }
    
                // shortcut out of here if we're at the end of the string
                if (strPos >= strLen) {
                    break;
                }
    
                // process next metacharacter
                char metaChar = str.charAt(strPos);
                if (metaChar == '+') {
                    dec.append(' ');
                    strPos++;
                    continue;
                } else if (metaChar == '%') {
                    // We throw the original exception - the super will deal with
                    // it
                    //                try {
                    char res = (char) Integer.parseInt(   //得到%号后面两个字符,之后以16进制转换成int类型再转换成char类型,之后追加到dec上
                            str.substring(strPos + 1, strPos + 3), 16);
                    if (noSlash && (res == '/')) {
                        throw new IllegalArgumentException("noSlash");
                    }
                    dec.append(res);
                    strPos += 3;
                }
            }
    
            return dec.toString();
        }
  • 相关阅读:
    【JZOJ6223】【20190617】互膜
    【JZOJ6225】【20190618】计数
    【JZOJ6226】【20190618】纳什均衡
    【JZOJ6210】【20190612】wsm
    【学习笔记】析合树
    【JZOJ6206】【20190610】二分图边染色
    【loj3123】【CTS2019】重复
    【loj3120】【CTS2019】珍珠
    【loj3119】【CTS2019】随机立方体
    CTS&&APIO2019爆零记
  • 原文地址:https://www.cnblogs.com/an5211/p/6961838.html
Copyright © 2011-2022 走看看