--- /dev/null
+/*******************************************************************************
+ * Copyright � Igor Barma, Alexandre Desoubeaux, Christian Martel, Eric Brun, Mathieu Amblard, Gwenael Gevet, Pierre Guillot, 2012
+ * Copyright Alexandre Desoubeaux, Christian Martel, Cedric Lecarpentier, Alexandre Lefevre, Marc Salvat 2014-2016
+ * Copyright Alexandre Desoubeaux, Christian Martel, Cedric Lecarpentier, Marc Salvat, Marc Suarez, Harifetra Ramamonjy 2017
+ *
+ * This file is part of the work and learning management system Pentila Nero.
+ *
+ * Pentila Nero is free software. You can redistribute it and/or modify since
+ * you respect the terms of either (at least one of the both license) :
+ * - under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ * - the CeCILL-C as published by CeCILL-C; either version 1 of the
+ * License, or any later version
+ * - the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the license,
+ * or (at your option) any later version.
+ *
+ * There are special exceptions to the terms and conditions of the
+ * licenses as they are applied to this software. View the full text of
+ * the exception in file LICENSE-PROJECT.txt in the directory of this software
+ * distribution.
+ *
+ * Pentila Nero 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
+ * Licenses for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * and the CeCILL-C and the GNU Lesser General Public License along with
+ * Pentila Nero. If not, see :
+ * <http://www.gnu.org/licenses/> and
+ * <http://www.cecill.info/licences.fr.html>.
+ ******************************************************************************/
+package com.pentila.entSavoie.utils;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.zip.Deflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import javax.portlet.ResourceRequest;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.ArchiveException;
+import org.apache.commons.compress.archivers.ArchiveInputStream;
+import org.apache.commons.compress.archivers.ArchiveStreamFactory;
+import org.apache.commons.compress.archivers.sevenz.SevenZFile;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.liferay.portal.kernel.dao.orm.QueryUtil;
+import com.liferay.portal.kernel.exception.PortalException;
+import com.liferay.portal.kernel.exception.SystemException;
+import com.liferay.portal.kernel.io.FileCacheOutputStream;
+import com.liferay.portal.kernel.repository.model.FileEntry;
+import com.liferay.portal.kernel.repository.model.Folder;
+import com.liferay.portal.kernel.util.ParamUtil;
+import com.liferay.portal.model.Layout;
+import com.liferay.portal.model.Organization;
+import com.liferay.portal.model.User;
+import com.liferay.portal.model.UserGroup;
+import com.liferay.portal.security.permission.PermissionChecker;
+import com.liferay.portal.security.permission.PermissionCheckerFactoryUtil;
+import com.liferay.portal.service.LayoutLocalServiceUtil;
+import com.liferay.portal.service.ServiceContext;
+import com.liferay.portal.util.PortalUtil;
+import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
+import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
+import com.pentila.entSavoie.applicationManager.ApplicationManagerUtils;
+import com.pentila.entSavoie.casier.Constants;
+import com.pentila.entSavoie.directory.OrganizationFinderServiceUtil;
+import com.pentila.entSavoie.gestionMenus.model.EntityMenu;
+import com.pentila.entSavoie.gestionMenus.service.EntityMenuLocalServiceUtil;
+
+public class ZipUtil {
+
+ private static Log logger = LogFactory.getLog(ZipUtil.class);
+ static DateFormat returnDF = new SimpleDateFormat("MM/dd/yyyy HH:mm");
+
+ /**
+ * Get request parameters and unzip archive
+ *
+ * @param resourceRequest
+ * @return
+ * @throws PortalException
+ * @throws SystemException
+ * @throws IOException
+ * @throws ArchiveException
+ */
+ public static Folder unzipFile(ResourceRequest resourceRequest)
+ throws PortalException, SystemException, IOException, ArchiveException {
+
+ final User user = PortalUtil.getUser(resourceRequest);
+ final long fileEntryId = ParamUtil.getLong(resourceRequest, "fileEntryId");
+ final String title = ParamUtil.getString(resourceRequest, "title");
+
+ return unzipFile(user, fileEntryId, title);
+ }
+
+ /**
+ * Unzip file
+ *
+ * @param user
+ * @param fileEntryId
+ * @param title
+ * @return
+ * @throws SystemException
+ * @throws IOException
+ * @throws PortalException
+ * @throws ArchiveException
+ */
+ public static Folder unzipFile(User user, long fileEntryId, String title) throws SystemException, IOException, PortalException, ArchiveException {
+
+ FileEntry fileEntry = DLAppLocalServiceUtil.getFileEntry(fileEntryId);
+ InputStream is = fileEntry.getContentStream();
+
+ Folder rootFolder = DLAppUtil.addFolder(user.getUserId(), fileEntry.getGroupId(), fileEntry.getFolderId(),
+ title);
+
+ if (rootFolder == null) {
+ return null;
+ }
+
+ unArchiveFileProccess(is, fileEntry.getGroupId(), rootFolder, user);
+ is.close();
+
+ return rootFolder;
+ }
+
+ /**
+ * Is it possible to unarchive this file ?
+ *
+ * @param fileExtension
+ * @return true if possible to unarchive
+ */
+ public static boolean canUnArchive(String fileExtension) {
+ return (fileExtension.equals("zip") || fileExtension.equals("tar") || fileExtension.equals("ar")
+ || fileExtension.equals("jar") || fileExtension.equals("dump") || fileExtension.equals("cpio")
+ || fileExtension.equals("7z"));
+ }
+
+ /**
+ * The inner unarchiving process
+ *
+ * @param is
+ * @param scopeGroupId
+ * @param rootFolder
+ * @param user
+ * @throws SystemException
+ * @throws PortalException
+ * @throws IOException
+ * @throws ArchiveException
+ */
+ private static void unArchiveFileProccess(InputStream is, long scopeGroupId, Folder rootFolder, User user)
+ throws SystemException, PortalException, IOException, ArchiveException {
+ BufferedInputStream bis = new BufferedInputStream(is);
+ ArchiveInputStream ais = null;
+ SevenZFile sevenZFile = null;
+ File tempFile = null;
+
+ if (ArchiveStreamFactory.detect(bis).equals(ArchiveStreamFactory.SEVEN_Z)) {
+ tempFile = File.createTempFile("archive", "7z");
+
+ OutputStream outputStream = new FileOutputStream(tempFile, false);
+
+ int read = 0;
+ byte[] bytes = new byte[1024];
+
+ while ((read = bis.read(bytes)) != -1) {
+ outputStream.write(bytes, 0, read);
+ }
+
+ sevenZFile = new SevenZFile(tempFile);
+ outputStream.close();
+
+ } else {
+ ais = new ArchiveStreamFactory().createArchiveInputStream(bis);
+ }
+
+ ArchiveEntry entry = null;
+
+ // Loop over archive entries
+ while ((entry = sevenZFile != null ? sevenZFile.getNextEntry() : ais.getNextEntry()) != null) {
+
+ if (!entry.isDirectory()) {
+ String[] filePath = entry.getName().split("/");
+ List<String> filePathList = new ArrayList<String>();
+ for (int i = 0; i < filePath.length; i++) {
+ filePathList.add(filePath[i]);
+ }
+
+ // on recupere le dossier qui doit contenir le fichier
+ Folder targetFolder = getTargetFolder(filePathList.subList(0, filePathList.size() - 1), rootFolder,
+ user, scopeGroupId);
+
+ String targetFileName = "";
+ targetFileName = filePathList.get(filePathList.size() - 1);
+
+ // Ajout du fichier
+ final int BUFFER = 2048;
+
+ FileCacheOutputStream myFile = new FileCacheOutputStream();
+ int count;
+ byte data[] = new byte[BUFFER];
+ if (sevenZFile != null) {
+ while ((count = sevenZFile.read(data, 0, BUFFER)) != -1) {
+ myFile.write(data, 0, count);
+ }
+ } else {
+ while ((count = ais.read(data, 0, BUFFER)) != -1) {
+ myFile.write(data, 0, count);
+ }
+ }
+
+ DLAppUtil.addFileEntry(user, targetFolder, targetFileName, myFile.getBytes());
+ }
+ }
+ if (tempFile != null) {
+ tempFile.delete();
+ }
+ if (ais != null) {
+ ais.close();
+ }
+ if (sevenZFile != null) {
+ sevenZFile.close();
+ }
+ bis.close();
+ }
+
+ private static Folder getTargetFolder(List<String> filePathList, Folder rootFolder, User user, long scopeGroupId)
+ throws SystemException, PortalException {
+ if (filePathList.isEmpty()) {
+ return rootFolder;
+ } else {
+ for (Folder f : DLAppLocalServiceUtil.getFolders(scopeGroupId, rootFolder.getFolderId())) {
+ if (f.getName().equals(filePathList.get(0))) {
+ return getTargetFolder(filePathList.subList(1, filePathList.size()), f, user, scopeGroupId);
+ }
+ }
+
+ Folder newFolder = DLAppLocalServiceUtil.addFolder(user.getUserId(), scopeGroupId, rootFolder.getFolderId(),
+ filePathList.get(0), "", new ServiceContext());
+ PermissionsUtils.setParentPermissionToFolder(newFolder);
+
+ return getTargetFolder(filePathList.subList(1, filePathList.size()), newFolder, user, scopeGroupId);
+ }
+ }
+
+ /**
+ * Loop over files of folder to add them into zip archive
+ *
+ * @param user
+ * @param folderEntries
+ * @param directory
+ * @param out
+ * @param permissionChecker
+ * @throws SystemException
+ * @throws PortalException
+ */
+ public static void addFolderToZip(User user, List<Folder> folderEntries, String directory, ZipOutputStream out,
+ PermissionChecker permissionChecker) throws SystemException, PortalException {
+ for (Folder dlfo : folderEntries) {
+ if (PermissionsUtils.checkFolderPermission(permissionChecker, dlfo, "VIEW")) {
+
+ List<FileEntry> ldlfe = DLAppLocalServiceUtil.getFileEntries(dlfo.getGroupId(), dlfo.getFolderId(),
+ QueryUtil.ALL_POS, QueryUtil.ALL_POS);
+
+ // Rename '._CASIER_' and "Mes documents" folder
+ String folderName = "";
+ if (dlfo.getName().equals(Constants.DROP_BOX_FOLDER_NAME)) {
+ folderName = "Casier";
+ } else if (dlfo.getName().equals(Constants.SCHOOL_BAG_FOLDER_NAME)) {
+ folderName = getDocumentsFolderName(user);
+ } else {
+ folderName = dlfo.getName();
+ }
+
+ addFileEntriesToZip(user, ldlfe, directory + folderName + "/", out, permissionChecker);
+
+ // Recursive call
+ List<Folder> ldlfo = DLAppLocalServiceUtil.getFolders(dlfo.getGroupId(), dlfo.getFolderId());
+ addFolderToZip(user, ldlfo, directory + folderName + "/", out, permissionChecker);
+ }
+ }
+ }
+
+ /**
+ * Add a list of file entries into a zip archive
+ *
+ * @param user
+ * @param fileEntries
+ * @param folderPath
+ * @param out
+ * @param permissionChecker
+ */
+ public static void addFileEntriesToZip(User user, List<FileEntry> fileEntries, String folderPath,
+ ZipOutputStream out, PermissionChecker permissionChecker) {
+ for (FileEntry dlfe : fileEntries) {
+ logger.info("Adding file " + dlfe.getTitle() + " (id "+dlfe.getFileEntryId()+") into zip with folderPath=" + folderPath);
+ try {
+ if (PermissionsUtils.checkFilePermission(permissionChecker, dlfe, "VIEW")) {
+
+ InputStream inputStream = DLFileEntryLocalServiceUtil.getFileAsStream(user.getUserId(),
+ dlfe.getFileEntryId(), dlfe.getVersion());
+
+ // Add ZIP entry to output stream.
+ out.putNextEntry(new ZipEntry(folderPath + dlfe.getTitle()));
+
+ byte buf[] = new byte[1024];
+ int len;
+ while ((len = inputStream.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+ out.closeEntry();
+ inputStream.close();
+ }
+ } catch (Exception e) {
+ logger.error("Error while adding file entry into zip archive", e);
+ e.printStackTrace();
+ continue;
+ }
+ }
+ }
+
+ /**
+ * Get the personal document folder from the menu
+ *
+ * @param user
+ * @return
+ */
+ private static String getDocumentsFolderName(User user) {
+
+ try {
+ // Get rattach etab
+ Organization org = OrganizationFinderServiceUtil.getEtabRatachement(user);
+ if (org == null) {
+ return "";
+ }
+
+ HashSet<UserGroup> allAppliUserGroup = ApplicationManagerUtils.getUserApplicationRoles(user);
+ // We do not take the management(gestion) portlets and we put a
+ // clean label for each portlet
+ for (UserGroup a : allAppliUserGroup) {
+ for (Layout l : LayoutLocalServiceUtil.getLayouts(a.getGroup().getGroupId(), true)) {
+ // If the layout is the workspace one we get the label
+ if (l.getTypeSettings().contains(PortletConstant.CARTABLE_PORTLET_ID)) {
+ for (EntityMenu em : EntityMenuLocalServiceUtil
+ .getEntityMenusByEtabId(org.getOrganizationId())) {
+ if (em.getAppRoleId() == a.getUserGroupId()) {
+ return em.getEntityName();
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ logger.error("Could not ranslate the personnal document folder name", e);
+ }
+ // default
+ return Constants.SCHOOL_BAG_FOLDER_NAME;
+ }
+
+ /**
+ * A file as a string into a zip archive
+ *
+ * @param fileString
+ * @param fileName
+ * @param folderPath
+ * @param out
+ */
+ public static void addStringFileToZip(String fileString, String fileName, String folderPath, ZipOutputStream out) {
+ try {
+ InputStream inputStream = new ByteArrayInputStream(fileString.getBytes());
+
+ // Add ZIP entry to output stream.
+ out.putNextEntry(new ZipEntry(folderPath + fileName));
+
+ byte buf[] = new byte[1024];
+ int len;
+ while ((len = inputStream.read(buf)) > 0)
+ out.write(buf, 0, len);
+ out.closeEntry();
+ inputStream.close();
+
+ } catch (Exception e) {
+ logger.error("Erreur lors de la creation des fichiers pour l'archive zip", e);
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Add a file as a byte array into a zip archive
+ *
+ * @param file
+ * @param fileName
+ * @param folderPath
+ * @param out
+ */
+ public static void addByteArrayFileToZip(byte[] file, String fileName, String folderPath, ZipOutputStream out) {
+ try {
+
+ InputStream inputStream = new ByteArrayInputStream(file);
+
+ // Add ZIP entry to output stream.
+ out.putNextEntry(new ZipEntry(folderPath + fileName));
+
+ byte buf[] = new byte[1024];
+ int len;
+ while ((len = inputStream.read(buf)) > 0)
+ out.write(buf, 0, len);
+ out.closeEntry();
+ inputStream.close();
+
+ } catch (Exception e) {
+ logger.error("Erreur lors de la creation des fichiers pour l'archive zip", e);
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Create a zip stram
+ *
+ * @param user
+ * @param folderIdArray
+ * @param fileIdArray
+ * @return
+ * @throws PortalException
+ * @throws SystemException
+ * @throws IOException
+ */
+ public static FileCacheOutputStream createZipStream(User user, long[] folderIdArray, long[] fileIdArray)
+ throws PortalException, SystemException, IOException {
+
+ PermissionChecker permissionChecker = null;
+ try {
+ permissionChecker = PermissionCheckerFactoryUtil.create(user);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ FileCacheOutputStream fcos = new FileCacheOutputStream();
+ ZipOutputStream zipOut = new ZipOutputStream(fcos);
+ zipOut.setLevel(Deflater.BEST_COMPRESSION);
+
+ // Loop over files
+ List<FileEntry> fileEntries = new ArrayList<FileEntry>();
+ for (long fileEntryId : fileIdArray) {
+ if (fileEntryId != 0) {
+ FileEntry dlfe = DLAppLocalServiceUtil.getFileEntry(fileEntryId);
+ fileEntries.add(dlfe);
+ }
+ }
+ addFileEntriesToZip(user, fileEntries, "", zipOut, permissionChecker);
+
+ // Loop over folders
+ List<Folder> folderEntries = new ArrayList<Folder>();
+ for (long folderId : folderIdArray) {
+ if (folderId != 0) {
+ Folder dlfo = DLAppLocalServiceUtil.getFolder(folderId);
+ folderEntries.add(dlfo);
+ }
+ }
+ addFolderToZip(user, folderEntries, "", zipOut, permissionChecker);
+
+ zipOut.close();
+ fcos.close();
+ return fcos;
+ }
+
+ /*
+ * Unzip file to given folder and recreate full hierarchy
+ */
+ public static void unzipFileToDir(File zipFile, File outputDir) {
+ try {
+ ZipInputStream zin = new ZipInputStream(new FileInputStream(zipFile.getAbsolutePath()));
+ ZipEntry entry;
+ String name, dir;
+ while ((entry = zin.getNextEntry()) != null) {
+ name = entry.getName();
+ if (entry.isDirectory()) {
+ mkdirs(outputDir, name);
+ continue;
+ }
+
+ dir = dirpart(name);
+ if (dir != null) {
+ mkdirs(outputDir, dir);
+ }
+ extractFile(zin, outputDir, name);
+ }
+ zin.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static final int BUFFER_SIZE = 4096;
+
+ private static void extractFile(ZipInputStream in, File outdir, String name) throws IOException {
+ System.out.println("In extract file : " + name + ", outDir=" + outdir.getAbsolutePath());
+ byte[] buffer = new byte[BUFFER_SIZE];
+ BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(outdir, name)));
+ int count = -1;
+ while ((count = in.read(buffer)) != -1)
+ out.write(buffer, 0, count);
+ out.close();
+ }
+
+ private static void mkdirs(File outdir, String path) {
+ File d = new File(outdir, path);
+ if (!d.exists())
+ d.mkdirs();
+ }
+
+ private static String dirpart(String name) {
+ int s = name.lastIndexOf(File.separatorChar);
+ return s == -1 ? null : name.substring(0, s);
+ }
+
+}