GithubHelp home page GithubHelp logo

swaechter / smbjwrapper Goto Github PK

View Code? Open in Web Editor NEW
35.0 6.0 6.0 174 KB

A modern object orientated library for Samba SMB

Home Page: https://github.com/swaechter/smbjwrapper

License: MIT License

Java 100.00%
smb samba java maven smbj jcifs cifs

smbjwrapper's Introduction

Wrapper for smbj

Introduction

This project provides an object & hierarchy based wrapper API for the smbj project (https://github.com/hierynomus/smbj). It serves as a replacement for the aging and insecure JCIFS project.

Foreword

In the open source world it is hard to get to know your users and their use cases & needs. In case you are using this library and enjoy it (or had problems), feel free to send me a mail ([email protected]) with your experience/thoughts. Thanks!

Installation

Import the dependency:

<dependency>
    <groupId>ch.swaechter</groupId>
    <artifactId>smbjwrapper</artifactId>
    <version>1.1.0</version>
</dependency>

Provide a SLF4J logger backend implementation:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.30</version>
</dependency>

Note: You can also use a different backend implementation. For more information see https://www.slf4j.org/manual.html

Usage

Create a SMB connection to the server

Via anonymous user:

AuthenticationContext authenticationContext = AuthenticationContext.anonymous();
try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    // Do your work
}

Via username and password:

AuthenticationContext authenticationContext = new AuthenticationContext("USERNAME", "PASSWORD".toCharArray(), "");
try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    // Do your work
}

Via username/domain and password:

AuthenticationContext authenticationContext = new AuthenticationContext("USERNAME", "PASSWORD".toCharArray(), "DOMAIN");
try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    // Do your work
}

In case you need a custom SMB configuration, you can also pass a smbj SmbConfig object to the SMB connection:

SmbConfig smbConfig = SmbConfig.builder().withSoTimeout(3000).build();
AuthenticationContext authenticationContext = new AuthenticationContext("USERNAME", "PASSWORD".toCharArray(), "DOMAIN");
try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext, smbConfig)) {
    // Do your work
}

Notes:

  • The created connection is not thread safe. As soon you are using several threads, create a new connection for each thread.
  • You don't have to use the try-with-resources statement that automatically closes the connection. You can also close the connection manually.

Access the root share and list all directories and files

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbDirectory rootDirectory = new SmbDirectory(smbConnection);
    for (SmbDirectory smbDirectory : rootDirectory.getDirectories()) {
        System.out.println(smbDirectory.getName());
    }
    for (SmbFile smbFile : rootDirectory.getFiles()) {
        System.out.println(smbFile.getName());
    }
}

Access the root share and list all specific files and directories by regex pattern or predicate

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbDirectory rootDirectory = new SmbDirectory(smbConnection);

    // List all directories and files of the current directory (Unfiltered, non-recursive)
    List<SmbItem> smbItems1 = rootDirectory.listItems();

    // List by string pattern (java.util.regex.Pattern), non-recursive tree search
    List<SmbItem> smbItems2 = rootDirectory.listItems("MyFile.txt", false);

    // List by predicate, recursive tree search
    List<SmbItem> smbItems3 = rootDirectory.listItems(smbItem -> smbItem.getName().contains("MyFile.txt"), true);
}

Note:

  • The given entry path is fully accessed and filtered/searched on the client side (There is no support for server side filtering). This can lead to performance issue with large file trees.

Access a directory/file and get more information

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbFile smbFile = new SmbFile(smbConnection, "File.txt");
    System.out.println("Is existing: " + smbFile.isExisting());
    System.out.println("Is directory: " + smbFile.isDirectory());
    System.out.println("Is file: " + smbFile.isFile());
    System.out.println("Is hidden: " + smbFile.isHidden());
    System.out.println("Is root path: " + smbFile.isRootPath());
    System.out.println("Name: " + smbFile.getName());
    System.out.println("Server name: " + smbFile.getServerName());
    System.out.println("Share name: " + smbFile.getShareName());
    System.out.println("Path: " + smbFile.getPath());
    System.out.println("SMB path: " + smbFile.getSmbPath());
    System.out.println("Creation time: " + smbFile.getCreationTime());
    System.out.println("Last access time: " + smbFile.getLastAccessTime());
    System.out.println("Last write time: " + smbFile.getLastWriteTime());
    System.out.println("Change time: " + smbFile.getChangeTime());
    System.out.println("File size: " + smbFile.getFileSize());
}

Access a subdirectory or file in a subdirectory

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbDirectory smbDirectory = new SmbDirectory(smbConnection, "Directory/Subdirectory/Subdirectory");
    SmbFile smbFile = new SmbFile(smbConnection, "Directory/Subdirectory/File.txt");
}

