/* * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package com.xpn.xwiki.api; import java.util.Calendar; import java.util.Date; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.XWikiException; import com.xpn.xwiki.doc.XWikiDocument; import com.xpn.xwiki.util.Programming; /** * Information about a deleted attachment in the recycle bin. Note that this does not hold much information about the * real attachment, but only meta-information relevant to the trash: original document and filename, deleter, deletion * date. The attachment can be accessed using {@link #getAttachment()}. * <p> * This object is immutable, since entries in the trash can not be modified. * * @version $Id: 07ec5ab11b8f5ba9acd95617584f2098c4228ca0 $ * @since 2.2M1 */ public class DeletedAttachment extends Api { /** Logging helper object. */ private static final Logger LOGGER = LoggerFactory.getLogger(DeletedAttachment.class); /** The internal object wrapped by this API. */ private final com.xpn.xwiki.doc.DeletedAttachment deletedAttachment; /** * Simple constructor, initializes a new API object with the current {@link com.xpn.xwiki.XWikiContext context} and * the specified protected {@link com.xpn.xwiki.doc.DeletedAttachment deleted attachment} object. * * @param deletedAttachment the internal object wrapped by this API * @param context the current request context */ public DeletedAttachment(com.xpn.xwiki.doc.DeletedAttachment deletedAttachment, XWikiContext context) { super(context); this.deletedAttachment = deletedAttachment; } /** * Retrieve the internal entry index, used to uniquely identify this entity in the trash. This is needed because a * file can be attached and deleted multiple times, so the document name and filename are not enough to uniquely * identify a deleted attachment. * * @return internal identifier of the corresponding trash entry */ public long getId() { return this.deletedAttachment.getId(); } /** * Retrieve the original name of this attachment. * * @return the original filename, for example {@code MyPhoto.png} */ public String getFilename() { return this.deletedAttachment.getFilename(); } /** * Retrieve the name of the document this attachment belonged to. * * @return the name of the owner document, in the {@code Space.Document} format */ public String getDocName() { return this.deletedAttachment.getDocName(); } /** * Retrieve the name of the user who deleted this attachment. * * @return the user who deleted the attachment, as its document name (e.g. {@code XWiki.Admin}) */ public String getDeleter() { return this.deletedAttachment.getDeleter(); } /** * Retrieve the date and time this attachment has been deleted. * * @return the date of the deletion */ public Date getDate() { return this.deletedAttachment.getDate(); } /** * Access to the real attachment object. * * @return the attachment as it was before being deleted, and as it currently is in the recycle bin */ public Attachment getAttachment() { try { Document doc = this.context.getWiki().getDocument(getDocName(), this.context).newDocument(this.context); return new Attachment(doc, this.deletedAttachment.restoreAttachment(null, this.context), this.context); } catch (XWikiException ex) { LOGGER.warn("Failed to parse deleted attachment: " + ex.getMessage(), ex); return null; } } /** * Privileged access to the internal object wrapped by this API. * * @return original deleted attachment if the current user has programming rights, else {@code null}. */ @Programming public com.xpn.xwiki.doc.DeletedAttachment getDeletedAttachment() { if (hasProgrammingRights()) { return this.deletedAttachment; } else { return null; } } /** * Check if the current user has the right to restore the attachment. * * @return {@code true} if the current user can restore this document, {@code false} otherwise */ public boolean canRestore() { // FIXME Temporary disabled until this action is implemented. // As a workaround, the attachment can be downloaded and re-attached. return false; } /** * Check if the current user has the right to permanently delete the attachment from the trash. * * @return {@code true} if the current user can purge this document, {@code false} otherwise * @xwiki.xwikicfg xwiki.store.recyclebin.adminWaitDays How many days should an administrator wait before being able * to permanently delete this document from the recycle bin. 0 by default. * @xwiki.xwikicfg xwiki.store.recyclebin.waitDays How many days should a normal user with "delete" right wait * before being able to permanently delete this document from the recycle bin. 7 by default. */ public boolean canDelete() { try { XWikiDocument doc = new XWikiDocument(); doc.setFullName(getDocName(), this.context); if (!hasAdminRights() && !getXWikiContext().getWiki().getRightService().checkAccess("delete", doc, this.context)) { return false; } String waitdays; if (hasAdminRights()) { waitdays = getXWikiContext().getWiki().Param("xwiki.store.recyclebin.adminWaitDays", "0"); } else { waitdays = getXWikiContext().getWiki().Param("xwiki.store.recyclebin.waitDays", "7"); } int seconds = (int) (Double.parseDouble(waitdays) * 24 * 60 * 60 + 0.5); Calendar cal = Calendar.getInstance(); cal.setTime(getDate()); cal.add(Calendar.SECOND, seconds); return cal.before(Calendar.getInstance()); } catch (Exception ex) { // Public APIs should not throw exceptions LOGGER.warn("Exception while checking if entry [" + getId() + "] can be removed from the recycle bin", ex); return false; } } /** * Permanently delete this attachment from the trash. Throws an access denied exception if the user does not have * the right to perform this action, which will trigger the generic Access Denied message. Any other failures will * be silently ignored. * * @throws XWikiException if the user does not have the right to perform this action */ public void delete() throws XWikiException { if (this.canDelete()) { try { this.context.getWiki().getAttachmentRecycleBinStore().deleteFromRecycleBin(getId(), this.context, true); } catch (Exception ex) { LOGGER.warn("Failed to purge deleted attachment", ex); } } else { java.lang.Object[] args = { this.getFilename(), this.getDocName() }; throw new XWikiException(XWikiException.MODULE_XWIKI_ACCESS, XWikiException.ERROR_XWIKI_ACCESS_DENIED, "Cannot permanently delete attachment {0}@{1} from the trash", null, args); } } }