/** * Create ZIP archive containing wiki pages rendered in HTML, attached files and used skins. * * @param context the XWiki context. * @return always return null. * @throws XWikiException error when exporting HTML ZIP package. * @throws IOException error when exporting HTML ZIP package. * @since XWiki Platform 1.3M1 */ private String exportHTML(XWikiContext context) throws XWikiException, IOException { XWikiRequest request = context.getRequest(); String description = request.get("description"); String name = request.get("name"); if (StringUtils.isBlank(name)) { name = context.getDoc().getFullName(); } Collection<String> pageList = getPagesToExport(request.getParameterValues("pages"), context); if (pageList.isEmpty()) { return null; } HtmlPackager packager = new HtmlPackager(); if (name != null && name.trim().length() > 0) { packager.setName(name); } if (description != null) { packager.setDescription(description); } packager.addPages(pageList); packager.export(context); return null; }
@Override public boolean action(XWikiContext context) throws XWikiException { XWikiRequest request = context.getRequest(); String formactionsave = request.getParameter("formactionsave"); String formactioncancel = request.getParameter("formactioncancel"); String formactionsac = request.getParameter("formactionsac"); if (isActionSelected(formactionsave)) { SaveAction sa = new SaveAction(); if (sa.action(context)) { sa.render(context); } return false; } if (isActionSelected(formactioncancel)) { CancelAction ca = new CancelAction(); if (ca.action(context)) { ca.render(context); } return false; } if (isActionSelected(formactionsac)) { SaveAndContinueAction saca = new SaveAndContinueAction(); if (saca.action(context)) { saca.render(context); } return false; } return true; }
@Override public String render(XWikiContext context) throws XWikiException { String defaultPage; try { XWikiRequest request = context.getRequest(); String format = request.get("format"); if ((format == null) || (format.equals("xar"))) { defaultPage = exportXAR(context); } else if (format.equals("html")) { defaultPage = exportHTML(context); } else { defaultPage = export(format, context); } } catch (Exception e) { throw new XWikiException( XWikiException.MODULE_XWIKI_APP, XWikiException.ERROR_XWIKI_APP_EXPORT, "Exception while exporting", e); } return defaultPage; }
/** * Respond to a range request, either with the requested bytes, or with a {@code 416 REQUESTED * RANGE NOT SATISFIABLE} response if the requested byte range falls outside the length of the * attachment. If the range request header is syntactically invalid, nothing is written, and * instead {@code false} is returned, letting the action handler ignore the Range header and treat * this as a normal (full) download request. * * @param attachment the attachment to get content from * @param request the current client request * @param response the response to write to. * @param context the current request context * @return {@code true} if the partial content request was syntactically valid and a response was * sent, {@code false} otherwise * @throws XWikiException if the attachment content cannot be retrieved * @throws IOException if the response cannot be written */ private static boolean sendPartialContent( final XWikiAttachment attachment, final XWikiRequest request, final XWikiResponse response, final XWikiContext context) throws XWikiException, IOException { String range = request.getHeader(RANGE_HEADER_NAME); Matcher m = RANGE_HEADER_PATTERN.matcher(range); if (m.matches()) { String startStr = m.group(1); String endStr = m.group(2); Long start = NumberUtils.createLong(startStr); Long end = NumberUtils.createLong(endStr); if (start == null && end != null && end > 0) { // Tail request, output the last <end> bytes start = Math.max(attachment.getContentSize(context) - end, 0L); end = attachment.getContentSize(context) - 1L; } if (!isValidRange(start, end)) { return false; } if (end == null) { end = attachment.getContentSize(context) - 1L; } end = Math.min(end, attachment.getContentSize(context) - 1L); writeByteRange(attachment, start, end, request, response, context); return true; } return false; }
@Override public boolean action(XWikiContext context) throws XWikiException { XWiki xwiki = context.getWiki(); XWikiResponse response = context.getResponse(); XWikiDocument doc = context.getDoc(); XWikiRequest request = context.getRequest(); String className = request.getParameter("classname"); String objectNumber = request.getParameter("object"); if (className != null && objectNumber != null) { try { BaseObject object = doc.getObject(className, Integer.valueOf(objectNumber)); synchronizeObject(object, context); } catch (Exception ex) { // Wrong parameters, non-existing object return true; } } else { for (List<BaseObject> classObjects : doc.getXObjects().values()) { for (BaseObject object : classObjects) { synchronizeObject(object, context); } } } // Set the new author doc.setAuthorReference(context.getUserReference()); xwiki.saveDocument( doc, localizePlainOrKey("core.model.xobject.synchronizeObjects.versionSummary"), true, context); if (Utils.isAjaxRequest(context)) { response.setStatus(HttpServletResponse.SC_NO_CONTENT); response.setContentLength(0); } else { // forward to edit String redirect = Utils.getRedirect("edit", "editor=object", context); sendRedirect(response, redirect); } return false; }
/** * Remove a cookie. * * @param request The servlet request needed to find the cookie to remove * @param cookieName The name of the cookie that must be removed. */ @Override public void removeCookie(String cookieName, XWikiRequest request) { Cookie cookie = request.getCookie(cookieName); if (cookie != null) { cookie.setMaxAge(0); cookie.setPath(cookie.getPath()); addCookie(cookie); } }
/** {@inheritDoc} */ public String render(XWikiContext context) throws XWikiException { XWikiRequest request = context.getRequest(); XWikiResponse response = context.getResponse(); String uri = request.getRequestURI(); // Locate the temporary file. File tempFile = getTemporaryFile(uri, context); if (null == tempFile) { throw new XWikiException( XWikiException.MODULE_XWIKI_APP, XWikiException.ERROR_XWIKI_APP_URL_EXCEPTION, "Invalid temporary resource URL"); } // Write temporary file into response. response.setDateHeader("Last-Modified", tempFile.lastModified()); String contentType = MimeTypes.OCTET_STREAM; try { contentType = tika.detect(tempFile); } catch (IOException ex) { LOG.warn( String.format( "Unable to determine mime type for temporary resource [%s]", tempFile.getAbsolutePath()), ex); } response.setContentType(contentType); try { response.setContentLength((int) tempFile.length()); IOUtils.copy(FileUtils.openInputStream(tempFile), response.getOutputStream()); } catch (IOException e) { throw new XWikiException( XWikiException.MODULE_XWIKI_APP, XWikiException.ERROR_XWIKI_APP_SEND_RESPONSE_EXCEPTION, "Exception while sending response", e); } return null; }
/** * Set the response HTTP headers common to both partial (Range) and full responses. * * @param attachment the attachment to get content from * @param request the current client request * @param response the response to write to. * @param context the current request context */ private static void setCommonHeaders( final XWikiAttachment attachment, final XWikiRequest request, final XWikiResponse response, final XWikiContext context) { // Choose the right content type String mimetype = attachment.getMimeType(context); response.setContentType(mimetype); try { response.setCharacterEncoding(""); } catch (IllegalCharsetNameException ex) { response.setCharacterEncoding(XWiki.DEFAULT_ENCODING); } String ofilename = Util.encodeURI(attachment.getFilename(), context).replaceAll("\\+", "%20"); // The inline attribute of Content-Disposition tells the browser that they should display // the downloaded file in the page (see http://www.ietf.org/rfc/rfc1806.txt for more // details). We do this so that JPG, GIF, PNG, etc are displayed without prompting a Save // dialog box. However, all mime types that cannot be displayed by the browser do prompt a // Save dialog box (exe, zip, xar, etc). String dispType = "inline"; // Determine whether the user who attached the file has Programming Rights or not. boolean hasPR = false; String author = attachment.getAuthor(); try { hasPR = context .getWiki() .getRightService() .hasAccessLevel("programming", author, "XWiki.XWikiPreferences", context); } catch (Exception e) { hasPR = false; } // If the mimetype is not authorized to be displayed inline, let's force its content disposition // to download. if ((!hasPR && !isAuthorized(mimetype)) || "1".equals(request.getParameter("force-download"))) { dispType = ATTACHMENT; } // Use RFC 2231 for encoding filenames, since the normal HTTP headers only allows ASCII // characters. // See http://tools.ietf.org/html/rfc2231 for more details. response.addHeader("Content-disposition", dispType + "; filename*=utf-8''" + ofilename); response.setDateHeader("Last-Modified", attachment.getDate().getTime()); // Advertise that downloads can be resumed response.setHeader("Accept-Ranges", "bytes"); }
private String exportXAR(XWikiContext context) throws XWikiException, IOException, FilterException { XWikiRequest request = context.getRequest(); boolean history = Boolean.valueOf(request.get("history")); boolean backup = Boolean.valueOf(request.get("backup")); String author = request.get("author"); String description = request.get("description"); String licence = request.get("licence"); String version = request.get("version"); String name = request.get("name"); String[] pages = request.getParameterValues("pages"); boolean all = ArrayUtils.isEmpty(pages); if (!context.getWiki().getRightService().hasWikiAdminRights(context)) { context.put("message", "needadminrights"); return "exception"; } if (name == null) { return "export"; } if (StringUtils.isBlank(name)) { if (all) { name = "backup"; } else { name = "export"; } } if (context.getWiki().ParamAsLong("xwiki.action.export.xar.usefilter", 1) == 1) { // Create input wiki stream DocumentInstanceInputProperties inputProperties = new DocumentInstanceInputProperties(); // We don't want to log the details inputProperties.setVerbose(false); inputProperties.setWithJRCSRevisions(history); inputProperties.setWithRevisions(false); EntityReferenceSet entities = new EntityReferenceSet(); if (all) { entities.includes(new WikiReference(context.getWikiId())); } else { // Find all page references and add them for processing Collection<String> pageList = getPagesToExport(pages, context); DocumentReferenceResolver<String> resolver = Utils.getComponent(DocumentReferenceResolver.TYPE_STRING, "current"); for (String pageName : pageList) { entities.includes(resolver.resolve(pageName)); } } inputProperties.setEntities(entities); InputFilterStreamFactory inputFilterStreamFactory = Utils.getComponent( InputFilterStreamFactory.class, FilterStreamType.XWIKI_INSTANCE.serialize()); InputFilterStream inputFilterStream = inputFilterStreamFactory.createInputFilterStream(inputProperties); // Create output wiki stream XAROutputProperties xarProperties = new XAROutputProperties(); // We don't want to log the details xarProperties.setVerbose(false); XWikiResponse response = context.getResponse(); xarProperties.setTarget(new DefaultOutputStreamOutputTarget(response.getOutputStream())); xarProperties.setPackageName(name); if (description != null) { xarProperties.setPackageDescription(description); } if (licence != null) { xarProperties.setPackageLicense(licence); } if (author != null) { xarProperties.setPackageAuthor(author); } if (version != null) { xarProperties.setPackageVersion(version); } xarProperties.setPackageBackupPack(backup); xarProperties.setPreserveVersion(backup || history); BeanOutputFilterStreamFactory<XAROutputProperties> xarFilterStreamFactory = Utils.getComponent( (Type) OutputFilterStreamFactory.class, FilterStreamType.XWIKI_XAR_11.serialize()); OutputFilterStream outputFilterStream = xarFilterStreamFactory.createOutputFilterStream(xarProperties); // Export response.setContentType("application/zip"); response.addHeader( "Content-disposition", "attachment; filename=" + Util.encodeURI(name, context) + ".xar"); inputFilterStream.read(outputFilterStream.getFilter()); inputFilterStream.close(); outputFilterStream.close(); // Flush response.getOutputStream().flush(); // Indicate that we are done with the response so no need to add anything context.setFinished(true); } else { PackageAPI export = ((PackageAPI) context.getWiki().getPluginApi("package", context)); if (export == null) { // No Packaging plugin configured return "exception"; } export.setWithVersions(history); if (author != null) { export.setAuthorName(author); } if (description != null) { export.setDescription(description); } if (licence != null) { export.setLicence(licence); } if (version != null) { export.setVersion(version); } export.setBackupPack(backup); export.setName(name); if (all) { export.backupWiki(); } else { if (pages != null) { for (int i = 0; i < pages.length; i++) { String pageName = pages[i]; String defaultAction = request.get("action_" + pageName); int iAction; try { iAction = Integer.parseInt(defaultAction); } catch (Exception e) { iAction = 0; } export.add(pageName, iAction); } } export.export(); } } return null; }
@Override public String render(XWikiContext context) throws XWikiException { XWikiRequest request = context.getRequest(); XWikiResponse response = context.getResponse(); XWikiDocument doc = context.getDoc(); String path = request.getRequestURI(); String filename = Util.decodeURI(getFileName(path, ACTION_NAME), context); XWikiAttachment attachment = null; final String idStr = request.getParameter("id"); if (StringUtils.isNumeric(idStr)) { int id = Integer.parseInt(idStr); if (doc.getAttachmentList().size() > id) { attachment = doc.getAttachmentList().get(id); } } else { attachment = doc.getAttachment(filename); } if (attachment == null) { Object[] args = {filename}; throw new XWikiException( XWikiException.MODULE_XWIKI_APP, XWikiException.ERROR_XWIKI_APP_ATTACHMENT_NOT_FOUND, "Attachment {0} not found", null, args); } XWikiPluginManager plugins = context.getWiki().getPluginManager(); attachment = plugins.downloadAttachment(attachment, context); // Try to load the attachment content just to make sure that the attachment really exists // This will throw an exception if the attachment content isn't available try { attachment.getContentSize(context); } catch (XWikiException e) { Object[] args = {filename}; throw new XWikiException( XWikiException.MODULE_XWIKI_APP, XWikiException.ERROR_XWIKI_APP_ATTACHMENT_NOT_FOUND, "Attachment content {0} not found", null, args); } long lastModifiedOnClient = request.getDateHeader("If-Modified-Since"); long lastModifiedOnServer = attachment.getDate().getTime(); if (lastModifiedOnClient != -1 && lastModifiedOnClient >= lastModifiedOnServer) { response.setStatus(HttpServletResponse.SC_NOT_MODIFIED); return null; } // Sending the content of the attachment if (request.getHeader(RANGE_HEADER_NAME) != null) { try { if (sendPartialContent(attachment, request, response, context)) { return null; } } catch (IOException ex) { // Broken response... } } sendContent(attachment, request, response, filename, context); return null; }
@Override public void readRequest() { XWikiRequest request = getRequest(); setContent(request.getParameter("content")); setWeb(request.getParameter("web")); setName(request.getParameter("name")); setParent(request.getParameter("parent")); setTemplate(request.getParameter("template")); setDefaultTemplate(request.getParameter("default_template")); setCreator(request.getParameter("creator")); setLanguage(request.getParameter("language")); setTitle(request.getParameter("title")); setComment(request.getParameter("comment")); setDefaultLanguage(request.getParameter("defaultLanguage")); setTags(request.getParameterValues("tags")); setLockForce("1".equals(request.getParameter("force"))); setMinorEdit(request.getParameter("minorEdit") != null); setSyntaxId(request.getParameter("syntaxId")); setHidden(request.getParameter("xhidden")); }