Access a directory/file and traverse the tree

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbFile smbFile = new SmbFile(smbConnection, "File.txt");
    System.out.println("Is root path: " + smbFile.isRootPath());
    SmbDirectory parentDirectory = smbFile.getParentPath();
    SmbDirectory rootDirectory = smbFile.getRootPath();
}

Create directories/files

Create a file:

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbFile smbFile = new SmbFile(smbConnection, "File.txt");
    smbFile.createFile();
}

Create a directory:

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbDirectory smbDirectory = new SmbDirectory(smbConnection, "Directory");
    smbDirectory.createDirectory();
}

Create a directory in the current directory (Same as SmbDirectory.createDirectory for path Directory/Subdirectory):

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbDirectory smbDirectory = new SmbDirectory(smbConnection, "Directory");
    SmbDirectory newSmbDirectory = smbDirectory.createDirectoryInCurrentDirectory("Subdirectory");
}

Create a file in the current directory (Same as SmbFile.createFile for path Directory/File.txt):

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbDirectory smbDirectory = new SmbDirectory(smbConnection, "Directory");
    SmbFile newSmbFile = smbDirectory.createFileInCurrentDirectory("File.txt");
}

Copy a file on the same server share

Copy a file on the same server share (In case they are different shares, use the download/upload bellow):

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbFile sourceFile = new SmbFile(smbConnection, "Screenshot1.png");
    SmbFile destinationFile = new SmbFile(smbConnection, "Screenshot2.png");
    sourceFile.copyFileViaServerSideCopy(destinationFile);
}

Rename a file or directory

Rename a file or directory with the possibility to replace it's existing pendant (The renamed file/directory will be returned as new object):

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbDirectory smbDirectory = new SmbDirectory(smbConnection, "Directory");
    SmbDirectory renamedSmbDirectory = smbDirectory.renameTo("DirectoryRenamed.txt", false);

    SmbFile smbFile = new SmbFile(smbConnection, "File.txt");
    SmbFile renamedSmbFile = smbFile.renameTo("FileRenamed.txt", true); // Replace an existing file
}

Notes:

  • You can only rename and replace a path of the same type (File/Directory). For example it's not possible to rename and replace a file to an existing directory and vica versa

Ensure a directory exist

Ensure that a directory exists (Autocreation if required):

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbDirectory smbDirectory = new SmbDirectory(smbConnection, "Directory");
    smbDirectory.ensureExists();
}

Upload and download a file

Upload from an input stream and overwrite/append to the file:

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbFile smbFile = new SmbFile(smbConnection, "File.txt");
    InputStream inputStream = ... // Your input stream

    // Overwrite the file
    OutputStream outputStream = smbFile.getOutputStream();

    // Append to the file
    OutputStream outputStream = smbFile.getOutputStream(true);

    IOUtils.copy(inputStream, outputStream);
    inputStream.close();
    outputStream.close();
}

Download to an output stream from the file:

try (SmbConnection smbConnection = new SmbConnection("127.0.0.1", "Share", authenticationContext)) {
    SmbFile smbFile = new SmbFile(smbConnection, "File.txt");
    InputStream inputStream = smbFile.getInputStream();
    OutputStream outputStream = ... // Your output stream

    IOUtils.copy(inputStream, outputStream);
    inputStream.close();
    outputStream.close();
}

License

This project is licensed under the MIT license. For more information see the LICENSE.md file.

Questions or problems

For questions and problems, please open an issue. Please also take a look at the open issues.

smbjwrapper's People

Contributors

dependabot[bot] avatar swaechter avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

smbjwrapper's Issues

getting issue while file rename

com.hierynomu com.hierynomus.ms smb2.SMB ApiException: STATUS_ACCESS_DENIED (0xc0000022): SetInfo failed for SMB2FileId file rename. rename file

Add a list file method

Add a SharedDirectory.listFiles(String searchPattern, boolean recursiveList) method to [recursively] list files in a directory

@JozefDropco Are you in favor of a regex or a boolean supplier method (So you are able to filter more than file names, e.g. file size)? Both?

Add methods for retreiving File/Directory information

Hi! I see, that there is no way to retreive file/directory information using only wrapper.
It would be great to create these methods for _FILE_ALL_INFORMATION or _FILE_BASIC_INFORMATION
In smbj exist methods like public FileAllInformation getFileInformation... but it is inconvenient to use these methods.
What about it?

Sincerely,
Alex

[Proposal]: Add some methods to SmbOutputStream

It would be nice to have two additional methods in your SmbOutputStream:

@Override
public void write(byte[] b) throws IOException {
    outputStream.write(b, 0, b.length);
}

@Override
public void write(byte[] b, int off, int len) throws IOException {
    outputStream.write(b, off, len);
}

Problem with copyFileViaServerSideCopy.

