Source Code Cross Referenced for CookieFilter.java in  » Web-Server » Brazil » sunlabs » brazil » proxy » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Server » Brazil » sunlabs.brazil.proxy 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * CookieFilter.java
003:         *
004:         * Brazil project web application Framework,
005:         * export version: 1.1 
006:         * Copyright (c) 1999-2000 Sun Microsystems, Inc.
007:         *
008:         * Sun Public License Notice
009:         *
010:         * The contents of this file are subject to the Sun Public License Version 
011:         * 1.0 (the "License"). You may not use this file except in compliance with 
012:         * the License. A copy of the License is included as the file "license.terms",
013:         * and also available at http://www.sun.com/
014:         * 
015:         * The Original Code is from:
016:         *    Brazil project web application Framework release 1.1.
017:         * The Initial Developer of the Original Code is: suhler.
018:         * Portions created by suhler are Copyright (C) Sun Microsystems, Inc.
019:         * All Rights Reserved.
020:         * 
021:         * Contributor(s): cstevens, suhler.
022:         *
023:         * Version:  1.22
024:         * Created by suhler on 99/01/27
025:         * Last modified by suhler on 00/12/11 13:31:29
026:         */
027:
028:        package sunlabs.brazil.proxy;
029:
030:        import sunlabs.brazil.filter.Filter;
031:        import sunlabs.brazil.server.Request;
032:        import sunlabs.brazil.server.Server;
033:        import sunlabs.brazil.session.SessionManager;
034:        import sunlabs.brazil.util.http.MimeHeaders;
035:
036:        import java.text.SimpleDateFormat;
037:        import java.text.ParseException;
038:        import java.util.Date;
039:        import java.io.IOException;
040:        import java.io.Serializable;
041:        import java.util.Enumeration;
042:        import java.util.Hashtable;
043:        import java.util.Properties;
044:        import java.util.NoSuchElementException;
045:        import java.util.StringTokenizer;
046:        import java.util.Vector;
047:
048:        /**
049:         * The <code>CookieFilter</code> keeps a
050:         * record of all the browser <i>cookies</i> associated with a given session.
051:         * This can be
052:         * used to make the user's cookies "mobile" as follows.  A user's cookies
053:         * are normally stored with the browser being used, on the user's machine.
054:         * If the user runs a different browser or goes to a different machine, the
055:         * user's cookies will not be there.  Instead, the user can access the web
056:         * via a proxy that keeps all their cookies.  No matter which browser the
057:         * user chooses or machine the user is at, a proxy running with the
058:         * <code>CookieFilter</code> will automatically remember and add in their
059:         * appropriate cookies.  The <code>CookieFilter</code> also supports
060:         * multiple, concurrent users, keeping each user's cookies separate.
061:         * <ul>
062:         * <li> All "Set-Cookie" HTTP response headers are filtered out and saved in
063:         * the local storage.  "Set-Cookie" headers are not transmitted back to the
064:         * client.
065:         *
066:         * <li> Requests from the client have the appropriate "Cookie" headers added.
067:         *
068:         * <li> Users can retrieve, edit, and delete their own cookies.
069:         *
070:         * <li> JavaScript code that sets cookies is <b>not</b> handled by this
071:         * filter, since the code only runs on the client computer, not on the proxy.
072:         * For instance: <code>document.cookie = "userid=778287312"</code>.  Any and
073:         * all Javascript is passed unchanged by this filter.
074:         *
075:         * <li> This filter works in both a session-based and a non-session-based
076:         * fashion.  If sessions are used, cookies are kept with respect to the
077:         * session associated with a user.  If sessions are not used, all cookies
078:         * are kept in one pile for all users.  The latter case is valid if, say,
079:         * only one user is using the proxy running the <code>CookieFilter</code>.
080:         * </ul>
081:         * Properties:
082:         * <dl class=props>
083:         * <dt>session		<dd>The request property to find the session id.
084:         *			Defaults to "SessionID"
085:         * <dt>nosession	<dd>The name of the session to use if no session
086:         *			id is found.  defaults to "common".
087:         * <dt>admin		<dd>A URL prefix that causes status information to
088:         *			be placed in the request properties.
089:         * </dl>
090:         *
091:         * @author	Stephen Uhler (stephen.uhler@sun.com)
092:         * @author	Colin Stevens (colin.stevens@sun.com)
093:         * @version	1.22, 00/12/11
094:         */
095:
096:        public class CookieFilter implements  Filter {
097:            private static final String SESSION = "session";
098:            private static final String NOSESSION = "nosession";
099:            private static final String ADMIN = "admin";
100:
101:            public String session = "SessionID";
102:            public String nosession = "common";
103:            public String admin = "";
104:
105:            String prefix;
106:
107:            public boolean init(Server server, String prefix) {
108:                this .prefix = prefix;
109:
110:                Properties props = server.props;
111:                session = props.getProperty(prefix + SESSION, session);
112:                nosession = props.getProperty(prefix + NOSESSION, nosession);
113:                admin = props.getProperty(prefix + ADMIN, admin);
114:
115:                return true;
116:            }
117:
118:            public boolean respond(Request request) throws IOException {
119:                if ((admin != null) && request.url.startsWith(admin)) {
120:                    return getInfo(request);
121:                }
122:
123:                if (request.url.startsWith("http://")) {
124:                    MimeHeaders headers = request.headers;
125:                    for (int i = headers.size(); --i >= 0;) {
126:                        if ("Cookie".equalsIgnoreCase(headers.getKey(i))) {
127:                            headers.remove(i);
128:                        }
129:                    }
130:
131:                    insertCookies(request);
132:                }
133:                return false;
134:            }
135:
136:            /**
137:             * Saves all "Set-Cookie" headers from the target in the client's local
138:             * storage, then removes those headers before allowing the response to
139:             * go back to the client.  The client never sees cookies on their local
140:             * machine.
141:             */
142:            public boolean shouldFilter(Request request, MimeHeaders headers) {
143:                for (int i = headers.size(); --i >= 0;) {
144:                    String key = headers.getKey(i);
145:                    if (key.equalsIgnoreCase("Set-Cookie")) {
146:                        rememberCookie(request, headers.get(i));
147:                        headers.remove(i);
148:                    }
149:                }
150:
151:                return false;
152:            }
153:
154:            /**
155:             * Returns the original content, since this filter does not change
156:             * content; it changes the headers.
157:             */
158:            public byte[] filter(Request request, MimeHeaders headers,
159:                    byte[] content) {
160:                return content;
161:            }
162:
163:            boolean getInfo(Request request) {
164:                Hashtable h = request.getQueryData();
165:
166:                Hashtable cookies = getSessionCookies(request);
167:                Enumeration e = cookies.keys();
168:
169:                Hashtable sites = new Hashtable();
170:
171:                Properties props = request.props;
172:                String pfx = prefix + "domains.";
173:
174:                while (e.hasMoreElements()) {
175:                    Vector list = (Vector) cookies.get(e.nextElement());
176:                    for (int i = 0; i < list.size(); i++) {
177:                        CookieInfo cookie = (CookieInfo) list.elementAt(i);
178:                        String site = cookie.domain + cookie.path;
179:
180:                        int index = cookie.cookie.indexOf('=');
181:
182:                        String name, value;
183:                        if (index < 0) {
184:                            name = cookie.cookie;
185:                            value = "";
186:                        } else {
187:                            name = cookie.cookie.substring(0, index);
188:                            value = cookie.cookie.substring(index + 1);
189:                        }
190:
191:                        sites.put(site, site);
192:
193:                        site = pfx + site;
194:                        props.put(site, props.getProperty(site, "") + name
195:                                + " ");
196:                        props.put(site + "." + name, value);
197:                    }
198:                }
199:
200:                e = sites.keys();
201:                StringBuffer sb = new StringBuffer();
202:                for (int i = 0; e.hasMoreElements(); i++) {
203:                    sb.append(e.nextElement()).append(' ');
204:                }
205:                props.put(prefix + "domains", sb.toString());
206:                return false;
207:            }
208:
209:            /*
210:             * Remembers a set-cookie request from the content server
211:             *
212:             * look for set-cookie requests from origin server, and remember them.
213:             * They will be of the form:
214:             *   Set-cookie: <cookie>; expires=<date>; path=<path>; domain=<domain>
215:             *    - ';'s are delimeters
216:             *    - all but <cookie> are optional
217:             *    - Cookies have at least on embedded '=' used for id matching
218:             *    - paths a prefix matches on urls (default is /)
219:             *    - domain is a suffix match on hostname field (default origin host)
220:             * Cookies are hashed via domains, eith all cookies for a domain
221:             * stored in a vector, in order of decreasing path size
222:             *
223:             * @param request	The request object from the browser
224:             * @param line	the http header line containing "set-cookie".
225:             */
226:
227:            void rememberCookie(Request request, String line) {
228:                Hashtable cookies = getSessionCookies(request);
229:
230:                Url url = new Url(request.url);
231:                String domain = url.domain();
232:                if (domain.equals("")) {
233:                    domain = url.host();
234:                }
235:
236:                CookieInfo cookie = new CookieInfo(url, line);
237:                Vector list = (Vector) cookies.get(domain);
238:                if (list == null) {
239:                    list = new Vector();
240:                    cookies.put(domain, list);
241:                    request.log(Server.LOG_DIAGNOSTIC,
242:                            "Creating vector for domain: " + domain);
243:                }
244:
245:                int myLength = cookie.path.length();
246:
247:                int i; // cookie index;
248:                for (i = 0; i < list.size(); i++) {
249:                    CookieInfo match = (CookieInfo) list.elementAt(i);
250:                    if (myLength < match.path.length()) {
251:                        break;
252:                    }
253:                    if (cookie.isEquals(match)) {
254:                        list.removeElementAt(i);
255:                        request.log(Server.LOG_DIAGNOSTIC, "Replacing Cookie: "
256:                                + match);
257:                        break;
258:                    }
259:                }
260:                request.log(Server.LOG_DIAGNOSTIC, "Inserting cookie: "
261:                        + cookie);
262:                list.insertElementAt(cookie, i);
263:                // System.out.println("Inserting cookie (" + cookie + ") into: " + cookieList);
264:            }
265:
266:            void insertCookies(Request request) {
267:                Url url = new Url(request.url);
268:                String domain = url.domain();
269:
270:                Hashtable cookies = getSessionCookies(request);
271:                Vector list = (Vector) cookies.get(domain);
272:                if (list == null) {
273:                    return;
274:                }
275:
276:                /*
277:                 * Theory: Multiple cookies that need to be sent to the same site
278:                 * can be send as multiple "Cookie" lines.  Makes sense, since
279:                 * multiple "Set-Cookie" headers are sent to the client as separate
280:                 * lines.
281:                 *
282:                 * Practice: Some HTTP servers instead require that all the cookies
283:                 * are sent in a single "Cookie" line, with each cookie separated
284:                 * by "; ".  Otherwise they don't see anything but the first or last
285:                 * "Cookie" line.
286:                 */
287:                StringBuffer sb = new StringBuffer();
288:
289:                Enumeration e = list.elements();
290:                while (e.hasMoreElements()) {
291:                    CookieInfo match = (CookieInfo) e.nextElement();
292:                    if (match.isMatch(url)) {
293:                        sb.append(match.cookie);
294:                        sb.append("; ");
295:                        match.update();
296:                    }
297:                }
298:                if (sb.length() > 0) {
299:                    /*
300:                     * Remove final "; " at end of "Cookie" HTTP header.  If present,
301:                     * it causes some HTTP servers get confused and generate an error
302:                     * response.  Specifically, this seemed to happen to Microsoft-IIS
303:                     * HTTP servers when issuing a POST to an .asp file.
304:                     */
305:
306:                    sb.setLength(sb.length() - 2);
307:
308:                    request.headers.add("Cookie", sb.toString());
309:                }
310:            }
311:
312:            /**
313:             * Get the session's cookie table
314:             */
315:
316:            Hashtable getSessionCookies(Request request) {
317:                String id = request.props.getProperty(session, nosession);
318:                return (Hashtable) SessionManager.getSession(id,
319:                        CookieFilter.class, Hashtable.class);
320:            }
321:
322:            /**
323:             * Store information about a cookie
324:             */
325:
326:            static class CookieInfo implements  Serializable {
327:                long ctime; // cookie creation time
328:                long mtime; // time of last cookie use
329:                long exptime; // cookie expiration time
330:                int uses; // number of uses
331:                String path; // the path prefix for this cookie
332:                String domain; // the domain of the cookie (including port)
333:                String cookie; // the value of the cookie
334:                String host; // Host setting this cookie (including port)
335:
336:                /**
337:                 * Create a cookie object.
338:                 * @param url: The url for this request, to fill out default stuff
339:                 * @param line The http line containing the cookie request
340:                 */
341:
342:                public CookieInfo(Url url, String line) {
343:                    ctime = mtime = System.currentTimeMillis();
344:                    exptime = 0;
345:                    uses = 0;
346:                    path = "/";
347:                    domain = null;
348:                    host = null;
349:                    cookie = null;
350:
351:                    // Convert the cookie data into a hash table
352:
353:                    StringTokenizer st = new StringTokenizer(line, ";");
354:                    Hashtable cookieData = new Hashtable(5);
355:                    cookieData.put("value", st.nextToken().trim());
356:                    while (st.hasMoreTokens()) {
357:                        String param = st.nextToken().trim();
358:                        int index = param.indexOf('=');
359:                        if (index > 0) {
360:                            cookieData.put(param.substring(0, index)
361:                                    .toLowerCase(), param.substring(index + 1));
362:                        } else {
363:                            cookieData.put(param, "");
364:                        }
365:                    }
366:
367:                    // validate data
368:
369:                    if (cookieData.containsKey("expires")) {
370:                        exptime = expTime((String) cookieData.get("expires"));
371:                    }
372:
373:                    String path = (String) cookieData.get("path");
374:                    if (path != null && !path.startsWith("/")) {
375:                        path = "/" + path;
376:                    }
377:                    if (path != null) {
378:                        this .path = path;
379:                    }
380:
381:                    // compute domain
382:
383:                    host = url.host();
384:                    String domain = (String) cookieData.get("domain");
385:                    if (domain != null) {
386:                        if (domain.indexOf(":") < 0) {
387:                            domain += host.substring(host.indexOf(":"));
388:                        }
389:                        if (url.domain().indexOf(domain) >= 0) {
390:                            this .domain = domain;
391:                        } else {
392:                            // System.out.println("Domain error, using host: " + domain + " !~ " + url.domain());
393:                            this .domain = host;
394:                        }
395:                    } else {
396:                        this .domain = host;
397:                    }
398:                    cookie = (String) cookieData.get("value");
399:                }
400:
401:                /**
402:                 * Generate the cookie info from the string representation
403:                 * This is called with the output of toString(). No error checking
404:                 */
405:
406:                public CookieInfo(String value) {
407:                    try {
408:                        StringTokenizer st = new StringTokenizer(cookie);
409:                        host = st.nextToken();
410:                        domain = st.nextToken();
411:                        path = st.nextToken();
412:                        cookie = st.nextToken();
413:                        host = st.nextToken();
414:                        ctime = Long.parseLong(st.nextToken());
415:                        mtime = Long.parseLong(st.nextToken());
416:                        exptime = Long.parseLong(st.nextToken());
417:                        uses = Integer.parseInt(st.nextToken());
418:                    } catch (NumberFormatException e) {
419:                        throw new RuntimeException(e.toString());
420:                    } catch (NoSuchElementException e) {
421:                        throw new RuntimeException(e.toString());
422:                    }
423:                }
424:
425:                /**
426:                 * Generate string representation - convertable back into a cookie
427:                 */
428:
429:                public String toString() {
430:                    return "<" + cookie + "> " + uses + " " + domain + path
431:                            + "[from " + host + "]";
432:                    /*
433:                    return host + "" + domain + " " + path + " " + cookie + " " +
434:                        host + " " + ctime + " " + mtime + " " + exptime + " " +
435:                        uses;
436:                     */
437:                }
438:
439:                /**
440:                 * See if url matches this cookie
441:                 */
442:
443:                public boolean isMatch(Url url) {
444:                    return url.path().startsWith(path)
445:                            && url.host().endsWith(domain);
446:                }
447:
448:                public void update() {
449:                    mtime = System.currentTimeMillis();
450:                    uses++;
451:                }
452:
453:                /**
454:                 * See if cookies match
455:                 */
456:
457:                public boolean isEquals(CookieInfo cookie) {
458:                    if (!cookie.domain.equals(domain)
459:                            || !cookie.path.equals(path)) {
460:                        return false;
461:                    }
462:                    int index = cookie.cookie.indexOf("=");
463:                    if (index >= 0
464:                            && index == this .cookie.indexOf("=")
465:                            && cookie.cookie.substring(0, index).equals(
466:                                    this .cookie.substring(0, index))) {
467:                        return true;
468:                    } else {
469:                        return false;
470:                    }
471:                }
472:
473:                /**
474:                 * Convert cookie dates into time-stamps
475:                 */
476:
477:                static SimpleDateFormat df = new SimpleDateFormat(
478:                        "EEE, dd-MMM-yy HH:mm:ss z");
479:
480:                public static long expTime(String dateString) {
481:                    try {
482:                        return (df.parse(dateString)).getTime();
483:                    } catch (ParseException e) {
484:                        return 0;
485:                    }
486:                }
487:            }
488:
489:            /**
490:             * This does special stuff, base on our needs
491:             * host: the host + port
492:             * path: the path (starting with /)
493:             * domain: The minimum legal cookie domain for this host
494:             */
495:
496:            static class Url {
497:                private String host = null; // the host part (excluding port)
498:                private String domain = null; // minumum domain for cookies
499:                private String path = null; // path part
500:                private String port; // the port #
501:
502:                /**
503:                 * Create a url object from a url string
504:                 * @param url	The http url string
505:                 *			("" if none)
506:                 *
507:                 */
508:
509:                public Url(String url) {
510:                    String host = url.substring("http://".length());
511:                    int index = host.indexOf("/");
512:                    if (index >= 0) {
513:                        this .path = host.substring(index);
514:                        this .host = host.substring(0, index).toLowerCase();
515:                    } else {
516:                        this .path = "/";
517:                        this .host = host.toLowerCase();
518:                    }
519:                    index = host.indexOf(":");
520:                    if (index > 0) {
521:                        this .host = host.substring(0, index);
522:                        port = host.substring(index + 1);
523:                    } else {
524:                        port = "80";
525:                    }
526:                }
527:
528:                public String host() {
529:                    return host + ":" + port;
530:                }
531:
532:                public String path() {
533:                    return path;
534:                }
535:
536:                /**
537:                 * Retrieve the minimum domain spec for a host.  Must have port info
538:                 * @param host	The host name (e.g. foo.x.y.com:80)
539:                 * @returns		min. cookie domain (e.g. y.com:80)
540:                 */
541:
542:                public static Vector specialDomains = new Vector();
543:                static {
544:                    specialDomains.addElement("com");
545:                    specialDomains.addElement("edu");
546:                    specialDomains.addElement("net");
547:                    specialDomains.addElement("org");
548:                    specialDomains.addElement("gov");
549:                    specialDomains.addElement("mil");
550:                    specialDomains.addElement("int");
551:                }
552:
553:                /**
554:                 * Compute the Minimum cookie domain.
555:                 * @param default	The string to tack onto the host name, 
556:                 *			if it only has 1 dot
557:                 */
558:
559:                public String domain() {
560:                    if (domain != null) {
561:                        return domain;
562:                    }
563:                    StringTokenizer st = new StringTokenizer(host, ".");
564:                    int dots = st.countTokens() - 1;
565:                    // System.out.println("COMPUTING DOMAIN FOR: " + host + " (" + dots + ") dots");
566:                    switch (dots) {
567:                    case 0: // no dots - invalid domain
568:                    case 1: // 1 dot - invalid domain
569:                        domain = "";
570:                        System.out.println("Domain error: " + host);
571:                        break;
572:                    case 2: // OK if special suffix
573:                        st.nextToken();
574:                        String middle = st.nextToken();
575:                        String right = st.nextToken();
576:                        if (specialDomains.contains(right)) {
577:                            domain = "." + middle + "." + right + ":" + port;
578:                        } else {
579:                            System.out.println("Domain error: " + host);
580:                            domain = "";
581:                        }
582:                        break;
583:                    default: // 3 or more dots, always ok, leave .xxx.yyy.zzz
584:                        while (dots-- > 2) {
585:                            st.nextToken();
586:                        }
587:                        domain = "";
588:                        String maybe = st.nextToken();
589:                        String next = "";
590:                        while (st.hasMoreTokens()) {
591:                            next = st.nextToken();
592:                            domain += "." + next;
593:                        }
594:                        domain += ":" + port;
595:                        if (!specialDomains.contains(next)) {
596:                            domain = "." + maybe + domain;
597:                        }
598:                    }
599:                    return domain;
600:                }
601:
602:                public String toString() {
603:                    return host + path + " (" + domain + ")";
604:                }
605:            }
606:        }
607:
608:        /*
609:
610:         Initial sign-on stragegy
611:         1) have proxy-authentication
612:         a) have hashtable entry - > ok
613:         b) don't have hash-table entry ->ask for re-authentication
614:         2) go to web-server sign-on page
615:         - fill out form userid/password
616:         a) unused ID - make entry in cookie table, explain how to do proxy
617:         b) used ID - make-em use another one
618:
619:         Misc
620:         - keep used id's in a separate hash table
621:
622:         Investigate: application/x-ns-proxy-autoconfig for setting
623:         proxy automatically
624:
625:         function FindProxyForURL(url, host) {
626:         return "PROXY ???.Sun.COM:8080;"
627:         }
628:         */
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.