Skip to content

Commit

Permalink
Fix #14197.
Browse files Browse the repository at this point in the history
  • Loading branch information
dkocher committed Jul 5, 2023
1 parent ccfaade commit 2e96e37
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@
import ch.cyberduck.core.features.PromptUrlProvider;
import ch.cyberduck.core.http.DefaultHttpResponseExceptionMappingService;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.entity.EntityBuilder;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ContentType;
Expand All @@ -45,6 +47,9 @@
import java.io.IOException;
import java.net.URI;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
Expand Down Expand Up @@ -79,16 +84,75 @@ public boolean isSupported(final Path file, final Type type) {
return true;
}

@Override
public List<Sharee> getSharees() throws BackgroundException {
final Host bookmark = session.getHost();
final StringBuilder request = new StringBuilder(String.format("https://%s/ocs/v2.php/apps/files_sharing/api/v1/sharees?lookup=trueshareType=%d&itemType=file",
bookmark.getHostname(),
SHARE_TYPE_USER // User
));
final HttpGet resource = new HttpGet(request.toString());
resource.setHeader("OCS-APIRequest", "true");
resource.setHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_XML.getMimeType());
final List<Sharee> sharees = new ArrayList<>(
Collections.singletonList(Sharee.world)
);
try {
sharees.addAll(session.getClient().execute(resource, new AbstractResponseHandler<List<Sharee>>() {
@Override
public List<Sharee> handleResponse(final HttpResponse response) throws IOException {
final StatusLine statusLine = response.getStatusLine();
final HttpEntity entity = response.getEntity();
if(statusLine.getStatusCode() >= 300) {
final StringAppender message = new StringAppender();
message.append(statusLine.getReasonPhrase());
final ocs error = new XmlMapper().readValue(entity.getContent(), ocs.class);
message.append(error.meta.message);
throw new HttpResponseException(statusLine.getStatusCode(), message.toString());
}
return super.handleResponse(response);
}

@Override
public List<Sharee> handleEntity(final HttpEntity entity) throws IOException {
final XmlMapper mapper = new XmlMapper();
final ocs value = mapper.readValue(entity.getContent(), ocs.class);
if(value.data != null) {
if(value.data.users != null) {
final List<Sharee> sharees = new ArrayList<>();
for(ocs.user user : value.data.users) {
final String id = user.value.shareWith;
final String label = String.format("%s (%s)", user.label, user.shareWithDisplayNameUnique);
sharees.add(new Sharee(id, label));
}
return sharees;
}
}
return Collections.emptyList();
}
}
));
}
catch(HttpResponseException e) {
throw new DefaultHttpResponseExceptionMappingService().map(e);
}
catch(IOException e) {
throw new DefaultIOExceptionMappingService().map(e);
}
return sharees;
}