I have forced to change SMB2ShareAccess.ALL to EnumSet.of(SMB2ShareAccess.FILE_SHARE_READ, SMB2ShareAccess.FILE_SHARE_DELETE) when opening the sourceFile because of impossibility to remove the sourceFile after copying which leads to STATUS_SHARING_VIOLATION (0xc0000043)

public void copyFileViaServerSideCopy(SmbFile destinationSmbFile) throws Buffer.BufferException, TransportException {
    try (
        File sourceFile = getDiskShare().openFile(getPath(), EnumSet.of(AccessMask.GENERIC_READ), null, SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_OPEN, null);
        File destinationFile = getDiskShare().openFile(destinationSmbFile.getPath(), EnumSet.of(AccessMask.GENERIC_ALL), null, SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_OVERWRITE_IF, null);
    ) {
        sourceFile.remoteCopyTo(destinationFile);
    }
}

SmbItem.isRootPath returns true for the first subdirectory

The method SmbItem.isRootPath returns true for the first subdirectory as directory path. A quick fix would be to check if the path is empty, but this won't work on DFS share.

In addition the method (and maybe other methods like getRootPath) should move to the SmbDirectory class. It's not possible to check if a file is the root path (Maybe it's interesting to know if the file is IN the root directory)

Append new content to files

It should be possible to append content to existing files (and not overwrite them)

@JozefDropco Was your feature pull request released with the 0.9.1 release or is it still pending?

Feature request: add server side copy support

Hi, can you please add this feature into your wrapper. We would like to use this instead maintaining our own codebase for handling connections of SMBJ
Thanks and kind regards,
Jozef

Provide a listFiles method

Provide a listFiles method with no arguments, so we can fetch directories and files together and don't have to use getDirectories + getFiles + merge the list

Issue with SharedFile.getInputStream()

Hi! I'm testing your wrapper and all examples work well. Really great wrapper!
But the last example (Download to an output stream) is not working:

[main] INFO com.hierynomus.smbj.session.Session - Logging off session 4398650490985 from host vm.test.com
[main] INFO com.hierynomus.smbj.connection.Connection - Closed connection to vm.test.com
[Packet Reader for vm.test.com] INFO com.hierynomus.smbj.transport.PacketReader - Thread[Packet Reader for vm.test.com,5,main] stopped.
com.hierynomus.mssmb2.SMBApiException: STATUS_ACCESS_DENIED(3221225506/3221225506): Create failed for test.txt
	at com.hierynomus.smbj.share.Share.receive(Share.java:342)
	at com.hierynomus.smbj.share.Share.sendReceive(Share.java:322)
	at com.hierynomus.smbj.share.Share.createFile(Share.java:135)
	at com.hierynomus.smbj.share.DiskShare.createFileAndResolve(DiskShare.java:79)
	at com.hierynomus.smbj.share.DiskShare.open(DiskShare.java:69)
	at com.hierynomus.smbj.share.DiskShare.openFile(DiskShare.java:144)
	at ch.swaechter.smbjwrapper.SharedFile.getInputStream(SharedFile.java:53)
	at Main.main(Main.java:25)

Problem is here:
InputStream inputStream = sharedFile.getInputStream();

Any ideas?

Note: I use smbj version 0.8.0

Creation of Diskshare in SharedConnection

Hi,
in our environment we are connecting to multiple diskshares and we dont know upfront how many of them will be. Also creation of DiskShare in constructor is an expensive operation and might fail due current connection issue. DiskShare should be created on demand once its needed by SharedFile or SharedDirectory. Also the connection should be able to reconnect or created on demand so the connection can be reused by parallel requests

Rename of directory doesnt work

Hi,
I found a bug in rename directory. When I was working on our application I found out the rename doesnt work. First I found out that PATH_SEPARATOR is slash instead of backslash. I put the path as backslash and getParentPath returned always / (isRoot returned true). and the renameTo function requires backslashes otherwise the rename failed as ACCESS_DENIED. Try to simulate it with more nested folders. Maybe its due our infrastructure I am not sure. We are running on DFS

Kind regards,
Jozef

Make the library Java 9+ ready

Make the library Java 9+ ready while keeping the Java 8 support.

(I only did Java 9+ module libraries, so if anyone can share a Java 8/9+ solution, that would be great).

Example code bug

Hi,
there is bug in your example code for custom SMBJ config.
SmbConfig smbConfig = SmbConfig.builder().withSoTimeout(3000).build(); AuthenticationContext authenticationContext = new AuthenticationContext("USERNAME", "PASSWORD".toCharArray(), "DOMAIN"**, smbConfig**); try (SharedConnection sharedConnection = new SharedConnection("127.0.0.1", "Share", authenticationContext)) { // Do your work }

smbConfig should be passed to new SharedConnection instead

Kind regards,
Jozef

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.