@Override
    public AttributedList<Path> list(final Path directory, final ListProgressListener listener) throws BackgroundException {
        try {
            final AttributedList<Path> objects = new AttributedList<>();
            Marker marker = new Marker(null, null);
            final String containerId = fileid.getVersionId(containerService.getContainer(directory));
            // Seen placeholders
            final Map<String, Long> revisions = new HashMap<>();
            boolean hasDirectoryPlaceholder = containerService.isContainer(directory);
            do {
                if(log.isDebugEnabled()) {
                    log.debug(String.format("List directory %s with marker %s", directory, marker));
                }
                final B2ListFilesResponse response;
                if(versioning.isEnabled()) {
                    // In alphabetical order by file name, and by reverse of date/time uploaded for
                    // versions of files with the same name.
                    response = session.getClient().listFileVersions(containerId,
                            marker.nextFilename, marker.nextFileId, chunksize,
                            this.createPrefix(directory),
                            String.valueOf(Path.DELIMITER));
                }
                else {
                    response = session.getClient().listFileNames(containerId,
                            marker.nextFilename, chunksize,
                            this.createPrefix(directory),
                            String.valueOf(Path.DELIMITER));
                }
                marker = this.parse(directory, objects, response, revisions);
                if(null == marker.nextFileId) {
                    if(!response.getFiles().isEmpty()) {
                        hasDirectoryPlaceholder = true;
                    }
                }
                listener.chunk(directory, objects);
            }
            while(marker.hasNext());
            if(!hasDirectoryPlaceholder && objects.isEmpty()) {
                if(log.isWarnEnabled()) {
                    log.warn(String.format("No placeholder found for directory %s", directory));
                }
                throw new NotfoundException(directory.getAbsolute());
            }
            return objects;
        }
        catch(B2ApiException e) {
            throw new B2ExceptionMappingService(fileid).map("Listing directory {0} failed", e, directory);
        }
        catch(IOException e) {
            throw new DefaultIOExceptionMappingService().map(e);
        }
    }
@Test
    public void testListFileNameDotDot() throws Exception {
        final B2VersionIdProvider fileid = new B2VersionIdProvider(session);
        final Path bucket = new B2DirectoryFeature(session, fileid).mkdir(
                new Path(String.format("test-%s", new AsciiRandomStringService().random()), EnumSet.of(Path.Type.directory, Path.Type.volume)), new TransferStatus());
        final Path file = new B2TouchFeature(session, fileid).touch(new Path(bucket, "..", EnumSet.of(Path.Type.file)), new TransferStatus());
        assertEquals(bucket, file.getParent());
        assertEquals("..", file.getName());
        assertTrue(new B2ObjectListService(session, fileid).list(bucket, new DisabledListProgressListener()).contains(file));
        new B2DeleteFeature(session, fileid).delete(Arrays.asList(file, bucket), new DisabledLoginCallback(), new Delete.DisabledCallback());
    }