@Override
    public DescriptiveUrl toUploadUrl(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%s/apps/files_sharing/api/v1/shares?path=%s&shareType=%d&permissions=%d",
                bookmark.getHostname(), new NextcloudHomeFeature(bookmark).find(NextcloudHomeFeature.Context.ocs).getAbsolute(),
                URIEncoder.encode(PathRelativizer.relativize(NextcloudHomeFeature.Context.files.home(bookmark).find().getAbsolute(), file.getAbsolute())),
                Sharee.world.equals(sharee) ? SHARE_TYPE_PUBLIC_LINK : SHARE_TYPE_USER,
                SHARE_PERMISSIONS_CREATE
        ));
        final Credentials password = callback.prompt(bookmark,
                LocaleFactory.localizedString("Passphrase", "Cryptomator"),
                MessageFormat.format(LocaleFactory.localizedString("Create a passphrase required to access {0}", "Credentials"), file.getName()),
                new LoginOptions().anonymous(true).keychain(false).icon(bookmark.getProtocol().disk()));
        if(password.isPasswordAuthentication()) {
            request.append(String.format("&password=%s", URIEncoder.encode(password.getPassword())));
        }
        final HttpPost resource = new HttpPost(request.toString());
        resource.setHeader("OCS-APIRequest", "true");
        resource.setHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_XML.getMimeType());
        try {
            return session.getClient().execute(resource, new OcsUploadShareResponseHandler() {
                @Override
                public DescriptiveUrl handleEntity(final HttpEntity entity) throws IOException {
                    final XmlMapper mapper = new XmlMapper();
                    final Share value = mapper.readValue(entity.getContent(), Share.class);
                    // Additional request, because permissions are ignored in POST
                    final StringBuilder request = new StringBuilder(String.format("https://%s/ocs/v1.php/apps/files_sharing/api/v1/shares/%s?permissions=%d",
                            bookmark.getHostname(),
                            value.data.id,
                            SHARE_PERMISSIONS_CREATE
                    ));
                    final HttpPut put = new HttpPut(request.toString());
                    put.setHeader("OCS-APIRequest", "true");
                    put.setHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_XML.getMimeType());
                    session.getClient().execute(put, new VoidResponseHandler());
                    return super.handleEntity(entity);
                }
            });
        }
        catch(HttpResponseException e) {
            throw new DefaultHttpResponseExceptionMappingService().map(e);
        }
        catch(IOException e) {
            throw new DefaultIOExceptionMappingService().map(e);
        }
    }
@Test
    public void testToUploadUrlPasswordTooShort() throws Exception {
        final Path home = new NextcloudHomeFeature(session.getHost()).find();
        final Path folder = new DAVDirectoryFeature(session, new NextcloudAttributesFinderFeature(session)).mkdir(new Path(home, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.directory)), new TransferStatus());
        try {
            new NextcloudShareFeature(session).toUploadUrl(folder, Share.Sharee.world, null, new DisabledPasswordCallback() {
                @Override
                public Credentials prompt(final Host bookmark, final String title, final String reason, final LoginOptions options) {
                    return new Credentials(null, new AlphanumericRandomStringService(5).random());
                }
            });
            fail();
        }
        catch(AccessDeniedException e) {
            assertEquals("Password needs to be at least 10 characters long. Please contact your web hosting service provider for assistance.", e.getDetail());
        }
        new DAVDeleteFeature(session).delete(Collections.singletonList(folder), new DisabledPasswordCallback(), new Delete.DisabledCallback());
    }