Skip to content

Commit

Permalink
Merge branch 'master' into feature/CD-1737
Browse files Browse the repository at this point in the history
Former-commit-id: 6ff2f93b513bfd88a935af6860059d20ac5af7b1
  • Loading branch information
dkocher committed Apr 19, 2017
2 parents 2d7d7a1 + f7fe242 commit 71fd632
Show file tree
Hide file tree
Showing 24 changed files with 223 additions and 46 deletions.
9 changes: 9 additions & 0 deletions Changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ https://cyberduck.io/
- [Feature] Search files fast without recursively listing directories (Dropbox)
- [Feature] Search files fast without recursively listing directories (Google Drive)
- [Feature] Search files fast using prefix (S3)
- [Feature] Browse local filesystem in browser

5.4.5 [https://trac.cyberduck.io/milestone/5.4.5
- [Feature] Support ssh-rsa-cert-v01@openssh.com format for private key files (SFTP)
- [Feature] Support ssh-dsa-cert-v01@openssh.com format for private key files (SFTP)

5.4.4 [https://trac.cyberduck.io/milestone/5.4.4
- [Bugfix] Multipart uploads do not resume (S3)
- [Bugfix] Field in login prompt disabled to enter authentication code (OAuth 2.0)

5.4.3 [https://trac.cyberduck.io/milestone/5.4.3
- [Bugfix]  Interoperability with PROPFIND for listing folders (WebDAV)
Expand Down
2 changes: 1 addition & 1 deletion backblaze/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
<dependency>
<groupId>ch.iterate.backblaze</groupId>
<artifactId>b2</artifactId>
<version>2.0.6</version>
<version>2.0.7</version>
<type>jar</type>
</dependency>
</dependencies>
Expand Down
10 changes: 10 additions & 0 deletions core/src/main/csharp/ch/cyberduck/ResourcesBundle.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions core/src/main/csharp/ch/cyberduck/ResourcesBundle.resx
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@
<data name="ftp" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\..\..\..\..\img\ftp.tiff;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="local" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\..\..\..\..\img\local.tiff;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="dropbox" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\..\..\..\..\img\dropbox.tiff;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
Expand Down
22 changes: 22 additions & 0 deletions core/src/main/java/ch/cyberduck/core/AttributedList.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

/**
* A sortable list with a map to lookup values by key.
Expand Down Expand Up @@ -239,4 +240,25 @@ public List<E> toList() {
public int indexOf(final E e) {
return impl.indexOf(e);
}

public boolean remove(final E e) {
return impl.remove(e);
}

@Override
public boolean equals(final Object o) {
if(this == o) {
return true;
}
if(o == null || getClass() != o.getClass()) {
return false;
}
final AttributedList<?> that = (AttributedList<?>) o;
return Objects.equals(impl, that.impl);
}

@Override
public int hashCode() {
return Objects.hash(impl);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ public static ThreadPool get(final Thread.UncaughtExceptionHandler handler) {
return get(DEFAULT_THREAD_NAME_PREFIX, PreferencesFactory.get().getInteger("threading.pool.size.max"), handler);
}

public static ThreadPool get(final String prefix, final Thread.UncaughtExceptionHandler handler) {
return get(prefix, PreferencesFactory.get().getInteger("threading.pool.size.max"), handler);
}

public static ThreadPool get(final int size) {
return get(DEFAULT_THREAD_NAME_PREFIX, size);
}
Expand Down
10 changes: 10 additions & 0 deletions core/src/test/java/ch/cyberduck/core/AttributedListTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,14 @@ public boolean accept(final Path file) {
assertTrue(list.add(a));
assertEquals(Collections.singletonList(a), list.attributes().getHidden());
}

@Test
public void testEqiaös() throws Exception {
final AttributedList<Path> list1 = new AttributedList<Path>();
final AttributedList<Path> list2 = new AttributedList<Path>();
final Path a = new Path("/a", EnumSet.of(Path.Type.directory));
assertTrue(list1.add(a));
assertTrue(list2.add(a));
assertEquals(list1, list2);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public StatusOutputStream<Reply> write(final Path file, final TransferStatus sta
public Append append(final Path file, final Long length, final Cache<Path> cache) throws BackgroundException {
if(finder.withCache(cache).find(vault.encrypt(session, file))) {
final PathAttributes attributes = this.attributes.withCache(cache).find(vault.encrypt(session, file));
return new Append(false, true).withSize(vault.toCleartextSize(attributes.getSize())).withChecksum(attributes.getChecksum());
return new Append(false, true).withSize(attributes.getSize()).withChecksum(attributes.getChecksum());
}
return Write.notfound;
}
Expand Down
Binary file added img/local.tiff
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package ch.cyberduck.core.nio;

/*
* Copyright (c) 2002-2017 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 2 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.Path;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.preferences.PreferencesFactory;
import ch.cyberduck.core.shared.DefaultHomeFinderService;

import java.util.EnumSet;

public class LocalHomeFinderFeature extends DefaultHomeFinderService {

public LocalHomeFinderFeature(final LocalSession session) {
super(session);
}

@Override
public Path find() throws BackgroundException {
final Path home = super.find();
if(home == DEFAULT_HOME) {
return new Path(PreferencesFactory.get().getProperty("local.user.home"), EnumSet.of(Path.Type.directory));
}
return home;
}

}
17 changes: 10 additions & 7 deletions nio/src/main/java/ch/cyberduck/core/nio/LocalProtocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
import ch.cyberduck.core.LocaleFactory;
import ch.cyberduck.core.Scheme;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class LocalProtocol extends AbstractProtocol {

@Override
Expand All @@ -33,7 +36,12 @@ public String getPrefix() {

@Override
public String getDescription() {
return LocaleFactory.localizedString("Local Filesystem");
try {
return InetAddress.getLocalHost().getHostName();
}
catch(UnknownHostException e) {
return LocaleFactory.localizedString("Local Filesystem");
}
}

@Override
Expand All @@ -51,11 +59,6 @@ public Type getType() {
return Type.file;
}

@Override
public String disk() {
return String.format("%s.tiff", "ftp");
}

@Override
public boolean isHostnameConfigurable() {
return false;
Expand Down Expand Up @@ -83,6 +86,6 @@ public String getDefaultHostname() {

@Override
public boolean isEnabled() {
return false;
return true;
}
}
4 changes: 4 additions & 0 deletions nio/src/main/java/ch/cyberduck/core/nio/LocalSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import ch.cyberduck.core.features.Delete;
import ch.cyberduck.core.features.Directory;
import ch.cyberduck.core.features.Find;
import ch.cyberduck.core.features.Home;
import ch.cyberduck.core.features.Move;
import ch.cyberduck.core.features.Read;
import ch.cyberduck.core.features.Symlink;
Expand Down Expand Up @@ -113,6 +114,9 @@ public <T> T _getFeature(final Class<T> type) {
return (T) new LocalUnixPermissionFeature(this);
}
}
if(type == Home.class) {
return (T) new LocalHomeFinderFeature(this);
}
return super._getFeature(type);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package ch.cyberduck.core.nio;

/*
* Copyright (c) 2002-2017 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 2 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.DisabledCancelCallback;
import ch.cyberduck.core.DisabledHostKeyCallback;
import ch.cyberduck.core.DisabledLoginCallback;
import ch.cyberduck.core.DisabledPasswordStore;
import ch.cyberduck.core.Host;
import ch.cyberduck.core.PathCache;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class LocalHomeFinderFeatureTest {

@Test
public void find() throws Exception {
final LocalSession session = new LocalSession(new Host(new LocalProtocol(), new LocalProtocol().getDefaultHostname()));
session.open(new DisabledHostKeyCallback());
session.login(new DisabledPasswordStore(), new DisabledLoginCallback(), new DisabledCancelCallback(), PathCache.empty());
assertEquals(System.getProperty("user.home"), new LocalHomeFinderFeature(session).find().getAbsolute());
session.close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public void callback(final String param) {
prompt.prompt(bookmark, token,
LocaleFactory.localizedString("OAuth2 Authentication", "Credentials"),
LocaleFactory.localizedString("Paste the authentication code from your web browser", "Credentials"),
new LoginOptions().keychain(false).user(false).password(true)
new LoginOptions().keychain(true).user(false).password(true)
);
}
try {
Expand All @@ -185,10 +185,11 @@ public void callback(final String param) {
.addRefreshListener(new SavingCredentialRefreshListener(keychain, bookmark))
.build()
.setFromTokenResponse(response);

// Save
save(keychain, bookmark, new Tokens(
tokens.getAccessToken(), tokens.getRefreshToken(), tokens.getExpirationTimeMilliseconds()));
if(token.isSaved()) {
// Save access key and refresh key
save(keychain, bookmark, new Tokens(
tokens.getAccessToken(), tokens.getRefreshToken(), tokens.getExpirationTimeMilliseconds()));
}
}
catch(IOException e) {
throw new OAuthExceptionMappingService().map(e);
Expand All @@ -211,13 +212,7 @@ public void refresh(final Credential tokens) throws BackgroundException {

public Tokens find(final HostPasswordStore keychain, final Host bookmark) {
final long expiry = preferences.getLong(String.format("%s.oauth.expiry", bookmark.getProtocol().getIdentifier()));
final String prefix;
if(StringUtils.isNotBlank(bookmark.getCredentials().getUsername())) {
prefix = String.format("%s (%s)", bookmark.getProtocol().getDescription(), bookmark.getCredentials().getUsername());
}
else {
prefix = bookmark.getProtocol().getDescription();
}
final String prefix = this.getPrefix(bookmark);
return new Tokens(keychain.getPassword(bookmark.getProtocol().getScheme(),
bookmark.getPort(), URI.create(tokenServerUrl).getHost(),
String.format("%s OAuth2 Access Token", prefix)),
Expand All @@ -228,7 +223,7 @@ public Tokens find(final HostPasswordStore keychain, final Host bookmark) {
}

private void save(final HostPasswordStore keychain, final Host bookmark, final Tokens tokens) {
final String prefix = String.format("%s (%s)", bookmark.getProtocol().getDescription(), bookmark.getCredentials().getUsername());
final String prefix = this.getPrefix(bookmark);
if(StringUtils.isNotBlank(tokens.accesstoken)) {
keychain.addPassword(bookmark.getProtocol().getScheme(),
bookmark.getPort(), URI.create(tokenServerUrl).getHost(),
Expand All @@ -245,8 +240,11 @@ private void save(final HostPasswordStore keychain, final Host bookmark, final T
}
}

private String getPrefix(final Host host) {
return String.format("%s (%s)", host.getProtocol().getDescription(), host.getCredentials().getUsername());
private String getPrefix(final Host bookmark) {
if(StringUtils.isNotBlank(bookmark.getCredentials().getUsername())) {
return String.format("%s (%s)", bookmark.getProtocol().getDescription(), bookmark.getCredentials().getUsername());
}
return bookmark.getProtocol().getDescription();
}

public OAuth2AuthorizationService withMethod(final Credential.AccessMethod method) {
Expand Down
8 changes: 7 additions & 1 deletion osx/src/main/java/ch/cyberduck/ui/cocoa/MainApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,13 @@ public static void main(String... arguments) {
new HubicProtocol(),
new LocalProtocol(),
new HubicProtocol(),
new OneDriveProtocol()
new OneDriveProtocol(),
new LocalProtocol() {
@Override
public String disk() {
return "NSComputer";
}
}
);
if(log.isInfoEnabled()) {
log.info(String.format("Running version %s", NSBundle.mainBundle()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import ch.cyberduck.core.io.StreamCopier;
import ch.cyberduck.core.io.StreamListener;
import ch.cyberduck.core.io.StreamProgress;
import ch.cyberduck.core.preferences.Preferences;
import ch.cyberduck.core.preferences.PreferencesFactory;
import ch.cyberduck.core.threading.BackgroundExceptionCallable;
import ch.cyberduck.core.threading.DefaultRetryCallable;
Expand Down Expand Up @@ -63,6 +64,9 @@
public class S3MultipartUploadService extends HttpUploadFeature<StorageObject, MessageDigest> {
private static final Logger log = Logger.getLogger(S3MultipartUploadService.class);

private final Preferences preferences
= PreferencesFactory.get();

private final S3Session session;

private final PathContainerService containerService
Expand Down Expand Up @@ -197,9 +201,14 @@ public StorageObject upload(final Path file, final Local local, final BandwidthT
reference = complete.getEtag();
}
if(!expected.equals(reference)) {
throw new ChecksumException(MessageFormat.format(LocaleFactory.localizedString("Upload {0} failed", "Error"), file.getName()),
MessageFormat.format("Mismatch between MD5 hash {0} of uploaded data and ETag {1} returned by the server",
expected, reference));
if(session.getHost().getHostname().endsWith(preferences.getProperty("s3.hostname.default"))) {
throw new ChecksumException(MessageFormat.format(LocaleFactory.localizedString("Upload {0} failed", "Error"), file.getName()),
MessageFormat.format("Mismatch between MD5 hash {0} of uploaded data and ETag {1} returned by the server",
expected, reference));
}
else {
log.warn(String.format("Mismatch between MD5 hash %s of uploaded data and ETag %s returned by the server", expected, reference));
}
}
}
// Mark parent status as complete
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,14 @@ public void close() throws IOException {
reference = complete.getEtag();
}
if(!expected.equals(reference)) {
throw new ChecksumException(MessageFormat.format(LocaleFactory.localizedString("Upload {0} failed", "Error"), file.getName()),
MessageFormat.format("Mismatch between MD5 hash {0} of uploaded data and ETag {1} returned by the server",
expected, reference));
if(session.getHost().getHostname().endsWith(preferences.getProperty("s3.hostname.default"))) {
throw new ChecksumException(MessageFormat.format(LocaleFactory.localizedString("Upload {0} failed", "Error"), file.getName()),
MessageFormat.format("Mismatch between MD5 hash {0} of uploaded data and ETag {1} returned by the server",
expected, reference));
}
else {
log.warn(String.format("Mismatch between MD5 hash %s of uploaded data and ETag %s returned by the server", expected, reference));
}
}
}
}
Expand Down
Loading

0 comments on commit 71fd632

Please sign in to comment.