Example #1
0
  /**
   * Given the starting position of a token, this gets the end of the token, with no separator
   * characters in between. JVK
   */
  private static final int getTokenEndPosition(
      byte bytes[], int off, int end, int version, boolean isName) {
    int pos = off;
    while (pos < end
        && (!CookieSupport.isHttpSeparator((char) bytes[pos])
            || version == 0
                && CookieSupport.ALLOW_HTTP_SEPARATORS_IN_V0
                && bytes[pos] != '='
                && !CookieSupport.isV0Separator((char) bytes[pos])
            || !isName && bytes[pos] == '=' && CookieSupport.ALLOW_EQUALS_IN_VALUE)) {
      pos++;
    }

    if (pos > end) {
      return end;
    }
    return pos;
  }
Example #2
0
  /**
   * Parses a cookie header after the initial "Cookie:" [WS][$]token[WS]=[WS](token|QV)[;|,] RFC
   * 2965 JVK
   */
  protected final void processCookieHeader(byte bytes[], int off, int len) {
    if (len <= 0 || bytes == null) {
      return;
    }
    int end = off + len;
    int pos = off;
    int nameStart = 0;
    int nameEnd = 0;
    int valueStart = 0;
    int valueEnd = 0;
    int version = 0;
    ServerCookie sc = null;
    boolean isSpecial;
    boolean isQuoted;

    while (pos < end) {
      isSpecial = false;
      isQuoted = false;

      // Skip whitespace and non-token characters (separators)
      while (pos < end
          && (CookieSupport.isHttpSeparator((char) bytes[pos])
                  && !CookieSupport.ALLOW_HTTP_SEPARATORS_IN_V0
              || CookieSupport.isV0Separator((char) bytes[pos])
              || isWhiteSpace(bytes[pos]))) {
        pos++;
      }

      if (pos >= end) {
        return;
      }

      // Detect Special cookies
      if (bytes[pos] == '$') {
        isSpecial = true;
        pos++;
      }

      // Get the cookie/attribute name. This must be a token
      valueEnd = valueStart = nameStart = pos;
      pos = nameEnd = getTokenEndPosition(bytes, pos, end, version, true);

      // Skip whitespace
      while (pos < end && isWhiteSpace(bytes[pos])) {
        pos++;
      }

      // Check for an '=' -- This could also be a name-only
      // cookie at the end of the cookie header, so if we
      // are past the end of the header, but we have a name
      // skip to the name-only part.
      if (pos < (end - 1) && bytes[pos] == '=') {

        // Skip whitespace
        do {
          pos++;
        } while (pos < end && isWhiteSpace(bytes[pos]));

        if (pos >= end) {
          return;
        }

        // Determine what type of value this is, quoted value,
        // token, name-only with an '=', or other (bad)
        switch (bytes[pos]) {
          case '"': // Quoted Value
            isQuoted = true;
            valueStart = pos + 1; // strip "
            // getQuotedValue returns the position before
            // at the last quote. This must be dealt with
            // when the bytes are copied into the cookie
            valueEnd = getQuotedValueEndPosition(bytes, valueStart, end);
            // We need pos to advance
            pos = valueEnd;
            // Handles cases where the quoted value is
            // unterminated and at the end of the header,
            // e.g. [myname="value]
            if (pos >= end) {
              return;
            }
            break;
          case ';':
          case ',':
            // Name-only cookie with an '=' after the name token
            // This may not be RFC compliant
            valueStart = valueEnd = -1;
            // The position is OK (On a delimiter)
            break;
          default:
            if (version == 0
                    && !CookieSupport.isV0Separator((char) bytes[pos])
                    && CookieSupport.ALLOW_HTTP_SEPARATORS_IN_V0
                || !CookieSupport.isHttpSeparator((char) bytes[pos])
                || bytes[pos] == '=' && CookieSupport.ALLOW_EQUALS_IN_VALUE) {
              // Token
              valueStart = pos;
              // getToken returns the position at the delimiter
              // or other non-token character
              valueEnd = getTokenEndPosition(bytes, valueStart, end, version, false);
              // We need pos to advance
              pos = valueEnd;
            } else {
              // INVALID COOKIE, advance to next delimiter
              // The starting character of the cookie value was
              // not valid.
              UserDataHelper.Mode logMode = userDataLog.getNextMode();
              if (logMode != null) {
                String message = sm.getString("cookies.invalidCookieToken");
                switch (logMode) {
                  case INFO_THEN_DEBUG:
                    message += sm.getString("cookies.fallToDebug");
                    // $FALL-THROUGH$
                  case INFO:
                    log.info(message);
                    break;
                  case DEBUG:
                    log.debug(message);
                }
              }
              while (pos < end && bytes[pos] != ';' && bytes[pos] != ',') {
                pos++;
              }
              pos++;
              // Make sure no special avpairs can be attributed to
              // the previous cookie by setting the current cookie
              // to null
              sc = null;
              continue;
            }
        }
      } else {
        // Name only cookie
        valueStart = valueEnd = -1;
        pos = nameEnd;
      }

      // We should have an avpair or name-only cookie at this
      // point. Perform some basic checks to make sure we are
      // in a good state.

      // Skip whitespace
      while (pos < end && isWhiteSpace(bytes[pos])) {
        pos++;
      }

      // Make sure that after the cookie we have a separator. This
      // is only important if this is not the last cookie pair
      while (pos < end && bytes[pos] != ';' && bytes[pos] != ',') {
        pos++;
      }

      pos++;

      // All checks passed. Add the cookie, start with the
      // special avpairs first
      if (isSpecial) {
        isSpecial = false;
        // $Version must be the first avpair in the cookie header
        // (sc must be null)
        if (equals("Version", bytes, nameStart, nameEnd) && sc == null) {
          // Set version
          if (bytes[valueStart] == '1' && valueEnd == (valueStart + 1)) {
            version = 1;
          } else {
            // unknown version (Versioning is not very strict)
          }
          continue;
        }

        // We need an active cookie for Path/Port/etc.
        if (sc == null) {
          continue;
        }

        // Domain is more common, so it goes first
        if (equals("Domain", bytes, nameStart, nameEnd)) {
          sc.getDomain().setBytes(bytes, valueStart, valueEnd - valueStart);
          continue;
        }

        if (equals("Path", bytes, nameStart, nameEnd)) {
          sc.getPath().setBytes(bytes, valueStart, valueEnd - valueStart);
          continue;
        }

        // v2 cookie attributes - skip them
        if (equals("Port", bytes, nameStart, nameEnd)) {
          continue;
        }
        if (equals("CommentURL", bytes, nameStart, nameEnd)) {
          continue;
        }

        // Unknown cookie, complain
        UserDataHelper.Mode logMode = userDataLog.getNextMode();
        if (logMode != null) {
          String message = sm.getString("cookies.invalidSpecial");
          switch (logMode) {
            case INFO_THEN_DEBUG:
              message += sm.getString("cookies.fallToDebug");
              // $FALL-THROUGH$
            case INFO:
              log.info(message);
              break;
            case DEBUG:
              log.debug(message);
          }
        }
      } else { // Normal Cookie
        if (valueStart == -1 && !CookieSupport.ALLOW_NAME_ONLY) {
          // Skip name only cookies if not supported
          continue;
        }

        sc = addCookie();
        sc.setVersion(version);
        sc.getName().setBytes(bytes, nameStart, nameEnd - nameStart);

        if (valueStart != -1) { // Normal AVPair
          sc.getValue().setBytes(bytes, valueStart, valueEnd - valueStart);
          if (isQuoted) {
            // We know this is a byte value so this is safe
            unescapeDoubleQuotes(sc.getValue().getByteChunk());
          }
        } else {
          // Name Only
          sc.getValue().setString("");
        }
        continue;
      }
    }
  }