1 package com.atlassian.seraph.util;
2
3 import com.atlassian.seraph.cookie.CookieFactory;
4 import org.apache.log4j.Category;
5
6 import javax.servlet.http.Cookie;
7 import javax.servlet.http.HttpServletRequest;
8 import javax.servlet.http.HttpServletResponse;
9
10 /**
11 * Seraph utility class for dealing with cookies
12 *
13 * Includes code from Jive 1.2.4 (released under the Apache license)
14 */
15 public class CookieUtils
16 {
17 private static final Category log = Category.getInstance(CookieUtils.class);
18
19 // the key which represents the list of cookies to add for this request (in case of redirect)
20 public static final String COOKIES_TO_SEND = "atlassian.core.web.cookies.unsent";
21
22 // Character used to separate username and password in persistent cookies.
23 // 0x13 == "Device Control 3" non-printing ASCII char. Unlikely to appear in a username
24 private static final char DELIMITER = 0x13;
25
26 //"Tweakable" parameters for the cookie encoding. NOTE: changing these
27 //and recompiling this class will essentially invalidate old cookies.
28 private final static int ENCODE_XORMASK = 0x5A;
29 private final static char ENCODE_CHAR_OFFSET1 = 'C';
30 private final static char ENCODE_CHAR_OFFSET2 = 'i';
31
32 /**
33 * Invalidate the specified cookie and delete it from the response object.
34 *
35 * @param response The HttpServletResponse object, known as "response" in a JSP page.
36 * @param cookieName The name of the cookie you want to delete.
37 * @param path of the path the cookie you want to delete.
38 * @deprecated Since 0.10, use {@link com.atlassian.seraph.cookie.CookieHandler} instead
39 */
40 public static void invalidateCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String path)
41 {
42 CookieFactory.getCookieHandler().invalidateCookie(request, response, cookieName, path);
43 }
44
45 /**
46 * Invalidate the specified cookie and delete it from the response object. Deletes only cookies mapped
47 * against the root "/" path. Otherwise use
48 * {@link #invalidateCookie(HttpServletRequest, HttpServletResponse, String, String)}
49 *
50 * @param response The HttpServletResponse object, known as "response" in a JSP page.
51 * @param cookieName The name of the cookie you want to delete.
52 * @see #invalidateCookie(HttpServletRequest, HttpServletResponse, String, String)
53 * @deprecated Since 0.10, use {@link com.atlassian.seraph.cookie.CookieHandler} instead
54 */
55 public static void invalidateCookie(HttpServletRequest request, HttpServletResponse response, String cookieName)
56 {
57 CookieFactory.getCookieHandler().invalidateCookie(request, response, cookieName, "/");
58 }
59
60 /**
61 * Returns the specified Cookie object, or null if the cookie does not exist.
62 *
63 * @param request The HttpServletRequest object, known as "request" in a
64 * JSP page.
65 * @param name the name of the cookie.
66 * @return the Cookie object if it exists, otherwise null.
67 * @deprecated Since 0.10, use {@link com.atlassian.seraph.cookie.CookieHandler} instead
68 */
69 public static Cookie getCookie(HttpServletRequest request, String name)
70 {
71 return CookieFactory.getCookieHandler().getCookie(request, name);
72 }
73
74 /**
75 * Sets a cookie
76 *
77 * This will also put the cookie in a list of cookies to send with this request's response
78 * (so that in case of a redirect occurring down the chain, the first filter
79 * will always try to set this cookie again)
80 *
81 * The cookie secure flag is set if the request is secure.
82 * @deprecated Since 0.10, use {@link com.atlassian.seraph.cookie.CookieHandler} instead
83 */
84 public static Cookie setCookie(HttpServletRequest request, HttpServletResponse response, String name, String value, int maxAge, String path)
85 {
86 return CookieFactory.getCookieHandler().setCookie(request, response, name, value, maxAge, path);
87 }
88
89 /**
90 * Returns the value of the specified cookie as a String. If the cookie
91 * does not exist, the method returns null.
92 *
93 * @param request the HttpServletRequest object, known as "request" in a
94 * JSP page.
95 * @param name the name of the cookie
96 * @return the value of the cookie, or null if the cookie does not exist.
97 * @deprecated Since 0.10, use {@link com.atlassian.seraph.cookie.CookieHandler} instead
98 */
99 public static String getCookieValue(HttpServletRequest request, String name)
100 {
101 return CookieFactory.getCookieHandler().getCookieValue(request, name);
102 }
103
104 /**
105 * Builds a cookie string containing a username and password.<p>
106 *
107 * Note: with open source this is not really secure, but it prevents users
108 * from snooping the cookie file of others and by changing the XOR mask and
109 * character offsets, you can easily tweak results.
110 *
111 * @param username The username.
112 * @param password The password.
113 * @return String encoding the input parameters, an empty string if one of
114 * the arguments equals <code>null</code>.
115 * @deprecated Since 0.10, use {@link com.atlassian.seraph.cookie.CookieEncoder} instead
116 */
117 public static String encodePasswordCookie(String username, String password)
118 {
119 return encodePasswordCookie(username, password, new String(new char[]{DELIMITER, ENCODE_CHAR_OFFSET1, ENCODE_CHAR_OFFSET2}));
120 }
121
122 /**
123 * Builds a cookie string containing a username and password, using offsets to customise the encoding.<p>
124 *
125 * Note: with open source this is not really secure, but it prevents users
126 * from snooping the cookie file of others and by changing the XOR mask and
127 * character offsets, you can easily tweak results.
128 *
129 * @param username The username.
130 * @param password The password.
131 * @param encoding A String used to customise cookie encoding (only the first 3 characters are used)
132 * @return String encoding the input parameters, an empty string if one of
133 * the arguments equals <code>null</code>.
134 * @deprecated Since 0.10, use {@link com.atlassian.seraph.cookie.CookieEncoder} instead
135 */
136 public static String encodePasswordCookie(String username, String password, String encoding)
137 {
138 StringBuffer buf = new StringBuffer();
139 if (username != null && password != null)
140 {
141 char offset1 = (encoding != null && encoding.length() > 1) ? encoding.charAt(1) : ENCODE_CHAR_OFFSET1;
142 char offset2 = (encoding != null && encoding.length() > 2) ? encoding.charAt(2) : ENCODE_CHAR_OFFSET2;
143
144 byte[] bytes = (username + DELIMITER + password).getBytes();
145 int b;
146
147 for (int n = 0; n < bytes.length; n++)
148 {
149 b = bytes[n] ^ (ENCODE_XORMASK + n);
150 buf.append((char) (offset1 + (b & 0x0F)));
151 buf.append((char) (offset2 + ((b >> 4) & 0x0F)));
152 }
153 }
154 return buf.toString();
155 }
156
157 /**
158 * Decodes a cookie string containing a username and password.
159 * @param cookieVal The cookie value.
160 * @return String[] containing the username at index 0 and the password at
161 * index 1, or <code>{ null, null }</code> if cookieVal equals
162 * <code>null</code> or the empty string.
163 * @deprecated Since 0.10, use {@link com.atlassian.seraph.cookie.CookieEncoder} instead
164 */
165 public static String[] decodePasswordCookie(String cookieVal)
166 {
167 return decodePasswordCookie(cookieVal, new String(new char[]{DELIMITER, ENCODE_CHAR_OFFSET1, ENCODE_CHAR_OFFSET2}));
168 }
169
170 /**
171 * Decodes a cookie string containing a username and password.
172 * @param cookieVal The cookie value.
173 * @param encoding A String used to customise cookie encoding (only the first 3 characters are used) - should be the same string you used to encode the cookie!
174 * @return String[] containing the username at index 0 and the password at
175 * index 1, or <code>{ null, null }</code> if cookieVal equals
176 * <code>null</code> or the empty string.
177 * @deprecated Since 0.10, use {@link com.atlassian.seraph.cookie.CookieEncoder} instead
178 */
179 public static String[] decodePasswordCookie(String cookieVal, String encoding)
180 {
181 // check that the cookie value isn't null or zero-length
182 if (cookieVal == null || cookieVal.length() <= 0)
183 {
184 return null;
185 }
186
187 char offset1 = (encoding != null && encoding.length() > 1) ? encoding.charAt(1) : ENCODE_CHAR_OFFSET1;
188 char offset2 = (encoding != null && encoding.length() > 2) ? encoding.charAt(2) : ENCODE_CHAR_OFFSET2;
189
190 // decode the cookie value
191 char[] chars = cookieVal.toCharArray();
192 byte[] bytes = new byte[chars.length / 2];
193 int b;
194 for (int n = 0, m = 0; n < bytes.length; n++)
195 {
196 b = chars[m++] - offset1;
197 b |= (chars[m++] - offset2) << 4;
198 bytes[n] = (byte) (b ^ (ENCODE_XORMASK + n));
199 }
200 cookieVal = new String(bytes);
201 int pos = cookieVal.indexOf(DELIMITER);
202 String username = (pos < 0) ? "" : cookieVal.substring(0, pos);
203 String password = (pos < 0) ? "" : cookieVal.substring(pos + 1);
204
205 return new String[]{username, password};
206 }
207 }