View Javadoc

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 }