Source Code Cross Referenced for AttachmentServlet.java in  » Wiki-Engine » JSPWiki » com » ecyrd » jspwiki » attachment » 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 » Wiki Engine » JSPWiki » com.ecyrd.jspwiki.attachment 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:            JSPWiki - a JSP-based WikiWiki clone.
003:
004:            Copyright (C) 2001-2002 Janne Jalkanen (Janne.Jalkanen@iki.fi)
005:
006:            This program is free software; you can redistribute it and/or modify
007:            it under the terms of the GNU Lesser General Public License as published by
008:            the Free Software Foundation; either version 2.1 of the License, or
009:            (at your option) any later version.
010:
011:            This program is distributed in the hope that it will be useful,
012:            but WITHOUT ANY WARRANTY; without even the implied warranty of
013:            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014:            GNU Lesser General Public License for more details.
015:
016:            You should have received a copy of the GNU Lesser General Public License
017:            along with this program; if not, write to the Free Software
018:            Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
019:         */
020:        package com.ecyrd.jspwiki.attachment;
021:
022:        import java.io.File;
023:        import java.io.IOException;
024:        import java.io.InputStream;
025:        import java.io.OutputStream;
026:        import java.net.SocketException;
027:        import java.security.Permission;
028:        import java.security.Principal;
029:        import java.util.Enumeration;
030:        import java.util.Properties;
031:
032:        import javax.servlet.ServletConfig;
033:        import javax.servlet.ServletContext;
034:        import javax.servlet.ServletException;
035:        import javax.servlet.http.HttpServletRequest;
036:        import javax.servlet.http.HttpServletResponse;
037:
038:        import net.iamvegan.multipartrequest.HttpServletMultipartRequest;
039:        import net.iamvegan.multipartrequest.MultipartFile;
040:        import net.iamvegan.multipartrequest.ProgressListener;
041:
042:        import org.apache.commons.lang.StringUtils;
043:        import org.apache.log4j.Logger;
044:
045:        import com.ecyrd.jspwiki.*;
046:        import com.ecyrd.jspwiki.auth.AuthorizationManager;
047:        import com.ecyrd.jspwiki.auth.permissions.PermissionFactory;
048:        import com.ecyrd.jspwiki.dav.AttachmentDavProvider;
049:        import com.ecyrd.jspwiki.dav.DavPath;
050:        import com.ecyrd.jspwiki.dav.DavProvider;
051:        import com.ecyrd.jspwiki.dav.WebdavServlet;
052:        import com.ecyrd.jspwiki.dav.methods.DavMethod;
053:        import com.ecyrd.jspwiki.dav.methods.PropFindMethod;
054:        import com.ecyrd.jspwiki.filters.RedirectException;
055:        import com.ecyrd.jspwiki.providers.ProviderException;
056:        import com.ecyrd.jspwiki.ui.progress.ProgressItem;
057:        import com.ecyrd.jspwiki.util.HttpUtil;
058:
059:        /**
060:         *  This is the chief JSPWiki attachment management servlet.  It is used for
061:         *  both uploading new content and downloading old content.  It can handle
062:         *  most common cases, e.g. check for modifications and return 304's as necessary.
063:         *  <p>
064:         *  Authentication is done using JSPWiki's normal AAA framework.
065:         *  <p>
066:         *  This servlet is also capable of managing dynamically created attachments.
067:         *
068:         *  @author Erik Bunn
069:         *  @author Janne Jalkanen
070:         *
071:         *  @since 1.9.45.
072:         */
073:        public class AttachmentServlet extends WebdavServlet {
074:            private static final int BUFFER_SIZE = 8192;
075:
076:            private static final long serialVersionUID = 3257282552187531320L;
077:
078:            private WikiEngine m_engine;
079:            static Logger log = Logger.getLogger(AttachmentServlet.class
080:                    .getName());
081:
082:            private static final String HDR_VERSION = "version";
083:            // private static final String HDR_NAME        = "page";
084:
085:            /** Default expiry period is 1 day */
086:            protected static final long DEFAULT_EXPIRY = 1 * 24 * 60 * 60
087:                    * 1000;
088:
089:            private String m_tmpDir;
090:
091:            private DavProvider m_attachmentProvider;
092:
093:            /**
094:             *  The maximum size that an attachment can be.
095:             */
096:            private int m_maxSize = Integer.MAX_VALUE;
097:
098:            /**
099:             *  List of attachment types which are allowed
100:             */
101:
102:            private String[] m_allowedPatterns;
103:
104:            private String[] m_forbiddenPatterns;
105:
106:            //
107:            // Not static as DateFormat objects are not thread safe.
108:            // Used to handle the RFC date format = Sat, 13 Apr 2002 13:23:01 GMT
109:            //
110:            //private final DateFormat rfcDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
111:
112:            /**
113:             *  Initializes the servlet from WikiEngine properties.
114:             *   
115:             *  {@inheritDoc}
116:             */
117:            public void init(ServletConfig config) throws ServletException {
118:                super .init(config);
119:
120:                m_engine = WikiEngine.getInstance(config);
121:                Properties props = m_engine.getWikiProperties();
122:
123:                m_attachmentProvider = new AttachmentDavProvider(m_engine);
124:                m_tmpDir = m_engine.getWorkDir() + File.separator
125:                        + "attach-tmp";
126:
127:                m_maxSize = TextUtil.getIntegerProperty(props,
128:                        AttachmentManager.PROP_MAXSIZE, Integer.MAX_VALUE);
129:
130:                String allowed = TextUtil.getStringProperty(props,
131:                        AttachmentManager.PROP_ALLOWEDEXTENSIONS, null);
132:
133:                if (allowed != null && allowed.length() > 0)
134:                    m_allowedPatterns = allowed.toLowerCase().split("\\s");
135:                else
136:                    m_allowedPatterns = new String[0];
137:
138:                String forbidden = TextUtil.getStringProperty(props,
139:                        AttachmentManager.PROP_FORDBIDDENEXTENSIONS, null);
140:
141:                if (forbidden != null && forbidden.length() > 0)
142:                    m_forbiddenPatterns = forbidden.toLowerCase().split("\\s");
143:                else
144:                    m_forbiddenPatterns = new String[0];
145:
146:                File f = new File(m_tmpDir);
147:                if (!f.exists()) {
148:                    f.mkdirs();
149:                } else if (!f.isDirectory()) {
150:                    log
151:                            .fatal("A file already exists where the temporary dir is supposed to be: "
152:                                    + m_tmpDir + ".  Please remove it.");
153:                }
154:
155:                log.debug("UploadServlet initialized. Using " + m_tmpDir
156:                        + " for temporary storage.");
157:            }
158:
159:            private boolean isTypeAllowed(String name) {
160:                if (name == null || name.length() == 0)
161:                    return false;
162:
163:                name = name.toLowerCase();
164:
165:                for (int i = 0; i < m_forbiddenPatterns.length; i++) {
166:                    if (name.endsWith(m_forbiddenPatterns[i])
167:                            && m_forbiddenPatterns[i].length() > 0)
168:                        return false;
169:                }
170:
171:                for (int i = 0; i < m_allowedPatterns.length; i++) {
172:                    if (name.endsWith(m_allowedPatterns[i])
173:                            && m_allowedPatterns[i].length() > 0)
174:                        return true;
175:                }
176:
177:                return m_allowedPatterns.length == 0;
178:            }
179:
180:            /**
181:             *  Implements the PROPFIND method.
182:             *  
183:             *  @param req The servlet request
184:             *  @param res The servlet response
185:             *  @throws IOException If input/output fails
186:             *  @throws ServletException If the servlet has issues
187:             */
188:            public void doPropFind(HttpServletRequest req,
189:                    HttpServletResponse res) throws IOException,
190:                    ServletException {
191:                DavMethod dm = new PropFindMethod(m_attachmentProvider);
192:
193:                String p = new String(req.getPathInfo().getBytes("ISO-8859-1"),
194:                        "UTF-8");
195:
196:                DavPath path = new DavPath(p);
197:
198:                dm.execute(req, res, path);
199:            }
200:
201:            /**
202:             *  Implements the OPTIONS method.
203:             *  
204:             *  @param req The servlet request
205:             *  @param res The servlet response
206:             */
207:
208:            protected void doOptions(HttpServletRequest req,
209:                    HttpServletResponse res) {
210:                res.setHeader("DAV", "1"); // We support only Class 1
211:                res
212:                        .setHeader("Allow",
213:                                "GET, PUT, POST, OPTIONS, PROPFIND, PROPPATCH, MOVE, COPY, DELETE");
214:                res.setStatus(HttpServletResponse.SC_OK);
215:            }
216:
217:            /**
218:             *  Serves a GET with two parameters: 'wikiname' specifying the wikiname
219:             *  of the attachment, 'version' specifying the version indicator.
220:             *  
221:             *  {@inheritDoc}
222:             */
223:
224:            // FIXME: Messages would need to be localized somehow.
225:            public void doGet(HttpServletRequest req, HttpServletResponse res)
226:                    throws IOException, ServletException {
227:                WikiContext context = m_engine.createContext(req,
228:                        WikiContext.ATTACH);
229:
230:                String version = req.getParameter(HDR_VERSION);
231:                String nextPage = req.getParameter("nextpage");
232:
233:                String msg = "An error occurred. Ouch.";
234:                int ver = WikiProvider.LATEST_VERSION;
235:
236:                AttachmentManager mgr = m_engine.getAttachmentManager();
237:                AuthorizationManager authmgr = m_engine
238:                        .getAuthorizationManager();
239:
240:                String page = context.getPage().getName();
241:
242:                if (page == null) {
243:                    log.info("Invalid attachment name.");
244:                    res.sendError(HttpServletResponse.SC_BAD_REQUEST);
245:                    return;
246:                }
247:
248:                OutputStream out = null;
249:                InputStream in = null;
250:
251:                try {
252:                    log.debug("Attempting to download att " + page
253:                            + ", version " + version);
254:                    if (version != null) {
255:                        ver = Integer.parseInt(version);
256:                    }
257:
258:                    Attachment att = mgr.getAttachmentInfo(page, ver);
259:
260:                    if (att != null) {
261:                        //
262:                        //  Check if the user has permission for this attachment
263:                        //
264:
265:                        Permission permission = PermissionFactory
266:                                .getPagePermission(att, "view");
267:                        if (!authmgr.checkPermission(context.getWikiSession(),
268:                                permission)) {
269:                            log.debug("User does not have permission for this");
270:                            res.sendError(HttpServletResponse.SC_FORBIDDEN);
271:                            return;
272:                        }
273:
274:                        //
275:                        //  Check if the client already has a version of this attachment.
276:                        //
277:                        if (HttpUtil.checkFor304(req, att)) {
278:                            log
279:                                    .debug("Client has latest version already, sending 304...");
280:                            res.sendError(HttpServletResponse.SC_NOT_MODIFIED);
281:                            return;
282:                        }
283:
284:                        String mimetype = getMimeType(context, att
285:                                .getFileName());
286:
287:                        res.setContentType(mimetype);
288:
289:                        //
290:                        //  We use 'inline' instead of 'attachment' so that user agents
291:                        //  can try to automatically open the file.
292:                        //
293:
294:                        res.addHeader("Content-Disposition",
295:                                "inline; filename=\"" + att.getFileName()
296:                                        + "\";");
297:
298:                        res.addDateHeader("Last-Modified", att
299:                                .getLastModified().getTime());
300:
301:                        if (!att.isCacheable()) {
302:                            res.addHeader("Pragma", "no-cache");
303:                            res.addHeader("Cache-control", "no-cache");
304:                        }
305:
306:                        // If a size is provided by the provider, report it.
307:                        if (att.getSize() >= 0) {
308:                            // log.info("size:"+att.getSize());
309:                            res.setContentLength((int) att.getSize());
310:                        }
311:
312:                        out = res.getOutputStream();
313:                        in = mgr.getAttachmentStream(context, att);
314:
315:                        int read = 0;
316:                        byte[] buffer = new byte[BUFFER_SIZE];
317:
318:                        while ((read = in.read(buffer)) > -1) {
319:                            out.write(buffer, 0, read);
320:                        }
321:
322:                        if (log.isDebugEnabled()) {
323:                            msg = "Attachment " + att.getFileName()
324:                                    + " sent to " + req.getRemoteUser()
325:                                    + " on " + req.getRemoteAddr();
326:                            log.debug(msg);
327:                        }
328:                        if (nextPage != null)
329:                            res.sendRedirect(nextPage);
330:
331:                        return;
332:                    }
333:
334:                    msg = "Attachment '" + page + "', version " + ver
335:                            + " does not exist.";
336:
337:                    log.info(msg);
338:                    res.sendError(HttpServletResponse.SC_NOT_FOUND, msg);
339:                    return;
340:                } catch (ProviderException pe) {
341:                    msg = "Provider error: " + pe.getMessage();
342:
343:                    log.debug("Provider failed while reading", pe);
344:                    //
345:                    //  This might fail, if the response is already committed.  So in that
346:                    //  case we just log it.
347:                    //
348:                    try {
349:                        res.sendError(
350:                                HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
351:                                msg);
352:                    } catch (IllegalStateException e) {
353:                    }
354:                    return;
355:                } catch (NumberFormatException nfe) {
356:                    msg = "Invalid version number (" + version + ")";
357:                    res.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
358:                    return;
359:                } catch (SocketException se) {
360:                    //
361:                    //  These are very common in download situations due to aggressive
362:                    //  clients.  No need to try and send an error.
363:                    //
364:                    log.debug("I/O exception during download", se);
365:                    return;
366:                } catch (IOException ioe) {
367:                    //
368:                    //  Client dropped the connection or something else happened.
369:                    //  We don't know where the error came from, so we'll at least
370:                    //  try to send an error and catch it quietly if it doesn't quite work.
371:                    //
372:                    msg = "Error: " + ioe.getMessage();
373:                    log.debug("I/O exception during download", ioe);
374:
375:                    try {
376:                        res.sendError(
377:                                HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
378:                                msg);
379:                    } catch (IllegalStateException e) {
380:                    }
381:                    return;
382:                } finally {
383:                    if (in != null) {
384:                        try {
385:                            in.close();
386:                        } catch (IOException e) {
387:                        }
388:                    }
389:
390:                    //
391:                    //  Quite often, aggressive clients close the connection when they have
392:                    //  received the last bits.  Therefore, we close the output, but ignore
393:                    //  any exception that might come out of it.
394:                    //
395:
396:                    if (out != null) {
397:                        try {
398:                            out.close();
399:                        } catch (IOException e) {
400:                        }
401:                    }
402:                }
403:            }
404:
405:            /**
406:             *  Returns the mime type for this particular file.  Case does not matter.
407:             *
408:             * @param ctx WikiContext; required to access the ServletContext of the request.
409:             * @param fileName The name to check for.
410:             * @return A valid mime type, or application/binary, if not recognized
411:             */
412:            private static String getMimeType(WikiContext ctx, String fileName) {
413:                String mimetype = null;
414:
415:                HttpServletRequest req = ctx.getHttpRequest();
416:                if (req != null) {
417:                    ServletContext s = req.getSession().getServletContext();
418:
419:                    if (s != null) {
420:                        mimetype = s.getMimeType(fileName.toLowerCase());
421:                    }
422:                }
423:
424:                if (mimetype == null) {
425:                    mimetype = "application/binary";
426:                }
427:
428:                return mimetype;
429:            }
430:
431:            /**
432:             * Grabs mime/multipart data and stores it into the temporary area.
433:             * Uses other parameters to determine which name to store as.
434:             *
435:             * <p>The input to this servlet is generated by an HTML FORM with
436:             * two parts. The first, named 'page', is the WikiName identifier
437:             * for the parent file. The second, named 'content', is the binary
438:             * content of the file.
439:             * 
440:             * {@inheritDoc}
441:             */
442:            public void doPost(HttpServletRequest req, HttpServletResponse res)
443:                    throws IOException, ServletException {
444:                try {
445:                    String nextPage = upload(req);
446:                    req.getSession().removeAttribute("msg");
447:                    res.sendRedirect(nextPage);
448:                } catch (RedirectException e) {
449:                    WikiSession session = WikiSession.getWikiSession(m_engine,
450:                            req);
451:                    session.addMessage(e.getMessage());
452:
453:                    req.getSession().setAttribute("msg", e.getMessage());
454:                    res.sendRedirect(e.getRedirect());
455:                }
456:            }
457:
458:            /**
459:             *  {@inheritDoc}
460:             */
461:            public void doPut(HttpServletRequest req, HttpServletResponse res)
462:                    throws IOException, ServletException {
463:                String errorPage = m_engine.getURL(WikiContext.ERROR, "", null,
464:                        false); // If something bad happened, Upload should be able to take care of most stuff
465:
466:                String p = new String(req.getPathInfo().getBytes("ISO-8859-1"),
467:                        "UTF-8");
468:                DavPath path = new DavPath(p);
469:
470:                try {
471:                    InputStream data = req.getInputStream();
472:
473:                    WikiContext context = m_engine.createContext(req,
474:                            WikiContext.UPLOAD);
475:
476:                    String wikipage = path.get(0);
477:
478:                    errorPage = context.getURL(WikiContext.UPLOAD, wikipage);
479:
480:                    String changeNote = null; // FIXME: Does not quite work
481:
482:                    boolean created = executeUpload(context, data, path
483:                            .getName(), errorPage, wikipage, changeNote, req
484:                            .getContentLength());
485:
486:                    if (created)
487:                        res.sendError(HttpServletResponse.SC_CREATED);
488:                    else
489:                        res.sendError(HttpServletResponse.SC_OK);
490:                } catch (ProviderException e) {
491:                    res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
492:                            e.getMessage());
493:                } catch (RedirectException e) {
494:                    res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
495:                            e.getMessage());
496:                }
497:            }
498:
499:            /**
500:             *  Validates the next page to be on the same server as this webapp.
501:             *  Fixes [JSPWIKI-46].
502:             */
503:
504:            private String validateNextPage(String nextPage, String errorPage) {
505:                if (nextPage.indexOf("://") != -1) {
506:                    // It's an absolute link, so unless it starts with our address, we'll
507:                    // log an error.
508:
509:                    if (!nextPage.startsWith(m_engine.getBaseURL())) {
510:                        log
511:                                .warn("Detected phishing attempt by redirecting to an unsecure location: "
512:                                        + nextPage);
513:                        nextPage = errorPage;
514:                    }
515:                }
516:
517:                return nextPage;
518:            }
519:
520:            /**
521:             *  Uploads a specific mime multipart input set, intercepts exceptions.
522:             *
523:             *  @param req The servlet request
524:             *  @return The page to which we should go next.
525:             *  @throws RedirectException If there's an error and a redirection is needed
526:             *  @throws IOException If upload fails
527:             */
528:            protected String upload(HttpServletRequest req)
529:                    throws RedirectException, IOException {
530:                String msg = "";
531:                String attName = "(unknown)";
532:                String errorPage = m_engine.getURL(WikiContext.ERROR, "", null,
533:                        false); // If something bad happened, Upload should be able to take care of most stuff
534:                String nextPage = errorPage;
535:
536:                String progressId = req.getParameter("progressid");
537:
538:                try {
539:                    HttpServletMultipartRequest multi;
540:
541:                    // Create the context _before_ Multipart operations, otherwise
542:                    // strict servlet containers may fail when setting encoding.
543:                    WikiContext context = m_engine.createContext(req,
544:                            WikiContext.ATTACH);
545:
546:                    UploadListener pl = new UploadListener();
547:
548:                    m_engine.getProgressManager().startProgress(pl, progressId);
549:
550:                    multi = new HttpServletMultipartRequest(req,
551:                            Long.MAX_VALUE,
552:                            HttpServletMultipartRequest.SAVE_TO_TMPDIR,
553:                            HttpServletMultipartRequest.ABORT_ON_MAX_LENGTH,
554:                            "UTF-8", pl);
555:
556:                    nextPage = validateNextPage(multi.getParameter("nextpage"),
557:                            errorPage);
558:                    String wikipage = multi.getParameter("page");
559:                    String changeNote = multi.getParameter("changenote");
560:
561:                    //
562:                    // FIXME: Kludge alert.  We must end up with the parent page name,
563:                    //        if this is an upload of a new revision
564:                    //
565:
566:                    int x = wikipage.indexOf("/");
567:
568:                    if (x != -1)
569:                        wikipage = wikipage.substring(0, x);
570:
571:                    //
572:                    //  Go through all files being uploaded.
573:                    //
574:                    Enumeration files = multi.getFileParameterNames();
575:                    long fileSize = 0L;
576:                    while (files.hasMoreElements()) {
577:                        String part = (String) files.nextElement();
578:                        MultipartFile multiFile = multi.getFileParameter(part);
579:                        fileSize += multiFile.getSize();
580:                        InputStream in = multiFile.getInputStream();
581:
582:                        String filename = multiFile.getName();
583:
584:                        executeUpload(context, in, filename, nextPage,
585:                                wikipage, changeNote, fileSize);
586:                    }
587:
588:                    // Inform the JSP page of which file we are handling:
589:                    // req.setAttribute( ATTR_ATTACHMENT, wikiname );
590:                } catch (ProviderException e) {
591:                    msg = "Upload failed because the provider failed: "
592:                            + e.getMessage();
593:                    log.warn(msg + " (attachment: " + attName + ")", e);
594:
595:                    throw new IOException(msg);
596:                } catch (IOException e) {
597:                    // Show the submit page again, but with a bit more
598:                    // intimidating output.
599:                    msg = "Upload failure: " + e.getMessage();
600:                    log.warn(msg + " (attachment: " + attName + ")", e);
601:
602:                    throw e;
603:                } finally {
604:                    m_engine.getProgressManager().stopProgress(progressId);
605:                    // FIXME: In case of exceptions should absolutely
606:                    //        remove the uploaded file.
607:                }
608:
609:                return nextPage;
610:            }
611:
612:            /**
613:             *
614:             * @param context the wiki context
615:             * @param data the input stream data
616:             * @param filename the name of the file to upload
617:             * @param errorPage the place to which you want to get a redirection
618:             * @param parentPage the page to which the file should be attached
619:             * @param changenote The change note
620:             * @param contentLength The content length
621:             * @return <code>true</code> if upload results in the creation of a new page;
622:             * <code>false</code> otherwise
623:             * @throws RedirectException If the content needs to be redirected
624:             * @throws IOException       If there is a problem in the upload.
625:             * @throws ProviderException If there is a problem in the backend.
626:             */
627:            protected boolean executeUpload(WikiContext context,
628:                    InputStream data, String filename, String errorPage,
629:                    String parentPage, String changenote, long contentLength)
630:                    throws RedirectException, IOException, ProviderException {
631:                boolean created = false;
632:
633:                //
634:                //  FIXME: This has the unfortunate side effect that it will receive the
635:                //  contents.  But we can't figure out the page to redirect to
636:                //  before we receive the file, due to the stupid constructor of MultipartRequest.
637:                //
638:
639:                if (!context.hasAdminPermissions()) {
640:                    if (contentLength > m_maxSize) {
641:                        // FIXME: Does not delete the received files.
642:                        throw new RedirectException(
643:                                "File exceeds maximum size (" + m_maxSize
644:                                        + " bytes)", errorPage);
645:                    }
646:
647:                    if (!isTypeAllowed(filename)) {
648:                        throw new RedirectException(
649:                                "Files of this type may not be uploaded to this wiki",
650:                                errorPage);
651:                    }
652:                }
653:
654:                Principal user = context.getCurrentUser();
655:
656:                AttachmentManager mgr = m_engine.getAttachmentManager();
657:
658:                if (filename == null || filename.trim().length() == 0) {
659:                    log.error("Empty file name given.");
660:
661:                    throw new RedirectException("Empty file name given.",
662:                            errorPage);
663:                }
664:
665:                //
666:                //  Should help with IE 5.22 on OSX
667:                //
668:                filename = filename.trim();
669:
670:                //
671:                //  Remove any characters that might be a problem. Most
672:                //  importantly - characters that might stop processing
673:                //  of the URL.
674:                //
675:                filename = StringUtils.replaceChars(filename, "#?\"'", "____");
676:
677:                log.debug("file=" + filename);
678:
679:                if (data == null) {
680:                    log.error("File could not be opened.");
681:
682:                    throw new RedirectException("File could not be opened.",
683:                            errorPage);
684:                }
685:
686:                //
687:                //  Check whether we already have this kind of a page.
688:                //  If the "page" parameter already defines an attachment
689:                //  name for an update, then we just use that file.
690:                //  Otherwise we create a new attachment, and use the
691:                //  filename given.  Incidentally, this will also mean
692:                //  that if the user uploads a file with the exact
693:                //  same name than some other previous attachment,
694:                //  then that attachment gains a new version.
695:                //
696:
697:                Attachment att = mgr.getAttachmentInfo(context.getPage()
698:                        .getName());
699:
700:                if (att == null) {
701:                    att = new Attachment(m_engine, parentPage, filename);
702:                    created = true;
703:                }
704:                att.setSize(contentLength);
705:
706:                //
707:                //  Check if we're allowed to do this?
708:                //
709:
710:                Permission permission = PermissionFactory.getPagePermission(
711:                        att, "upload");
712:                if (m_engine.getAuthorizationManager().checkPermission(
713:                        context.getWikiSession(), permission)) {
714:                    if (user != null) {
715:                        att.setAuthor(user.getName());
716:                    }
717:
718:                    if (changenote != null && changenote.length() > 0) {
719:                        att.setAttribute(WikiPage.CHANGENOTE, changenote);
720:                    }
721:
722:                    m_engine.getAttachmentManager().storeAttachment(att, data);
723:
724:                    log.info("User " + user + " uploaded attachment to "
725:                            + parentPage + " called " + filename + ", size "
726:                            + att.getSize());
727:                } else {
728:                    throw new RedirectException(
729:                            "No permission to upload a file", errorPage);
730:                }
731:
732:                return created;
733:            }
734:
735:            /**
736:             *  Provides tracking for upload progress.
737:             *  
738:             *  @author Janne Jalkanen
739:             */
740:            private class UploadListener extends ProgressItem implements 
741:                    ProgressListener {
742:                public long m_currentBytes;
743:                public long m_totalBytes;
744:                public String m_uid;
745:
746:                public void update(long recvdBytes, long totalBytes, int item) {
747:                    m_currentBytes = recvdBytes;
748:                    m_totalBytes = totalBytes;
749:                }
750:
751:                public int getProgress() {
752:                    return (int) (((float) m_currentBytes / m_totalBytes) * 100 + 0.5);
753:                }
754:            }
755:
756:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.