/**
* int) 0 = user; 1 = group; 3 = public link; 6 = federated cloud share
*/
@Override
public DescriptiveUrl toDownloadUrl(final Path file, final Sharee sharee, final Object options, final PasswordCallback callback) throws BackgroundException {
final Host bookmark = session.getHost();
final StringBuilder request = new StringBuilder(String.format("https://%s/ocs/v2.php/apps/files_sharing/api/v1/shares?path=%s&shareType=%d",
final StringBuilder request = new StringBuilder(String.format("https://%s/ocs/v2.php/apps/files_sharing/api/v1/shares?path=%s&shareType=%d&shareWith=%s",
bookmark.getHostname(),
URIEncoder.encode(PathRelativizer.relativize(new NextcloudHomeFeature(bookmark).find().getAbsolute(), file.getAbsolute())),
SHARE_TYPE_PUBLIC_LINK // Public link
Sharee.world == sharee ? SHARE_TYPE_PUBLIC_LINK : SHARE_TYPE_USER,
Sharee.world == sharee ? StringUtils.EMPTY : sharee.getIdentifier()
));
final Credentials password = callback.prompt(bookmark,
LocaleFactory.localizedString("Passphrase", "Cryptomator"),
Expand All @@ -101,9 +165,9 @@ public DescriptiveUrl toDownloadUrl(final Path file, final Sharee sharee, final
resource.setHeader("OCS-APIRequest", "true");
resource.setHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_XML.getMimeType());
try {
return new DescriptiveUrl(session.getClient().execute(resource, new AbstractResponseHandler<URI>() {
return session.getClient().execute(resource, new AbstractResponseHandler<DescriptiveUrl>() {
@Override
public URI handleResponse(final HttpResponse response) throws IOException {
public DescriptiveUrl handleResponse(final HttpResponse response) throws IOException {
final StatusLine statusLine = response.getStatusLine();
final HttpEntity entity = response.getEntity();
if(statusLine.getStatusCode() >= 300) {
Expand All @@ -117,12 +181,17 @@ public URI handleResponse(final HttpResponse response) throws IOException {
}

@Override
public URI handleEntity(final HttpEntity entity) throws IOException {
public DescriptiveUrl handleEntity(final HttpEntity entity) throws IOException {
final XmlMapper mapper = new XmlMapper();
final ocs value = mapper.readValue(entity.getContent(), ocs.class);
return URI.create(value.data.url);
if(null != value.data) {
if(null != value.data.url) {
return new DescriptiveUrl(URI.create(value.data.url), DescriptiveUrl.Type.http);
}
}
return DescriptiveUrl.EMPTY;
}
}), DescriptiveUrl.Type.http);
});
}
catch(HttpResponseException e) {
throw new DefaultHttpResponseExceptionMappingService().map(e);
Expand Down Expand Up @@ -246,12 +315,35 @@ private static final class meta {
public String status;
public String statuscode;
public String message;
public int itemsperpage;
public int totalitems;
}

@JsonIgnoreProperties(ignoreUnknown = true)
private static final class data {
public int id;
public String url;
public user[] users;
}

@JsonIgnoreProperties(ignoreUnknown = true)
private static final class users {
public user[] element;
}

@JsonIgnoreProperties(ignoreUnknown = true)
private static final class user {
public String label;
public String icon;
public String shareWithDisplayNameUnique;
public value value;
}

@JsonIgnoreProperties(ignoreUnknown = true)
private static final class value {
public int shareType;
public String shareWith;
public String shareWithAdditionalInfo;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

import java.util.Collections;
import java.util.EnumSet;
import java.util.List;

import static org.junit.Assert.*;

Expand All @@ -58,6 +59,23 @@ public void testToDownloadUrlNoPassword() throws Exception {
new DAVDeleteFeature(session).delete(Collections.singletonList(file), new DisabledPasswordCallback(), new Delete.DisabledCallback());
}

@Test
public void testToDownloadUrlSharee() throws Exception {
final Path home = new NextcloudHomeFeature(session.getHost()).find();
final Path file = new DAVTouchFeature(session).touch(new Path(home, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file)), new TransferStatus());
final NextcloudShareProvider provider = new NextcloudShareProvider(session);
final List<PromptUrlProvider.Sharee> sharees = provider.getSharees();
assertFalse(sharees.isEmpty());
assertTrue(sharees.contains(PromptUrlProvider.Sharee.world));
sharees.remove(PromptUrlProvider.Sharee.world);
for(PromptUrlProvider.Sharee sharee : sharees) {
final DescriptiveUrl url = provider.toDownloadUrl(file, sharee, null, new DisabledPasswordCallback());
assertSame(DescriptiveUrl.EMPTY, url);
break;
}
new DAVDeleteFeature(session).delete(Collections.singletonList(file), new DisabledPasswordCallback(), new Delete.DisabledCallback());
}

@Test
public void testToUploadUrlNoPassword() throws Exception {
final Path home = new NextcloudHomeFeature(session.getHost()).find();
Expand Down

0 comments on commit 2e96e37

Please sign in to comment.