Overriding conditional FEAT caching to workaround issue #7427.

Former-commit-id: f803b628548398bb17bd8c47cb50bee0dc7ad421
This commit is contained in:
David Kocher
2013-10-08 10:45:03 +00:00
parent 92b1360b59
commit efbf042149
4 changed files with 137 additions and 0 deletions
+1
View File
@@ -38,6 +38,7 @@ Changelog. Last modified: $Date$
- [Bugfix] Changing permissions resets extended access rights flags (SFTP, FTP) (#3790)
- [Bugfix] Remember browser column widths (#6034)
- [Bugfix] Refresh list of thirdparty application bookmarks to import (#6141)
- [Bugfix] PRET support not working anymore (#7427)
4.3.1 [http://trac.cyberduck.ch/milestone/4.3.1]
- [Bugfix] Modification date shown as 01.01.1970 (Windows) (#7177)
+134
View File
@@ -44,8 +44,11 @@ import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
/**
* @version $Id$
@@ -55,6 +58,12 @@ public class FTPClient extends FTPSClient {
private SSLSocketFactory sslSocketFactory;
/**
* Map of FEAT responses. If null, has not been initialised.
*/
private HashMap<String, Set<String>> features;
public FTPClient(final SSLSocketFactory f, final SSLContext c) {
super(false, c);
this.sslSocketFactory = f;
@@ -173,6 +182,131 @@ public class FTPClient extends FTPSClient {
return results;
}
/**
* Query the server for a supported feature, and returns its values (if any).
* Caches the parsed response to avoid resending the command repeatedly.
*
* @return if the feature is present, returns the feature values (empty array if none)
* Returns {@code null} if the feature is not found or the command failed.
* Check {@link #getReplyCode()} or {@link #getReplyString()} if so.
* @throws IOException
* @since 3.0
*/
public String[] featureValues(String feature) throws IOException {
if(!initFeatureMap()) {
return null;
}
Set<String> entries = features.get(feature.toUpperCase(Locale.ROOT));
if(entries != null) {
return entries.toArray(new String[entries.size()]);
}
return null;
}
/**
* Query the server for a supported feature, and returns the its value (if any).
* Caches the parsed response to avoid resending the command repeatedly.
*
* @return if the feature is present, returns the feature value or the empty string
* if the feature exists but has no value.
* Returns {@code null} if the feature is not found or the command failed.
* Check {@link #getReplyCode()} or {@link #getReplyString()} if so.
* @throws IOException
* @since 3.0
*/
public String featureValue(String feature) throws IOException {
String[] values = featureValues(feature);
if(values != null) {
return values[0];
}
return null;
}
/**
* Query the server for a supported feature.
* Caches the parsed response to avoid resending the command repeatedly.
*
* @param feature the name of the feature; it is converted to upper case.
* @return {@code true} if the feature is present, {@code false} if the feature is not present
* or the {@link #feat()} command failed. Check {@link #getReplyCode()} or {@link #getReplyString()}
* if it is necessary to distinguish these cases.
* @throws IOException
* @since 3.0
*/
public boolean hasFeature(String feature) throws IOException {
if(!initFeatureMap()) {
return false;
}
return features.containsKey(feature.toUpperCase(Locale.ROOT));
}
/**
* Query the server for a supported feature with particular value,
* for example "AUTH SSL" or "AUTH TLS".
* Caches the parsed response to avoid resending the command repeatedly.
*
* @param feature the name of the feature; it is converted to upper case.
* @param value the value to find.
* @return {@code true} if the feature is present, {@code false} if the feature is not present
* or the {@link #feat()} command failed. Check {@link #getReplyCode()} or {@link #getReplyString()}
* if it is necessary to distinguish these cases.
* @throws IOException
* @since 3.0
*/
public boolean hasFeature(String feature, String value) throws IOException {
if(!initFeatureMap()) {
return false;
}
Set<String> entries = features.get(feature.toUpperCase(Locale.ROOT));
if(entries != null) {
return entries.contains(value);
}
return false;
}
/*
* Create the feature map if not already created.
*/
private boolean initFeatureMap() throws IOException {
if(features == null) {
// Don't create map here, because next line may throw exception
final int reply = feat();
if(FTPReply.NOT_LOGGED_IN == reply) {
return false;
}
else {
// we init the map here, so we don't keep trying if we know the command will fail
features = new HashMap<String, Set<String>>();
}
boolean success = FTPReply.isPositiveCompletion(reply);
if(!success) {
return false;
}
for(String l : getReplyStrings()) {
if(l.startsWith(" ")) { // it's a FEAT entry
String key;
String value = "";
int varsep = l.indexOf(' ', 1);
if(varsep > 0) {
key = l.substring(1, varsep);
value = l.substring(varsep + 1);
}
else {
key = l.substring(1);
}
key = key.toUpperCase(Locale.ROOT);
Set<String> entries = features.get(key);
if(entries == null) {
entries = new HashSet<String>();
features.put(key, entries);
}
entries.add(value);
}
}
}
return true;
}
@Override
public boolean retrieveFile(String remote, OutputStream local) throws IOException {
this.pret(FTPCmd.RETR, remote);
+1
View File
@@ -77,6 +77,7 @@
<li>[Bugfix] Changing permissions resets extended access rights flags (SFTP, FTP) (<a href="http://trac.cyberduck.ch/ticket/3790">#3790</a>)</li>
<li>[Bugfix] Remember browser column widths (<a href="http://trac.cyberduck.ch/ticket/6034">#6034</a>)</li>
<li>[Bugfix] Refresh list of thirdparty application bookmarks to import (<a href="http://trac.cyberduck.ch/ticket/6141">#6141</a>)</li>
<li>[Bugfix] PRET support not working anymore (<a href="http://trac.cyberduck.ch/ticket/7427">#7427</a>)</li>
</ul>
<p>Release notes for previous versions can be found at <a
+1
View File
@@ -25,3 +25,4 @@
- [Bugfix] Directory placeholder not displayed if same name as object (OpenStack) (#6988)
- [Bugfix] Changing permissions resets extended access rights flags (SFTP, FTP) (#3790)
- [Bugfix] Refresh list of thirdparty application bookmarks to import (#6141)
- [Bugfix] PRET support not working anymore (#7427)