org.apache.sling.commons.json.http.Cookie Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
package org.apache.sling.commons.json.http;
import java.util.Locale;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.commons.json.JSONTokener;
/*
Public Domain.
*/
/**
* Convert a web browser cookie specification to a JSONObject and back.
* JSON and Cookies are both notations for name/value pairs.
* See also: https://tools.ietf.org/html/rfc6265
*
* @author JSON.org
* @version 2015-12-09
*/
@Deprecated
public class Cookie {
/**
* Constructs a new Cookie object.
*/
public Cookie() {
}
/**
* Produce a copy of a string in which the characters '+', '%', '=', ';'
* and control characters are replaced with "%hh". This is a gentle form
* of URL encoding, attempting to cause as little distortion to the
* string as possible. The characters '=' and ';' are meta characters in
* cookies. By convention, they are escaped using the URL-encoding. This is
* only a convention, not a standard. Often, cookies are expected to have
* encoded values. We encode '=' and ';' because we must. We encode '%' and
* '+' because they are meta characters in URL encoding.
*
* @param string The source string.
* @return The escaped result.
*/
public static String escape(String string) {
char c;
String s = string.trim();
int length = s.length();
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i += 1) {
c = s.charAt(i);
if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') {
sb.append('%');
sb.append(Character.forDigit((char) ((c >>> 4) & 0x0f), 16));
sb.append(Character.forDigit((char) (c & 0x0f), 16));
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
* Convert a cookie specification string into a JSONObject. The string
* must contain a name value pair separated by '='. The name and the value
* will be unescaped, possibly converting '+' and '%' sequences. The
* cookie properties may follow, separated by ';', also represented as
* name=value (except the Attribute properties like "Secure" or "HttpOnly",
* which do not have a value. The value {@link Boolean#TRUE} will be used for
* these).
* The name will be stored under the key "name", and the value will be
* stored under the key "value". This method does not do checking or
* validation of the parameters. It only converts the cookie string into
* a JSONObject. All attribute names are converted to lower case keys in the
* JSONObject (HttpOnly => httponly). If an attribute is specified more than
* once, only the value found closer to the end of the cookie-string is kept.
*
* @param string The cookie specification string.
* @return A JSONObject containing "name", "value", and possibly other
* members.
* @throws JSONException If there is an error parsing the Cookie String.
* Cookie strings must have at least one '=' character and
* the 'name'
* portion of the cookie must not be blank.
*/
public static JSONObject toJSONObject(String string) {
final JSONObject jo = new JSONObject();
String name;
Object value;
JSONTokener x = new JSONTokener(string);
name = unescape(x.nextTo('=').trim());
// per RFC6265, if the name is blank, the cookie should be ignored.
if ("".equals(name)) {
throw new JSONException("Cookies must have a 'name'");
}
jo.put("name", name);
// per RFC6265, if there is no '=', the cookie should be ignored.
// the 'next' call here throws an exception if the '=' is not found.
x.next('=');
jo.put("value", unescape(x.nextTo(';')).trim());
// discard the ';'
x.next();
// parse the remaining cookie attributes
while (x.more()) {
name = unescape(x.nextTo("=;")).trim().toLowerCase(Locale.ROOT);
// don't allow a cookies attributes to overwrite its name or value.
if ("name".equalsIgnoreCase(name)) {
throw new JSONException("Illegal attribute name: 'name'");
}
if ("value".equalsIgnoreCase(name)) {
throw new JSONException("Illegal attribute name: 'value'");
}
// check to see if it's a flag property
if (x.next() != '=') {
value = Boolean.TRUE;
} else {
value = unescape(x.nextTo(';')).trim();
x.next();
}
// only store non-blank attributes
if (!"".equals(name) && !"".equals(value)) {
jo.put(name, value);
}
}
return jo;
}
/**
* Convert a JSONObject into a cookie specification string. The JSONObject
* must contain "name" and "value" members (case insensitive).
* If the JSONObject contains other members, they will be appended to the cookie
* specification string. User-Agents are instructed to ignore unknown
* attributes,
* so ensure your JSONObject is using only known attributes.
* See also: https://tools.ietf.org/html/rfc6265
*
* @param jo A JSONObject
* @return A cookie specification string
* @throws JSONException thrown if the cookie has no name.
*/
public static String toString(JSONObject jo) throws JSONException {
StringBuilder sb = new StringBuilder();
String name = null;
Object value = null;
for (String key : jo.keySet()) {
if ("name".equalsIgnoreCase(key)) {
name = jo.getString(key).trim();
}
if ("value".equalsIgnoreCase(key)) {
value = jo.getString(key).trim();
}
if (name != null && value != null) {
break;
}
}
if (name == null || "".equals(name.trim())) {
throw new JSONException("Cookie does not have a name");
}
if (value == null) {
value = "";
}
sb.append(escape(name));
sb.append("=");
sb.append(escape((String) value));
for (String key : jo.keySet()) {
if ("name".equalsIgnoreCase(key)
|| "value".equalsIgnoreCase(key)) {
// already processed above
continue;
}
value = jo.opt(key);
if (value instanceof Boolean) {
if (Boolean.TRUE.equals(value)) {
sb.append(';').append(escape(key));
}
// don't emit false values
} else {
sb.append(';')
.append(escape(key))
.append('=')
.append(escape(value.toString()));
}
}
return sb.toString();
}
/**
* Convert %
hh sequences to single characters, and
* convert plus to space.
*
* @param string A string that may contain
* +
(plus) and
* %
hh sequences.
* @return The unescaped string.
*/
public static String unescape(String string) {
int length = string.length();
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; ++i) {
char c = string.charAt(i);
if (c == '+') {
c = ' ';
} else if (c == '%' && i + 2 < length) {
int d = JSONTokener.dehexchar(string.charAt(i + 1));
int e = JSONTokener.dehexchar(string.charAt(i + 2));
if (d >= 0 && e >= 0) {
c = (char) (d * 16 + e);
i += 2;
}
}
sb.append(c);
}
return sb.toString();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy