Source Code Cross Referenced for ServeTextFile.java in  » J2EE » Expresso » com » jcorporate » expresso » ext » controller » 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 » J2EE » Expresso » com.jcorporate.expresso.ext.controller 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* ====================================================================
002:         * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003:         *
004:         * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005:         *
006:         * Redistribution and use in source and binary forms, with or without
007:         * modification, are permitted provided that the following conditions
008:         * are met:
009:         *
010:         * 1. Redistributions of source code must retain the above copyright
011:         *    notice, this list of conditions and the following disclaimer.
012:         *
013:         * 2. Redistributions in binary form must reproduce the above copyright
014:         *    notice, this list of conditions and the following disclaimer in
015:         *    the documentation and/or other materials provided with the
016:         *    distribution.
017:         *
018:         * 3. The end-user documentation included with the redistribution,
019:         *    if any, must include the following acknowledgment:
020:         *       "This product includes software developed by Jcorporate Ltd.
021:         *        (http://www.jcorporate.com/)."
022:         *    Alternately, this acknowledgment may appear in the software itself,
023:         *    if and wherever such third-party acknowledgments normally appear.
024:         *
025:         * 4. "Jcorporate" and product names such as "Expresso" must
026:         *    not be used to endorse or promote products derived from this
027:         *    software without prior written permission. For written permission,
028:         *    please contact info@jcorporate.com.
029:         *
030:         * 5. Products derived from this software may not be called "Expresso",
031:         *    or other Jcorporate product names; nor may "Expresso" or other
032:         *    Jcorporate product names appear in their name, without prior
033:         *    written permission of Jcorporate Ltd.
034:         *
035:         * 6. No product derived from this software may compete in the same
036:         *    market space, i.e. framework, without prior written permission
037:         *    of Jcorporate Ltd. For written permission, please contact
038:         *    partners@jcorporate.com.
039:         *
040:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043:         * DISCLAIMED.  IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044:         * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045:         * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046:         * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051:         * SUCH DAMAGE.
052:         * ====================================================================
053:         *
054:         * This software consists of voluntary contributions made by many
055:         * individuals on behalf of the Jcorporate Ltd. Contributions back
056:         * to the project(s) are encouraged when you make modifications.
057:         * Please send them to support@jcorporate.com. For more information
058:         * on Jcorporate Ltd. and its products, please see
059:         * <http://www.jcorporate.com/>.
060:         *
061:         * Portions of this software are based upon other open source
062:         * products and are subject to their respective licenses.
063:         */
064:
065:        package com.jcorporate.expresso.ext.controller;
066:
067:        import com.jcorporate.expresso.core.controller.ControllerException;
068:        import com.jcorporate.expresso.core.controller.ControllerRequest;
069:        import com.jcorporate.expresso.core.controller.ControllerResponse;
070:        import com.jcorporate.expresso.core.controller.DBController;
071:        import com.jcorporate.expresso.core.controller.ServletControllerRequest;
072:        import com.jcorporate.expresso.core.controller.State;
073:        import com.jcorporate.expresso.core.misc.ConfigManager;
074:        import com.jcorporate.expresso.core.security.filters.Filter;
075:        import org.apache.log4j.Logger;
076:
077:        import javax.servlet.Servlet;
078:        import javax.servlet.http.HttpServletRequest;
079:        import javax.servlet.http.HttpServletResponse;
080:        import javax.servlet.http.HttpSession;
081:        import java.io.BufferedInputStream;
082:        import java.io.ByteArrayOutputStream;
083:        import java.io.File;
084:        import java.io.FileInputStream;
085:        import java.io.FileNotFoundException;
086:        import java.io.IOException;
087:        import java.io.OutputStream;
088:        import java.io.PrintStream;
089:        import java.io.PushbackInputStream;
090:        import java.util.Date;
091:        import java.util.Hashtable;
092:        import java.util.Vector;
093:
094:        /**
095:         * This controller is used to serve up text files.  It helps provide a particularly
096:         * useful mechanism for tutorial purposes.
097:         * <p><b>PLEASE NOTE!</b>: It is DEFINITELY not recommended that this controller
098:         * should be opened up to anybody but the Administrator in a production
099:         * environment!  It could be used by malicious attackers to cause the system
100:         * to cough up password files, and many other things that they would not normally
101:         * have access to </p>
102:         *
103:         * @author Michael Rimov - Adapted from code created by Peter Pilgrim.
104:         */
105:
106:        public class ServeTextFile extends DBController {
107:
108:            /**
109:             * List of locations to search for this file
110:             */
111:            static private Vector rootDirList = new Vector();
112:
113:            /**
114:             * Our Log4J logger.  See <a href="http://jakarta.apache.org/log4j/">The Log4j Website</a>
115:             * for more information.
116:             */
117:            transient static private Logger log = Logger
118:                    .getLogger("expresso.ext.controller.ServeTextFile");
119:
120:            /**
121:             * A filter that efficiently removes (hopefully) all URL trickery that could
122:             * result in unnecessary security problems
123:             */
124:            transient private static Filter fileNameFilter = null;
125:
126:            /**
127:             * A filter that efficiently goes through a string and color codes the
128:             * appropriate stuff for nice eye candy
129:             */
130:            transient private static Filter javaCodeFilter = null;
131:
132:            //--------------------------------------------------------------
133:            //Here we have contstants for color coding java files
134:            //--------------------------------------------------------------
135:            public final static String DEFAULT_RESERVED_KEYWORD_COLOR = "#9900CC";
136:            public final static String DEFAULT_PRIMITIVE_VAR_COLOR = "#008000";
137:            public final static String DEFAULT_SPECIAL_KEYWORD_COLOR = "#4682B4"; // Light Blue
138:            public final static String DEFAULT_SINGLE_QUOTE_COLOR = "#0066FF";
139:            public final static String DEFAULT_DOUBLE_QUOTE_COLOR = "#0000CC";
140:            public final static String DEFAULT_CSTYLE_COMMENT_COLOR = "#CC0033";
141:            public final static String DEFAULT_CPLUS_COMMENT_COLOR = "B22222"; // firebrick
142:            public final static String DEFAULT_DECIMAL_NUMBER_COLOR = "#996600";
143:            protected final static String reservedKeywordColor = DEFAULT_RESERVED_KEYWORD_COLOR;
144:            protected final static String primitiveVarColor = DEFAULT_PRIMITIVE_VAR_COLOR;
145:            protected final static String specialKeywordColor = DEFAULT_SPECIAL_KEYWORD_COLOR;
146:            protected final static String singleQuoteColor = DEFAULT_SINGLE_QUOTE_COLOR;
147:            protected final static String doubleQuoteColor = DEFAULT_DOUBLE_QUOTE_COLOR;
148:            protected final static String cstyleCommentColor = DEFAULT_CSTYLE_COMMENT_COLOR;
149:            protected final static String cplusCommentColor = DEFAULT_CPLUS_COMMENT_COLOR;
150:            protected final static String decimalNumberColor = DEFAULT_DECIMAL_NUMBER_COLOR;
151:
152:            /**
153:             * Class used a structure to pass info around calls
154:             */
155:            class Parameters {
156:                HttpServletRequest req; // Request
157:                HttpServletResponse res; // Response
158:                HttpSession session; // Session
159:                String inputFilename; // Input Filename
160:                String filename; // Resolved Filename
161:                PrintStream out; // Output
162:            }
163:
164:            /**
165:             * A simple structure class to map a Java
166:             * reserved keyword to a HTML colour code
167:             */
168:            static class ReservedWord {
169:                String keyword;
170:                String htmlcolor;
171:
172:                ReservedWord(String keyword, String htmlcolor) {
173:                    this .keyword = keyword;
174:                    this .htmlcolor = htmlcolor;
175:                }
176:            }
177:
178:            static protected final ServeTextFile.ReservedWord[] java_reserved_keywords = {
179:                    new ReservedWord("class", DEFAULT_RESERVED_KEYWORD_COLOR),
180:                    new ReservedWord("interface",
181:                            DEFAULT_RESERVED_KEYWORD_COLOR),
182:                    new ReservedWord("extends", DEFAULT_RESERVED_KEYWORD_COLOR),
183:                    new ReservedWord("implements",
184:                            DEFAULT_RESERVED_KEYWORD_COLOR),
185:                    new ReservedWord("goto", DEFAULT_RESERVED_KEYWORD_COLOR),
186:                    new ReservedWord("for", DEFAULT_RESERVED_KEYWORD_COLOR),
187:                    new ReservedWord("return", DEFAULT_RESERVED_KEYWORD_COLOR),
188:                    new ReservedWord("if", DEFAULT_RESERVED_KEYWORD_COLOR),
189:                    new ReservedWord("then", DEFAULT_RESERVED_KEYWORD_COLOR),
190:                    new ReservedWord("else", DEFAULT_RESERVED_KEYWORD_COLOR),
191:                    new ReservedWord("while", DEFAULT_RESERVED_KEYWORD_COLOR),
192:                    new ReservedWord("do", DEFAULT_RESERVED_KEYWORD_COLOR),
193:                    new ReservedWord("switch", DEFAULT_RESERVED_KEYWORD_COLOR),
194:                    new ReservedWord("case", DEFAULT_RESERVED_KEYWORD_COLOR),
195:                    new ReservedWord("default", DEFAULT_RESERVED_KEYWORD_COLOR),
196:                    new ReservedWord("instanceof",
197:                            DEFAULT_RESERVED_KEYWORD_COLOR),
198:                    new ReservedWord("package", DEFAULT_RESERVED_KEYWORD_COLOR),
199:                    new ReservedWord("import", DEFAULT_RESERVED_KEYWORD_COLOR),
200:                    new ReservedWord("public", DEFAULT_RESERVED_KEYWORD_COLOR),
201:                    new ReservedWord("protected",
202:                            DEFAULT_RESERVED_KEYWORD_COLOR),
203:                    new ReservedWord("private", DEFAULT_RESERVED_KEYWORD_COLOR),
204:                    new ReservedWord("super", DEFAULT_RESERVED_KEYWORD_COLOR),
205:                    new ReservedWord("new", DEFAULT_RESERVED_KEYWORD_COLOR),
206:                    new ReservedWord("this", DEFAULT_RESERVED_KEYWORD_COLOR),
207:                    new ReservedWord("try", DEFAULT_RESERVED_KEYWORD_COLOR),
208:                    new ReservedWord("catch", DEFAULT_RESERVED_KEYWORD_COLOR),
209:                    new ReservedWord("throw", DEFAULT_RESERVED_KEYWORD_COLOR),
210:                    new ReservedWord("throws", DEFAULT_RESERVED_KEYWORD_COLOR),
211:                    new ReservedWord("final", DEFAULT_RESERVED_KEYWORD_COLOR),
212:                    new ReservedWord("abstract", DEFAULT_RESERVED_KEYWORD_COLOR),
213:                    new ReservedWord("native", DEFAULT_RESERVED_KEYWORD_COLOR),
214:                    new ReservedWord("static", DEFAULT_RESERVED_KEYWORD_COLOR),
215:                    new ReservedWord("transient",
216:                            DEFAULT_RESERVED_KEYWORD_COLOR),
217:                    new ReservedWord("void", DEFAULT_PRIMITIVE_VAR_COLOR),
218:                    new ReservedWord("boolean", DEFAULT_PRIMITIVE_VAR_COLOR),
219:                    new ReservedWord("char", DEFAULT_PRIMITIVE_VAR_COLOR),
220:                    new ReservedWord("int", DEFAULT_PRIMITIVE_VAR_COLOR),
221:                    new ReservedWord("short", DEFAULT_PRIMITIVE_VAR_COLOR),
222:                    new ReservedWord("long", DEFAULT_PRIMITIVE_VAR_COLOR),
223:                    new ReservedWord("float", DEFAULT_PRIMITIVE_VAR_COLOR),
224:                    new ReservedWord("double", DEFAULT_PRIMITIVE_VAR_COLOR),
225:                    new ReservedWord("null", DEFAULT_SPECIAL_KEYWORD_COLOR),
226:                    new ReservedWord("true", DEFAULT_SPECIAL_KEYWORD_COLOR),
227:                    new ReservedWord("false", DEFAULT_SPECIAL_KEYWORD_COLOR) };
228:
229:            protected static Hashtable fast_keyword_map = null;
230:
231:            public ServeTextFile() {
232:                State s = new State("serveTextFile", "Serve A Text File");
233:                s.addRequiredParameter("filename");
234:                this .addState(s);
235:
236:                s = new State("serveJavaFile", "Serve a Java File");
237:                s.addRequiredParameter("filename");
238:                this .addState(s);
239:
240:                String baseRootDir = ConfigManager.getWebAppDir()
241:                        + "/WEB-INF/src";
242:                rootDirList.add(baseRootDir);
243:                baseRootDir = ConfigManager.getWebAppDir();
244:                rootDirList.add(baseRootDir);
245:
246:                if (fileNameFilter == null) {
247:                    //We use this to filter out all URL trickery that we can think of
248:                    fileNameFilter = new Filter(new String[] { "|", "..", ">",
249:                            "<" }, new String[] { "", "", "", "" });
250:                }
251:
252:                //
253:                //Initialize the Java keyword map
254:                //
255:                if (fast_keyword_map == null) {
256:                    fast_keyword_map = new Hashtable(
257:                            java_reserved_keywords.length);
258:
259:                    for (int k = 0; k < java_reserved_keywords.length; ++k) {
260:                        fast_keyword_map.put(java_reserved_keywords[k].keyword,
261:                                java_reserved_keywords[k]);
262:                    }
263:                }
264:
265:                this .setInitialState("serveJavaFile");
266:                this 
267:                        .setSchema(com.jcorporate.expresso.core.ExpressoSchema.class);
268:            }
269:
270:            /**
271:             * Serves up a basic text file as specified by the parameter.  Our goal
272:             * here is to provide something that is reasonably secure in that we remove
273:             * all URL trickery.
274:             *
275:             * @param request  The <code>ControllerRequest</code> Object
276:             * @param response The <code>ControllerResponse</code> Object
277:             * @return ControllerResponse
278:             * @throws ControllerException upon error
279:             */
280:            protected ControllerResponse runServeTextFileState(
281:                    ControllerRequest request, ControllerResponse response)
282:                    throws ControllerException {
283:
284:                ServletControllerRequest servRequest;
285:                try {
286:                    servRequest = (ServletControllerRequest) request;
287:                } catch (ClassCastException ex) {
288:                    throw new ControllerException(
289:                            "This controller must be run within only a http environment");
290:                }
291:
292:                //
293:                //ControllerRequest contains pointers to low level HttpServlet stuff
294:                //if it can be downcast to ServletControllerRequest
295:                //
296:                HttpServletRequest req = (HttpServletRequest) servRequest
297:                        .getServletRequest();
298:                HttpServletResponse res = (HttpServletResponse) servRequest
299:                        .getServletResponse();
300:                Servlet servlet = servRequest.getCallingServlet();
301:
302:                String fileSep = System.getProperty("file.separator");
303:                String inputFilename = req.getParameter("filename");
304:
305:                try {
306:
307:                    // Append the input filename to the root directory
308:                    if (inputFilename == null) {
309:                        throw new ControllerException(
310:                                "filename parameter is not set.");
311:                    }
312:
313:                    //
314:                    //By running it throuhg the filter, we should be able to remove all
315:                    //sorts of URL trickery that occurs by people sending urls like a
316:                    //URL encoded version of:
317:                    //mail hacker@hotmail.com -s Password! < cat /../../../etc/passwd
318:                    //(And YES, this kind of attack happens often!)
319:                    //
320:                    inputFilename = fileNameFilter.stripFilter(inputFilename);
321:
322:                    if (inputFilename.length() == 0) {
323:                        throw new ControllerException(
324:                                "filename parameter is not set.");
325:                    }
326:
327:                    if (!(inputFilename.endsWith(".java")
328:                            || inputFilename.endsWith(".cpp")
329:                            || inputFilename.endsWith(".cc")
330:                            || inputFilename.endsWith(".jpg")
331:                            || inputFilename.endsWith(".jpeg")
332:                            || inputFilename.endsWith(".png")
333:                            || inputFilename.endsWith(".jsp")
334:                            || inputFilename.endsWith(".txt") || inputFilename
335:                            .endsWith(".wm"))) {
336:                        throw new ControllerException(
337:                                "Sorry, it is forbidden to serve this type of file.");
338:                    }
339:
340:                    boolean fileWasServed = false;
341:
342:                    for (int k = 0; k < rootDirList.size(); ++k) {
343:                        String rootDir = (String) rootDirList.elementAt(k);
344:                        File file = new File(rootDir, inputFilename);
345:                        String filename = file.getPath();
346:
347:                        if (file.exists()) {
348:                            if (!file.canRead()) {
349:                                throw new IOException("not readable filename:`"
350:                                        + inputFilename + "'");
351:                            }
352:                            if (file.isDirectory()) {
353:                                throw new IOException(
354:                                        "cannot serve a directory as filename:`"
355:                                                + inputFilename + "'");
356:                            }
357:
358:                            fileWasServed = true; /*!*/
359:                            //
360:                            //Set this value to indicate we don't want to do a normal struts forward
361:                            //
362:                            response.setCustomResponse(true);
363:
364:                            // Get the MIME type to return the browser
365:                            String contentType = servlet.getServletConfig()
366:                                    .getServletContext().getMimeType(filename);
367:
368:                            if (contentType == null) {
369:                                contentType = "text/plain";
370:                            }
371:
372:                            if (log.isInfoEnabled()) {
373:                                log
374:                                        .info("BasicFileServeServlet: Serving file:`"
375:                                                + filename
376:                                                + "'  type:"
377:                                                + contentType);
378:                            }
379:
380:                            // Create a buffer for the file contents
381:                            ByteArrayOutputStream baos = new ByteArrayOutputStream(
382:                                    8192);
383:
384:                            // Extract the file contents
385:                            returnFile(filename, baos);
386:
387:                            // Provided no I/O exception occurred, pump the buffered
388:                            // data to the browser now.
389:                            OutputStream out = res.getOutputStream();
390:                            res.setContentType(contentType);
391:                            baos.writeTo(out);
392:                            out.flush();
393:                            out.close();
394:                            break;
395:                        }
396:                    }
397:                    if (!fileWasServed) {
398:                        throw new FileNotFoundException("no such file: `"
399:                                + inputFilename + "'");
400:                    }
401:                } catch (FileNotFoundException ex) {
402:                    log.error("FileNotFoundException locating file file", ex);
403:                    throw new ControllerException(
404:                            "FileNotFoundException Error transferring file", ex);
405:                } catch (java.io.IOException ioe) {
406:                    log.error("I/O Error transferring file", ioe);
407:                    throw new ControllerException(
408:                            "I/O Error transferring file", ioe);
409:                }
410:
411:                return response;
412:            }
413:
414:            protected void returnFile(String filename, OutputStream out)
415:                    throws FileNotFoundException, IOException {
416:                FileInputStream fis = null;
417:
418:                try {
419:                    fis = new FileInputStream(filename);
420:
421:                    byte[] buffer = new byte[8192];
422:                    int bytesRead;
423:
424:                    while ((bytesRead = fis.read(buffer)) != -1) {
425:                        out.write(buffer, 0, bytesRead);
426:                    }
427:                } finally {
428:                    if (fis != null) {
429:                        fis.close();
430:                    }
431:                }
432:            }
433:
434:            /**
435:             * Serves up a java source file as specified by the parameter.  This
436:             * state is different from that of servTextFile in that it color codes
437:             * all the keywords, etc in the java file.
438:             * <p/>
439:             * Our goal here is to provide something that is reasonably secure in that we remove
440:             * all URL trickery, and we also only serve up NON source code files.  Again,
441:             * this should be NOT used in a production environment and only exists for
442:             * teaching purposes.
443:             *
444:             * @param request  The <code>ControllerRequest</code> Object
445:             * @param response The <code>ControllerResponse</code> Object
446:             * @return ControllerResponse
447:             * @throws ControllerException upon error
448:             */
449:            protected ControllerResponse runServeJavaFileState(
450:                    ControllerRequest request, ControllerResponse response)
451:                    throws ControllerException {
452:                ServletControllerRequest servRequest;
453:                try {
454:                    servRequest = (ServletControllerRequest) request;
455:                } catch (ClassCastException ex) {
456:                    throw new ControllerException(
457:                            "This controller must be run within only a http environment");
458:                }
459:
460:                //
461:                //ControllerRequest contains pointers to low level HttpServlet stuff
462:                //if it can be downcast to ServletControllerRequest
463:                //
464:                HttpServletRequest req = (HttpServletRequest) servRequest
465:                        .getServletRequest();
466:                HttpSession session = req.getSession(true);
467:                HttpServletResponse res = (HttpServletResponse) servRequest
468:                        .getServletResponse();
469:                Servlet servlet = servRequest.getCallingServlet();
470:
471:                String fileSep = System.getProperty("file.separator");
472:                String inputFilename = req.getParameter("filename");
473:
474:                try {
475:                    // Append the input filename to the root directory
476:                    if (inputFilename == null) {
477:                        throw new ControllerException(
478:                                "filename parameter is not set.");
479:                    }
480:
481:                    // Append the input filename to the root directory
482:                    if (inputFilename == null) {
483:                        throw new ControllerException(
484:                                "filename parameter is not set.");
485:                    }
486:
487:                    //
488:                    //By running it throuhg the filter, we should be able to remove all
489:                    //sorts of URL trickery that occurs by people sending urls like a
490:                    //URL encoded version of:
491:                    //mail hacker@hotmail.com -s Password! < cat /../../../etc/passwd
492:                    //(And YES, this kind of attack happens often!)
493:                    //
494:                    inputFilename = fileNameFilter.stripFilter(inputFilename);
495:
496:                    if (inputFilename.length() == 0) {
497:                        throw new ControllerException(
498:                                "filename parameter is not set.");
499:                    }
500:
501:                    if (!(inputFilename.endsWith(".java"))) {
502:                        throw new ControllerException(
503:                                "Sorry, it is forbidden to serve this type of file. This servlet only serves Java source files!");
504:                    }
505:
506:                    boolean fileWasServed = false;
507:
508:                    for (int k = 0; k < rootDirList.size(); ++k) {
509:                        String rootDir = (String) rootDirList.elementAt(k);
510:                        File file = new File(rootDir, inputFilename);
511:                        String filename = file.getPath();
512:
513:                        if (file.exists()) {
514:                            if (!file.canRead()) {
515:                                throw new IOException("not readable filename:`"
516:                                        + inputFilename + "'");
517:                            }
518:                            if (file.isDirectory()) {
519:                                throw new IOException(
520:                                        "cannot serve a directory as filename:`"
521:                                                + inputFilename + "'");
522:                            }
523:
524:                            fileWasServed = true; /*!*/
525:
526:                            //
527:                            //Set this value to indicate we don't want to do a normal struts forward
528:                            //
529:                            response.setCustomResponse(true);
530:
531:                            // Get the MIME type to return the browser
532:                            String contentType = "text/html";
533:                            if (log.isInfoEnabled()) {
534:                                log.info("JavaFileServeServlet: Serving file:`"
535:                                        + filename + "'  type:" + contentType);
536:                            }
537:
538:                            // Create a buffer for the file contents
539:                            ByteArrayOutputStream baos = new ByteArrayOutputStream(
540:                                    32678);
541:                            PrintStream prs = new PrintStream(baos);
542:
543:                            // Set up parameter structure
544:                            Parameters params = new Parameters();
545:                            params.req = req;
546:                            params.res = res;
547:                            params.session = session;
548:                            params.inputFilename = inputFilename;
549:                            params.filename = filename;
550:                            params.out = prs;
551:
552:                            // Extract the file contents and format HTML
553:                            returnHTMLFormattedFile(params);
554:                            prs.flush(); // MAKE SURE!!!
555:
556:                            // Provided no I/O exception occurred, pump the buffered
557:                            // data to the browser now.
558:                            OutputStream out = res.getOutputStream();
559:                            res.setContentType(contentType);
560:                            baos.writeTo(out);
561:                            out.flush();
562:                            out.close();
563:                            break;
564:                        }
565:                    }
566:                    if (!fileWasServed) {
567:                        throw new FileNotFoundException("no such file: `"
568:                                + inputFilename + "'");
569:                    }
570:
571:                } catch (FileNotFoundException ex) {
572:                    log.error("FileNotFoundException locating file file", ex);
573:                    throw new ControllerException(
574:                            "FileNotFoundException Error transferring file", ex);
575:                } catch (java.io.IOException ioe) {
576:                    log.error("I/O Error transferring file", ioe);
577:                    throw new ControllerException(
578:                            "I/O Error transferring file", ioe);
579:                }
580:
581:                return response;
582:            }
583:
584:            public void returnHTMLFormattedFile(Parameters params)
585:                    throws FileNotFoundException, IOException {
586:                writeHeader(params);
587:                writeContent(params);
588:                writeFooter(params);
589:            }
590:
591:            public void writeHeader(Parameters params)
592:                    throws FileNotFoundException, IOException {
593:                PrintStream out = params.out;
594:                out.println("<html>");
595:                out.println("<head>");
596:                out.println("<title>Java Source File: `" + params.inputFilename
597:                        + "'</title>");
598:                out.println("<meta name=\"generator\" value=\""
599:                        + getClass().getName() + "\" >");
600:                out.println("<meta name=\"published_date\" value=\""
601:                        + new Date() + "\" >");
602:                out.println("</head>");
603:                out.println("<body bgcolor=\"#FFFFFF\" >");
604:
605:                File file = new File(params.filename);
606:                out
607:                        .println("<p><font face=\"Lucida, Georgia, Arial,Helvetica\" size=\"-1\" color=\"#000000\" >filename: <b>"
608:                                + params.inputFilename + "</b><br>");
609:                out.println("file size: <b>" + file.length() + "</b><br>");
610:                out.println("last modified: <b>"
611:                        + new Date(file.lastModified()) + "</b><br>");
612:                out.println("</font></p>");
613:            }
614:
615:            protected void writeFooter(Parameters params)
616:                    throws FileNotFoundException, IOException {
617:                PrintStream out = params.out;
618:                out.println("</body>");
619:                out.println("</html>");
620:            }
621:
622:            protected void writeContent(Parameters params)
623:                    throws FileNotFoundException, IOException {
624:                PrintStream out = params.out;
625:                FileInputStream fis = null;
626:                BufferedInputStream bis = null;
627:                PushbackInputStream pis = null;
628:                boolean insideDQuote = false;
629:                boolean insideSQuote = false;
630:                boolean cstyleComment = false;
631:
632:                try {
633:
634:                    // Try to open a file stream to the Java source file
635:                    fis = new FileInputStream(params.filename);
636:                    bis = new BufferedInputStream(fis, 8192);
637:                    pis = new PushbackInputStream(bis, 256);
638:
639:                    // Write start of the content section
640:                    out.println("<pre>");
641:                    out
642:                            .println("<font face=\"Courier New, Monospace, Helvetica, San-serif\" size=\"+0\" color=\"#000000\" >");
643:
644:                    int c1 = pis.read();
645:
646:                    while (c1 >= 0) {
647:
648:                        // Pipe through any blank spaces
649:                        while (Character.isWhitespace((char) c1)) {
650:                            out.print((char) c1);
651:                            c1 = pis.read();
652:                        }
653:                        if (c1 < 0) {
654:
655:                            // EOF - End of file reached
656:                            break;
657:                        }
658:
659:                        if (log.isDebugEnabled()) {
660:                            System.out.print((char) c1);
661:                        }
662:
663:                        if (c1 == '/') {
664:                            int c2 = pis.read();
665:
666:                            if (c2 == '/') {
667:
668:                                // Directly hand 'C++' style comment
669:                                out.print("<font color=\"" + cplusCommentColor
670:                                        + "\">//");
671:
672:                                if (log.isDebugEnabled()) {
673:                                    System.out.println("C++ comment");
674:                                }
675:
676:                                c2 = pis.read();
677:
678:                                while (c2 != -1 && c2 != '\n') {
679:                                    out.print(substituteEntity((char) c2));
680:                                    c2 = pis.read();
681:                                }
682:
683:                                out.print("</font>\n");
684:                                c1 = pis.read(); // READ NEXT
685:                                continue;
686:                            } else if (c2 == '*') {
687:
688:                                // Start of 'C' style comment
689:                                if (log.isDebugEnabled()) {
690:                                    System.out.println("C comment start");
691:                                }
692:                                cstyleComment = true;
693:                                out.print("<font color=\"" + cstyleCommentColor
694:                                        + "\">/*");
695:                                c1 = pis.read(); // READ NEXT
696:                                continue;
697:                            } else {
698:                                pis.unread(c2);
699:                            }
700:                        } else if (c1 == '*') {
701:                            int c2 = pis.read();
702:
703:                            if (c2 == '/') {
704:
705:                                // End of 'C' style comment
706:                                if (log.isDebugEnabled()) {
707:                                    System.out.println("C comment end"); // FIXME:
708:                                }
709:
710:                                cstyleComment = false;
711:                                out.print("*/</font>");
712:                                c1 = pis.read(); // READ NEXT
713:                                continue;
714:                            } else {
715:                                pis.unread(c2);
716:                            }
717:                        }
718:                        if (c1 == '\"' && !cstyleComment) {
719:                            if (!insideDQuote) {
720:                                out.print("<font color=\"" + doubleQuoteColor
721:                                        + "\">&quot;");
722:                            } else {
723:                                out.print("&quot;</font>");
724:                            }
725:
726:                            insideDQuote = !insideDQuote;
727:                            if (log.isDebugEnabled()) {
728:                                System.out.println("double quotes:"
729:                                        + insideDQuote);
730:                            }
731:                        } else if (c1 == '\'' && !cstyleComment
732:                                && !insideDQuote) {
733:                            if (!insideSQuote) {
734:                                out.print("<font color=\"" + singleQuoteColor
735:                                        + "\">&#039;");
736:                            } else {
737:                                out.print("&#039;</font>");
738:                            }
739:
740:                            insideSQuote = !insideSQuote;
741:                            if (log.isDebugEnabled()) {
742:                                System.out.println("single quotes:"
743:                                        + insideSQuote);
744:                            }
745:                        } else if (Character.isDigit((char) c1)
746:                                && !cstyleComment && !insideSQuote
747:                                && !insideDQuote) {
748:
749:                            // Handle parsing of decimal or floating
750:                            // formatting numbers here
751:                            boolean valid = true;
752:                            StringBuffer tokenBuffer = new StringBuffer();
753:                            tokenBuffer.append((char) c1);
754:
755:                            int c2 = pis.read();
756:
757:                            while (Character.isDigit((char) c2)) {
758:                                tokenBuffer.append((char) c2);
759:                                c2 = pis.read();
760:                            }
761:
762:                            pis.mark(256);
763:                            if (log.isDebugEnabled()) {
764:                                System.out.println("(1) token=`"
765:                                        + tokenBuffer.toString() + "' (c2:"
766:                                        + c2 + "<" + (char) c2 + ")");
767:                            }
768:
769:                            if (c2 == '.') {
770:                                tokenBuffer.append((char) c2);
771:                                c2 = pis.read();
772:                                if (log.isDebugEnabled()) {
773:                                    System.out.println("(2) token=`"
774:                                            + tokenBuffer.toString() + "' (c2:"
775:                                            + c2 + "<" + (char) c2 + ")");
776:                                }
777:
778:                                if (c2 == 'e' || c2 == 'E') {
779:                                    tokenBuffer.append((char) c2);
780:                                    c2 = pis.read();
781:                                    if (log.isDebugEnabled()) {
782:                                        System.out.println("(3) token=`"
783:                                                + tokenBuffer.toString()
784:                                                + "' (c2:" + c2 + "<"
785:                                                + (char) c2 + ")");
786:                                    }
787:                                }
788:
789:                                System.out.println("(4) token=`"
790:                                        + tokenBuffer.toString() + "' (c2:"
791:                                        + c2 + "<" + (char) c2 + ")");
792:
793:                                if (c2 == '+' || c2 == '-') {
794:                                    tokenBuffer.append((char) c2);
795:                                    c2 = pis.read();
796:                                }
797:                                if (Character.isDigit((char) c2)) {
798:                                    while (Character.isDigit((char) c2)) {
799:                                        tokenBuffer.append((char) c2);
800:                                        c2 = pis.read();
801:                                    }
802:                                } else {
803:
804:                                    // Sorry, not a valid floating point number
805:                                    // `[0-9]+\.(E|e)?(+|-)?[0-9]+'
806:                                    valid = false;
807:                                    pis.reset();
808:                                }
809:                            }
810:
811:                            pis.unread(c2); // Pushback the last unread!
812:
813:                            if (valid) {
814:                                out.print("<font color=\"" + decimalNumberColor
815:                                        + "\" >");
816:                            }
817:
818:                            out.print(tokenBuffer.toString());
819:
820:                            if (valid) {
821:                                out.print("</font>");
822:                            }
823:                        } else if (Character.isLetter((char) c1)
824:                                && !cstyleComment && !insideSQuote
825:                                && !insideDQuote) {
826:
827:                            // Handle reserved keywords here
828:                            StringBuffer tokenBuffer = new StringBuffer();
829:                            tokenBuffer.append((char) c1);
830:
831:                            int c2 = pis.read();
832:
833:                            while (Character.isLetter((char) c2)) {
834:                                tokenBuffer.append((char) c2);
835:                                c2 = pis.read();
836:                            }
837:
838:                            pis.unread(c2); // Pushback the last unread!
839:
840:                            // Does the token match a reserved Java keyword?
841:                            boolean wasMatched = false;
842:                            String token = tokenBuffer.toString();
843:                            if (log.isDebugEnabled()) {
844:                                System.out.println("<" + token + ">(" + c2
845:                                        + "/`" + (char) c2 + "')");
846:                            }
847:
848:                            ReservedWord reservedWord = (ReservedWord) fast_keyword_map
849:                                    .get(token);
850:
851:                            if (reservedWord != null) {
852:
853:                                // Matched a reserved Java keyword
854:                                wasMatched = true;
855:                            }
856:                            if (wasMatched) {
857:                                out.print("<font color=\""
858:                                        + reservedWord.htmlcolor + "\" >");
859:                            }
860:
861:                            out.print(token);
862:
863:                            if (wasMatched) {
864:                                out.print("</font>");
865:                            }
866:                        } else {
867:                            out.print(substituteEntity((char) c1));
868:                        }
869:
870:                        // DON'T FORGET: Read the next character from the pushback stream!
871:                        c1 = pis.read();
872:                    }
873:
874:                    // Write end of the content section
875:                    out.println("</font>");
876:                    out.println("</pre>");
877:                } finally {
878:                    if (pis != null) {
879:                        pis.close();
880:                    }
881:                    if (fis != null) {
882:                        fis.close();
883:                    }
884:                }
885:            }
886:
887:            protected static final String substituteEntity(char c9) {
888:                switch (c9) {
889:                case '<':
890:                    return "&lt;";
891:
892:                case '>':
893:                    return "&gt;";
894:
895:                case '&':
896:                    return "&amp;";
897:
898:                case '\"':
899:                    return "&quot;";
900:                }
901:
902:                return new String(new char[] { c9 });
903:            }
904:
905:            public String getTitle() {
906:                return "Serve Text File";
907:            }
908:
909:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.