com.nuvolect.securesuite.webserver.connector.CmdPaste.java Source code

Java tutorial

Introduction

Here is the source code for com.nuvolect.securesuite.webserver.connector.CmdPaste.java

Source

/*
 * Copyright (c) 2017. Nuvolect LLC
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU
 * General Public License as published by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * Contact legal@nuvolect.com for a less restrictive commercial license if you would like to use the
 * software without the GPLv3 restrictions.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program.  If not,
 * see <http://www.gnu.org/licenses/>.
 *
 */

package com.nuvolect.securesuite.webserver.connector;//

import android.support.annotation.NonNull;

import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.nuvolect.securesuite.util.LogUtil;
import com.nuvolect.securesuite.util.OmniFile;
import com.nuvolect.securesuite.util.OmniFiles;
import com.nuvolect.securesuite.webserver.connector.base.ConnectorJsonCommand;

import org.apache.commons.io.FilenameUtils;

import java.io.InputStream;
import java.util.Map;

/**
 * <pre>
 * paste
    
 Copies or moves a directory / files
    
 Arguments:
    
 cmd : paste
 src : hash of the directory from which the files will be copied / moved (the source)
 dst : hash of the directory to which the files will be copied / moved (the destination)
 targets : An array of hashes for the files to be copied / moved
 cut : 1 if the files are moved, missing if the files are copied
 renames : Filename list of rename request
 suffix : Suffixes during rename (default is "~")
 Response:
    
 If the copy / move is successful:
    
 added : (Array) array of file and directory objects pasted. Information about File/Directory
 removed : (Array) array of file and directory 'hashes' that were successfully deleted
 {
 "added": [{
 "mime": "text\/plain",
 "ts": 1380910690,
 "read": 1,
 "write": 1,
 "size": 51,
 "hash": "l2_dW50aXRsZWQgZm9sZGVyL1JlYWQgVGhpcyBjb3B5IDEudHh0",
 "name": "Read This copy 1.txt",
 "phash": "l2_dW50aXRsZWQgZm9sZGVy"
 }],
 "removed": ["l2_UmVhZCBUaGlzIGNvcHkgMS50eHQ"]
 }
 Caution
    
 If the file name of the rename list exists in the directory,
 The command should rename the file to "filename + suffix"
 The command should stop copying at the first error. Is not allowed to overwrite
 files / directories with the same name. But the behavior of this command depends on
 some options on connector (if the user uses the default one). Please, take look the options:
 https://github.com/Studio-42/elFinder/wiki/Connector-configuration-options-2.1#copyoverwrite
 https://github.com/Studio-42/elFinder/wiki/Connector-configuration-options-2.1#copyjoin
    
 * Example:
 * GET '/servlet/connector'
 * {
 *   cmd=paste,
 *   cut=0,
 *   targets[]=l0_L3N0b3JhZ2UvZW11bGF0ZWQvMC9Eb3dubG9hZC9mcm96ZW4gcm9zZSBjb3B5IDEuanBn,
 *   dst=l0_L3N0b3JhZ2UvZW11bGF0ZWQvMC90bXA,
 *   suffix=~, _=1459348591420,
 *   src=l0_L3N0b3JhZ2UvZW11bGF0ZWQvMC9Eb3dubG9hZA,
 * }
 * Example 2, copy /Music from standard volume to paste crypto volume
 * {
 * targets[]=l0_L3N0b3JhZ2UvZW11bGF0ZWQvMC9NdXNpYw,
 * suffix=~,
 * _=1459527851332,
 * src=l0_L3N0b3JhZ2UvZW11bGF0ZWQvMA,
 * cmd=paste,
 * dst=c0_Lw,
 * queryParameterStrings=cmd=paste
 *   &dst=c0_Lw
 *   &targets%5B%5D=l0_L3N0b3JhZ2UvZW11bGF0ZWQvMC9NdXNpYw
 *   &cut=0
 *   &src=l0_L3N0b3JhZ2UvZW11bGF0ZWQvMA
 *   &suffix=~
 *   &_=1459527851332,
 * cut=0
 * }
 *
 * </pre>
 */
public class CmdPaste extends ConnectorJsonCommand {

    @Override
    public InputStream go(@NonNull Map<String, String> params) {
        String url = params.get("url");
        OmniFile dst = new OmniFile(params.get("dst"));

        boolean cut = params.containsKey("cut") && params.get("cut").contentEquals("1");

        String suffix = params.get("suffix");
        JsonArray added = new JsonArray();
        JsonArray removed = new JsonArray();

        /**
         * Params only has the first element of the targets[] array.
         * This is fine if there is only one target but an issue for multiple file operations.
         * Manually parse the query parameter strings to get all targets.
         */
        String[] qps = params.get("queryParameterStrings").split("&");

        /**
         * Iterate over the source files and copy each to the destination folder.
         * Files can be single files or directories and cut/copy/paste works across
         * different volume types, clear to encrypted, etc.
         * If the cut flag is set also delete each file.
         */
        for (String candidate : qps) {
            if (!candidate.contains("targets")) {
                continue;
            }
            String[] parts = candidate.split("=");

            OmniFile fromFile = new OmniFile(parts[1]);
            String toPath = dst.getPath() + "/" + fromFile.getName();
            OmniFile toFile = null;

            // add no more than 10 tilda
            for (int dupCount = 0; dupCount < 10; dupCount++) {
                toFile = new OmniFile(dst.getVolumeId(), toPath);

                if (!toFile.exists()) {
                    break;
                }

                // add ~ to filename, keep extension
                String extension = FilenameUtils.getExtension(toPath);
                if (!extension.isEmpty()) {
                    extension = "." + extension;
                }
                toPath = FilenameUtils.removeExtension(toPath) + suffix;
                toPath = toPath + extension;
            }

            boolean success;
            if (fromFile.isDirectory()) {
                success = OmniFiles.copyDirectory(fromFile, toFile);
            } else {
                success = OmniFiles.copyFile(fromFile, toFile);
            }

            if (success) {
                //note: full depth of directory not added
                added.add(FileObj.makeObj(toFile, url));
            }

            if (success && cut) {
                if (fromFile.delete()) {
                    removed.add(FileObj.makeObj(fromFile, url));
                } else {
                    LogUtil.log(LogUtil.LogType.CMD_PASTE, "File delete failure: " + fromFile.getPath());
                }
            }
        }

        JsonObject wrapper = new JsonObject();

        wrapper.add("added", added);
        wrapper.add("removed", removed);

        return getInputStream(wrapper);
    }
}