Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package ch.cyberduck.core.transfer;

/*
* Copyright (c) 2002-2024 iterate GmbH. All rights reserved.
* https://cyberduck.io/
*
* 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.
*
* 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.
*/

import ch.cyberduck.core.Local;
import ch.cyberduck.core.Path;
import ch.cyberduck.core.ProgressListener;
import ch.cyberduck.core.exception.BackgroundException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.Optional;

public class ChainedFeatureFilter implements FeatureFilter {
private static final Logger log = LogManager.getLogger(ChainedFeatureFilter.class);

private final FeatureFilter[] filters;

public ChainedFeatureFilter(final FeatureFilter... filters) {
this.filters = filters;
}

@Override
public TransferStatus prepare(final Path file, final Optional<Local> local, final TransferStatus status, final ProgressListener progress) throws BackgroundException {
for(final FeatureFilter filter : filters) {
log.debug("Prepare {} with {}", file, filter);
filter.prepare(file, local, status, progress);
}
return status;
}

@Override
public void complete(final Path file, final Optional<Local> local, final TransferStatus status, final ProgressListener progress) throws BackgroundException {
for(final FeatureFilter filter : filters) {
log.debug("Complete {} with {}", file, filter);
filter.complete(file, local, status, progress);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package ch.cyberduck.core.transfer;

/*
* Copyright (c) 2002-2024 iterate GmbH. All rights reserved.
* https://cyberduck.io/
*
* 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.
*
* 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.
*/

import ch.cyberduck.core.Local;
import ch.cyberduck.core.Path;
import ch.cyberduck.core.ProgressListener;
import ch.cyberduck.core.exception.BackgroundException;

import java.util.Optional;

public interface FeatureFilter {
default TransferStatus prepare(final Path file, final Optional<Local> local, final TransferStatus status, final ProgressListener progress) throws BackgroundException {
// No-op
return status;
}

default void apply(final Path file, final TransferStatus status, final ProgressListener progress) throws BackgroundException {
// No-op
}

default void complete(final Path file, final Optional<Local> local, final TransferStatus status, final ProgressListener progress) throws BackgroundException {
// No-op
}

FeatureFilter noop = new FeatureFilter() {
@Override
public TransferStatus prepare(final Path file, final Optional<Local> local, final TransferStatus status, final ProgressListener progress) {
// No-op
return status;
}
};
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package ch.cyberduck.core.transfer.download.features;

/*
* Copyright (c) 2002-2024 iterate GmbH. All rights reserved.
* https://cyberduck.io/
*
* 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.
*
* 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.
*/

import ch.cyberduck.core.Local;
import ch.cyberduck.core.LocaleFactory;
import ch.cyberduck.core.Path;
import ch.cyberduck.core.ProgressListener;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.exception.ChecksumException;
import ch.cyberduck.core.io.Checksum;
import ch.cyberduck.core.io.ChecksumCompute;
import ch.cyberduck.core.io.ChecksumComputeFactory;
import ch.cyberduck.core.transfer.FeatureFilter;
import ch.cyberduck.core.transfer.TransferStatus;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.text.MessageFormat;
import java.util.Optional;

public class ChecksumFeatureFilter implements FeatureFilter {
private static final Logger log = LogManager.getLogger(ChecksumFeatureFilter.class);

@Override
public TransferStatus prepare(final Path file, final Optional<Local> local, final TransferStatus status, final ProgressListener progress) throws BackgroundException {
return status.setChecksum(status.getRemote().getChecksum());
}

@Override
public void complete(final Path file, final Optional<Local> local, final TransferStatus status, final ProgressListener progress) throws BackgroundException {
if(file.isFile()) {
if(file.getType().contains(Path.Type.decrypted)) {
log.warn("Skip checksum verification for {} with client side encryption enabled", file);
}
else {
final Checksum checksum = status.getChecksum();
if(Checksum.NONE != checksum) {
if(local.isPresent()) {
final ChecksumCompute compute = ChecksumComputeFactory.get(checksum.algorithm);
progress.message(MessageFormat.format(LocaleFactory.localizedString("Calculate checksum for {0}", "Status"),
file.getName()));
final Checksum download = compute.compute(local.get().getInputStream(), new TransferStatus());
if(!checksum.equals(download)) {
throw new ChecksumException(
MessageFormat.format(LocaleFactory.localizedString("Download {0} failed", "Error"), file.getName()),
MessageFormat.format(LocaleFactory.localizedString("Mismatch between {0} hash {1} of downloaded data and checksum {2} returned by the server", "Error"),
download.algorithm.toString(), download.hash, checksum.hash));
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package ch.cyberduck.core.transfer.download.features;

/*
* Copyright (c) 2002-2024 iterate GmbH. All rights reserved.
* https://cyberduck.io/
*
* 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.
*
* 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.
*/

import ch.cyberduck.core.Session;
import ch.cyberduck.core.transfer.ChainedFeatureFilter;
import ch.cyberduck.core.transfer.download.DownloadFilterOptions;

public class DefaultDownloadOptionsFilterChain extends ChainedFeatureFilter {

public DefaultDownloadOptionsFilterChain(final Session<?> session, final DownloadFilterOptions options) {
super(
options.timestamp ? new TimestampFeatureFilter() : noop,
options.permissions ? new PermissionFeatureFilter(session) : noop,
options.checksum ? new ChecksumFeatureFilter() : noop,
new TemporaryFeatureFilter(),
options.quarantine ? new QuarantineFilter(session) : noop,
options.open ? new LauncherFilter() : noop
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package ch.cyberduck.core.transfer.download.features;

/*
* Copyright (c) 2002-2024 iterate GmbH. All rights reserved.
* https://cyberduck.io/
*
* 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.
*
* 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.
*/

import ch.cyberduck.core.Local;
import ch.cyberduck.core.Path;
import ch.cyberduck.core.ProgressListener;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.local.ApplicationLauncher;
import ch.cyberduck.core.local.ApplicationLauncherFactory;
import ch.cyberduck.core.transfer.FeatureFilter;
import ch.cyberduck.core.transfer.TransferStatus;

import java.util.Optional;

public class LauncherFilter implements FeatureFilter {

private final ApplicationLauncher launcher = ApplicationLauncherFactory.get();

@Override
public void complete(final Path file, final Optional<Local> local, final TransferStatus status, final ProgressListener progress) throws BackgroundException {
if(file.isFile()) {
local.ifPresent(launcher::open);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package ch.cyberduck.core.transfer.download.features;

/*
* Copyright (c) 2002-2024 iterate GmbH. All rights reserved.
* https://cyberduck.io/
*
* 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.
*
* 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.
*/

import ch.cyberduck.core.Local;
import ch.cyberduck.core.Path;
import ch.cyberduck.core.Permission;
import ch.cyberduck.core.ProgressListener;
import ch.cyberduck.core.Session;
import ch.cyberduck.core.exception.AccessDeniedException;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.preferences.HostPreferencesFactory;
import ch.cyberduck.core.preferences.PreferencesReader;
import ch.cyberduck.core.transfer.FeatureFilter;
import ch.cyberduck.core.transfer.TransferStatus;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.Optional;

public class PermissionFeatureFilter implements FeatureFilter {
private static final Logger log = LogManager.getLogger(PermissionFeatureFilter.class);

private final PreferencesReader preferences;

public PermissionFeatureFilter(final Session<?> session) {
this.preferences = HostPreferencesFactory.get(session.getHost());
}

@Override
public TransferStatus prepare(final Path file, final Optional<Local> local, final TransferStatus status, final ProgressListener progress) throws BackgroundException {
Permission permission = Permission.EMPTY;
if(preferences.getBoolean("queue.download.permissions.default")) {
if(file.isFile()) {
permission = new Permission(
preferences.getInteger("queue.download.permissions.file.default"));
}
if(file.isDirectory()) {
permission = new Permission(
preferences.getInteger("queue.download.permissions.folder.default"));
}
}
else {
permission = status.getRemote().getPermission();
}
return status.setPermission(permission);
}

@Override
public void complete(final Path file, final Optional<Local> local, final TransferStatus status, final ProgressListener progress) throws BackgroundException {
if(!Permission.EMPTY.equals(status.getPermission())) {
if(file.isDirectory()) {
// Make sure we can read & write files to directory created.
status.getPermission().setUser(status.getPermission().getUser().or(Permission.Action.read).or(Permission.Action.write).or(Permission.Action.execute));
}
if(file.isFile()) {
// Make sure the owner can always read and write.
status.getPermission().setUser(status.getPermission().getUser().or(Permission.Action.read).or(Permission.Action.write));
}
if(local.isPresent()) {
log.info("Updating permissions of {} to {}", local, status.getPermission());
try {
local.get().attributes().setPermission(status.getPermission());
}
catch(AccessDeniedException e) {
// Ignore
log.warn(e.getMessage());
}
}
}
}
}
Loading
Loading