fileList = smbManager.getController().getChildList(dirName);
146 | String currentPath = smbManager.getController().getCurrentPath();
147 | runOnUiThread(() -> {
148 | smbFileList.clear();
149 | smbFileList.addAll(fileList);
150 | smbFileAdapter.notifyDataSetChanged();
151 | pathTv.setText(currentPath);
152 | });
153 | });
154 | }
155 |
156 | /**
157 | * 打开文件
158 | */
159 | private void openFile(String fileName) {
160 | if (!CommonUtils.isMediaFile(fileName)) {
161 | showToast("不是可播放的视频文件");
162 | return;
163 | }
164 |
165 | //文件Url由开启监听的IP和端口及视频地址组成
166 | String httpUrl = "http://" + SmbServer.SMB_IP + ":" + SmbServer.SMB_PORT;
167 | String videoUrl = httpUrl + "/smb/" + fileName;
168 | SmbServer.SMB_FILE_NAME = fileName;
169 |
170 | Uri uri = Uri.parse(videoUrl);
171 | Intent intent = new Intent(Intent.ACTION_VIEW);
172 | intent.setDataAndType(uri, "video/*");
173 | startActivity(intent);
174 | }
175 |
176 | /**
177 | * 启动后台服务
178 | */
179 | private void startService() {
180 | Intent intent = new Intent(SmbFileActivity.this, SmbService.class);
181 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
182 | startForegroundService(intent);
183 | } else {
184 | startService(intent);
185 | }
186 | }
187 |
188 | private void showToast(String msg) {
189 | Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/app/src/main/java/com/xyoye/smbplayhelper/service/SmbService.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.smbplayhelper.service;
2 |
3 | import android.app.Notification;
4 | import android.app.NotificationChannel;
5 | import android.app.NotificationManager;
6 | import android.app.Service;
7 | import android.content.Context;
8 | import android.content.Intent;
9 | import android.os.Build;
10 | import android.os.IBinder;
11 |
12 | import androidx.core.app.NotificationCompat;
13 |
14 | import com.xyoye.smbplayhelper.R;
15 | import com.xyoye.smbplayhelper.smb.SmbServer;
16 |
17 | /**
18 | * Created by xyoye on 2019/7/23.
19 | *
20 | * 局域网视频播放服务
21 | */
22 |
23 | public class SmbService extends Service {
24 | private int NOTIFICATION_ID = 1001;
25 |
26 | private SmbServer smbServer = null;
27 | private NotificationManager notificationManager;
28 |
29 | @Override
30 | public IBinder onBind(Intent intent) {
31 | return null;
32 | }
33 |
34 | @Override
35 | public int onStartCommand(Intent intent, int flags, int startId) {
36 | notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
37 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
38 | NotificationChannel channel = new NotificationChannel("com.xyoye.smbplayhelper.smbservice.playchannel", "SMB服务", NotificationManager.IMPORTANCE_LOW);
39 | channel.enableVibration(false);
40 | channel.setVibrationPattern(new long[]{0});
41 | channel.enableLights(false);
42 | channel.setSound(null, null);
43 | if (notificationManager != null) {
44 | notificationManager.createNotificationChannel(channel);
45 | }
46 | }
47 | startForeground(NOTIFICATION_ID, buildNotification());
48 | return super.onStartCommand(intent, flags, startId);
49 | }
50 |
51 | @Override
52 | public void onCreate() {
53 | super.onCreate();
54 | smbServer = new SmbServer();
55 | smbServer.start();
56 |
57 | }
58 |
59 | private Notification buildNotification() {
60 | Notification.Builder builder = new Notification.Builder(this)
61 | .setSmallIcon(R.mipmap.ic_launcher)
62 | .setContentTitle("SmbPlayHelper")
63 | .setContentText("已开启SMB服务")
64 | .setPriority(Notification.PRIORITY_DEFAULT)
65 | .setContentIntent(null)
66 | .setWhen(System.currentTimeMillis())
67 | .setDefaults(NotificationCompat.FLAG_ONLY_ALERT_ONCE)
68 | .setVibrate(new long[]{0})
69 | .setSound(null);
70 |
71 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
72 | builder.setChannelId("com.xyoye.smbplayhelper.smbservice.playchannel");
73 | }
74 | Notification notify = builder.build();
75 | notify.flags = Notification.FLAG_FOREGROUND_SERVICE;
76 | return notify;
77 | }
78 |
79 | @Override
80 | public void onDestroy() {
81 | super.onDestroy();
82 | notificationManager.cancel(NOTIFICATION_ID);
83 | if (smbServer != null){
84 | smbServer.stopSmbServer();
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xyoye/smbplayhelper/smb/SmbServer.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.smbplayhelper.smb;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.xyoye.libsmb.SmbManager;
6 | import com.xyoye.smbplayhelper.smb.http.HttpContentListener;
7 |
8 | import java.io.File;
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.net.InetAddress;
12 | import java.net.ServerSocket;
13 | import java.net.Socket;
14 |
15 | /**
16 | * Created by xyoye on 2019/7/18.
17 | *
18 | * 接收请求
19 | */
20 |
21 | public class SmbServer extends Thread implements HttpContentListener {
22 | //smb绑定的文件名
23 | public static String SMB_FILE_NAME;
24 | //smb绑定的本地端口
25 | public static int SMB_PORT = 2222;
26 | //smb绑定的本地IP
27 | public static String SMB_IP = "127.0.0.1";
28 |
29 | //用于接收客户端(播放器)请求的Socket
30 | private ServerSocket serverSocket = null;
31 |
32 | public SmbServer() {
33 |
34 | }
35 |
36 | public void stopSmbServer() {
37 | if (serverSocket != null) {
38 | try {
39 | serverSocket.close();
40 | serverSocket = null;
41 | SMB_PORT = 2222;
42 | } catch (IOException e) {
43 | e.printStackTrace();
44 | }
45 | }
46 | }
47 |
48 | @Override
49 | public void run() {
50 | super.run();
51 |
52 | //创建ServerSocket
53 | int retryCount = 0;
54 | int port = 2222;
55 | while (!createServerSocket(port)) {
56 | retryCount++;
57 | if (retryCount > 100) {
58 | return;
59 | }
60 | port++;
61 | }
62 |
63 | //在ServerSocket关闭之前一直监听请求
64 | while (!serverSocket.isClosed()){
65 | try {
66 | Socket socket = serverSocket.accept();
67 | socket.setSoTimeout(getTimeOut());
68 | //接收到请求后,新建线程处理请求
69 | new SmbServerThread(socket, this).start();
70 | }catch (Exception e){
71 | e.printStackTrace();
72 | break;
73 | }
74 | }
75 | }
76 |
77 | private synchronized int getTimeOut(){
78 | return 15 * 1000;
79 | }
80 |
81 | //创建ServerSocket
82 | private boolean createServerSocket(int port) {
83 | if (serverSocket != null) {
84 | return true;
85 | }
86 | try {
87 | SMB_PORT = port;
88 | serverSocket = new ServerSocket(SMB_PORT, 0, InetAddress.getByName(SMB_IP));
89 | return true;
90 | } catch (IOException e) {
91 | return false;
92 | }
93 | }
94 |
95 | @Override
96 | //获取视频内容
97 | public InputStream getContentInputStream() {
98 | return SmbManager.getInstance().getController().getFileInputStream(SMB_FILE_NAME);
99 | }
100 |
101 | @Override
102 | //获取视频格式
103 | public String getContentType() {
104 | if (TextUtils.isEmpty(SMB_FILE_NAME))
105 | return "";
106 | int lastPoi = SMB_FILE_NAME.lastIndexOf('.');
107 | int lastSep = SMB_FILE_NAME.lastIndexOf(File.separator);
108 | if (lastPoi == -1 || lastSep >= lastPoi) return "";
109 | return "." +SMB_FILE_NAME.substring(lastPoi + 1);
110 | }
111 |
112 | @Override
113 | //获取视频长度
114 | public long getContentLength() {
115 | return SmbManager.getInstance().getController().getFileLength(SMB_FILE_NAME);
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/app/src/main/java/com/xyoye/smbplayhelper/smb/SmbServerThread.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.smbplayhelper.smb;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.xyoye.smbplayhelper.smb.http.HttpContentListener;
6 | import com.xyoye.smbplayhelper.smb.http.HttpResponse;
7 | import com.xyoye.smbplayhelper.smb.http.HttpSocket;
8 | import com.xyoye.smbplayhelper.smb.http.HttpStatus;
9 |
10 | import java.io.BufferedInputStream;
11 | import java.io.ByteArrayOutputStream;
12 | import java.io.IOException;
13 | import java.io.InputStream;
14 | import java.io.OutputStream;
15 | import java.net.Socket;
16 |
17 | /**
18 | * Created by xyoye on 2019/7/18.
19 | *
20 | * 处理请求,返回响应
21 | */
22 |
23 | public class SmbServerThread extends Thread {
24 | //包含请求内容的Socket
25 | private Socket socket;
26 | //获取视频内容及信息的接口
27 | private HttpContentListener httpContent;
28 |
29 | SmbServerThread(Socket socket, HttpContentListener httpContentListener) {
30 | this.socket = socket;
31 | this.httpContent = httpContentListener;
32 | }
33 |
34 | @Override
35 | public void run() {
36 | HttpSocket httpSocket = new HttpSocket(socket);
37 | if (!httpSocket.open()) {
38 | return;
39 | }
40 |
41 | printLog("----- read request thread start -----");
42 |
43 | long[] requestRange = getRangeByRequestHeader(httpSocket);
44 | while (requestRange != null) {
45 | handleHttpRequest(httpSocket, requestRange);
46 | requestRange = getRangeByRequestHeader(httpSocket);
47 | }
48 | httpSocket.close();
49 | }
50 |
51 | //从请求头中读取range信息
52 | private long[] getRangeByRequestHeader(HttpSocket socket) {
53 | printLog("----- read request header -----");
54 | InputStream inputStream = socket.getInputStream();
55 | BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
56 |
57 | String firstLine = readRequestHeaderLine(bufferedInputStream);
58 | if (TextUtils.isEmpty(firstLine)) {
59 | printLog("----- request header is empty -----");
60 | return null;
61 | }
62 |
63 | String headerLine = readRequestHeaderLine(bufferedInputStream);
64 | while (!TextUtils.isEmpty(headerLine)) {
65 | //Range : byte-
66 | int colonIdx = headerLine.indexOf(':');
67 | if (colonIdx > 0) {
68 | //Range
69 | String name = new String(headerLine.getBytes(), 0, colonIdx);
70 | //(byte-) (byte 1-123) (byte -123)
71 | String value = new String(headerLine.getBytes(), colonIdx + 1, headerLine.length() - colonIdx - 1);
72 | if (name.equals("Range")) {
73 | int cutIndex = value.indexOf("=");
74 | value = value.substring(cutIndex + 1);
75 | if (value.contains("-")) {
76 | if (value.startsWith("-")) {
77 | value = "0" + value;
78 | } else if (value.endsWith("-")) {
79 | value = value + "0";
80 | }
81 | String[] ranges = value.split("-");
82 | long[] range = new long[2];
83 | range[0] = Long.valueOf(ranges[0]);
84 | range[1] = Long.valueOf(ranges[1]);
85 | printLog("----- read range success ----- :" + range[0] + "/" + range[1]);
86 | return range;
87 | }
88 | }
89 | }
90 | headerLine = readRequestHeaderLine(bufferedInputStream);
91 | }
92 | return new long[]{0, 0};
93 | }
94 |
95 | //按行读取头信息
96 | private String readRequestHeaderLine(BufferedInputStream bufferedInputStream) {
97 | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
98 | byte[] bytes = new byte[1];
99 | try {
100 | int readLen = bufferedInputStream.read(bytes);
101 | while (readLen > 0) {
102 | byte n = '\n';
103 | byte r = '\r';
104 | if (bytes[0] == n) {
105 | break;
106 | }
107 | if (bytes[0] != r) {
108 | byteArrayOutputStream.write(bytes[0]);
109 | }
110 | readLen = bufferedInputStream.read(bytes);
111 | }
112 | } catch (IOException e) {
113 | e.printStackTrace();
114 | return "";
115 | }
116 |
117 | return byteArrayOutputStream.toString();
118 | }
119 |
120 | //处理请求构建response
121 | private void handleHttpRequest(HttpSocket httpSocket, long[] requestRange) {
122 | printLog("----- handle http request -----");
123 | // 获取文件流
124 | InputStream contentInputStream = httpContent.getContentInputStream();
125 | // 获取文件的大小
126 | long contentLength = httpContent.getContentLength();
127 | // 获取文件类型
128 | String contentType = httpContent.getContentType();
129 |
130 | long requestRangeStart = requestRange[0];
131 | long requestRangeEnd = requestRange[1] <= 0 ? contentLength - 1 : requestRange[1];
132 |
133 | if (contentLength <= 0 || contentType.length() <= 0 || contentInputStream == null) {
134 | printLog("----- handle failed : smb file error -----");
135 | printLog("----- length:" + contentLength + " stream:" + (contentInputStream == null) + " -----");
136 | HttpResponse badResponse = new HttpResponse();
137 | badResponse.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
138 | badResponse.setContentLength(0);
139 | dispatchResponse(badResponse, httpSocket, 0, 0, true);
140 | return;
141 | }
142 |
143 | if ((requestRangeStart > contentLength) || (requestRangeEnd > contentLength)) {
144 | printLog("-----handle failed : request range error -----");
145 | HttpResponse badResponse = new HttpResponse();
146 | badResponse.setStatusCode(HttpStatus.INVALID_RANGE);
147 | badResponse.setContentLength(0);
148 | dispatchResponse(badResponse, httpSocket, 0, 0, true);
149 | return;
150 | }
151 |
152 | printLog("-----handle success : response build -----");
153 | long responseLength = requestRangeEnd - requestRangeStart + 1;
154 | HttpResponse response = new HttpResponse();
155 | response.setStatusCode(HttpStatus.PARTIAL_CONTENT);
156 | response.setContentType(contentType);
157 | response.setContentLength(responseLength);
158 | response.setContentInputStream(contentInputStream);
159 | response.setContentRange(requestRangeStart, requestRangeEnd, contentLength);
160 | dispatchResponse(response, httpSocket, requestRangeStart, responseLength, false);
161 | }
162 |
163 | //返回response
164 | private synchronized void dispatchResponse(HttpResponse response,
165 | HttpSocket httpSocket,
166 | long contentOffset,
167 | long contentLength,
168 | boolean badRequest) {
169 | printLog("----- dispatch http response -----");
170 |
171 | InputStream inputStream = null;
172 | OutputStream outputStream = null;
173 | try {
174 | outputStream = httpSocket.getOutputStream();
175 | outputStream.write(response.getResponseHeader().getBytes());
176 | //必须返回!!!
177 | outputStream.write("\r\n".getBytes());
178 |
179 | //无法处理的请求
180 | if (badRequest) {
181 | outputStream.flush();
182 | printLog("----- return bad response -----");
183 | return;
184 | }
185 |
186 | inputStream = response.getContentInputStream();
187 | if (contentOffset > 0) {
188 | if (inputStream.skip(contentOffset) > 0) {
189 | printLog("----- input stream skip -----:" + contentOffset);
190 | }
191 | }
192 |
193 | int bufferSize = 512 * 1024;
194 | byte[] readBuffer = new byte[bufferSize];
195 | long readTotalSize = 0;
196 | long readSize = (bufferSize > contentLength) ? contentLength : bufferSize;
197 | int readLen = inputStream.read(readBuffer, 0, (int) readSize);
198 |
199 | printLog("----- send video data start -----:" + contentOffset);
200 | while (readLen > 0 && readTotalSize < contentLength) {
201 | outputStream.write(readBuffer, 0, readLen);
202 | outputStream.flush();
203 | readTotalSize += readLen;
204 | readSize = (bufferSize > (contentLength - readTotalSize))
205 | ? (contentLength - readTotalSize)
206 | : bufferSize;
207 | readLen = inputStream.read(readBuffer, 0, (int) readSize);
208 |
209 | printLog("----- send video data success -----:" + readTotalSize + "/" + contentLength);
210 | }
211 | printLog("----- send video data over -----:" + contentOffset);
212 | outputStream.flush();
213 | } catch (Exception e) {
214 | printLog("----- send video data error -----:" + e.getMessage());
215 | e.printStackTrace();
216 | } finally {
217 | try {if (inputStream != null)
218 | inputStream.close();
219 | if (outputStream != null)
220 | outputStream.close();
221 | }catch (IOException ignore){
222 |
223 | }
224 | }
225 | }
226 |
227 | //打印信息
228 | private void printLog(String message) {
229 | System.out.println(message);
230 | }
231 | }
232 |
--------------------------------------------------------------------------------
/app/src/main/java/com/xyoye/smbplayhelper/smb/http/HttpContentListener.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.smbplayhelper.smb.http;
2 |
3 | import java.io.InputStream;
4 |
5 | /**
6 | * Created by xyoye on 2019/7/19.
7 | */
8 |
9 | public interface HttpContentListener {
10 | /**
11 | * 获取视频流
12 | */
13 | InputStream getContentInputStream();
14 |
15 | /**
16 | * 获取视频类型
17 | */
18 | String getContentType();
19 |
20 | /**
21 | * 获取视频长度
22 | */
23 | long getContentLength();
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/xyoye/smbplayhelper/smb/http/HttpResponse.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.smbplayhelper.smb.http;
2 |
3 | import java.io.InputStream;
4 |
5 | /**
6 | * Created by xyoye on 2019/7/15.
7 | *
8 | * 响应头封装
9 | */
10 | public class HttpResponse{
11 | //内容
12 | private InputStream contentInputStream = null;
13 |
14 | //http状态码
15 | private int statusCode = 0;
16 | //服务名
17 | private String server;
18 | //内容类型
19 | private String contentType;
20 | //内容长度
21 | private String contentLength;
22 | //内容范围
23 | private String contentRange;
24 |
25 | public HttpResponse() {
26 | String OSName = System.getProperty("os.name");
27 | String OSVersion = System.getProperty("os.version");
28 |
29 | server = OSName + "/" + OSVersion + " HTTP/1.1";
30 | contentType = "text/html; charset=\"utf-8\"";
31 | }
32 |
33 | public void setStatusCode(int code) {
34 | statusCode = code;
35 | }
36 |
37 | public void setContentType(String contentType){
38 | this.contentType = contentType;
39 | }
40 |
41 | public void setContentInputStream(InputStream inputStream){
42 | contentInputStream = inputStream;
43 | }
44 |
45 | public void setContentLength(long contentLength){
46 | this.contentLength = String.valueOf(contentLength);
47 | }
48 |
49 | public void setContentRange(long startRange, long endRange, long length){
50 | String rangeStr = "bytes ";
51 | rangeStr += startRange + "-";
52 | rangeStr += endRange + "/";
53 | rangeStr += ((0 < length) ? Long.toString(length) : "*");
54 | contentRange = rangeStr;
55 | }
56 |
57 | public String getResponseHeader() {
58 | String statusLine = "HTTP/1.1 " + statusCode + " " + HttpStatus.code2String(statusCode);
59 | return statusLine + "\r\n" +
60 | "Server: " + server + "\r\n" +
61 | "Content-Type: " + contentType + "\r\n" +
62 | "Content-Length: " + contentLength + "\r\n" +
63 | "Content-Range: " + contentRange + "\r\n";
64 | }
65 |
66 | public InputStream getContentInputStream(){
67 | return contentInputStream;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/com/xyoye/smbplayhelper/smb/http/HttpSocket.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.smbplayhelper.smb.http;
2 |
3 | import java.io.InputStream;
4 | import java.io.OutputStream;
5 | import java.net.Socket;
6 |
7 | /**
8 | * Created by xyoye on 2019/7/15.
9 | *
10 | * Socket封装
11 | */
12 | public class HttpSocket {
13 | private Socket mSocket;
14 | private InputStream socketInputStream = null;
15 | private OutputStream socketOutputStream = null;
16 |
17 | public HttpSocket(Socket socket) {
18 | this.mSocket = socket;
19 | open();
20 | }
21 |
22 | public boolean open() {
23 | try {
24 | socketInputStream = mSocket.getInputStream();
25 | socketOutputStream = mSocket.getOutputStream();
26 | } catch (Exception e) {
27 | e.printStackTrace();
28 | return false;
29 | }
30 | return true;
31 | }
32 |
33 | public void close() {
34 | try {
35 | if (socketInputStream != null) {
36 | socketInputStream.close();
37 | }
38 | if (socketOutputStream != null) {
39 | socketOutputStream.close();
40 | }
41 | mSocket.close();
42 | } catch (Exception e) {
43 | e.printStackTrace();
44 | }
45 | }
46 |
47 | @Override
48 | public void finalize() {
49 | close();
50 | }
51 |
52 | public boolean isClosed(){
53 | return mSocket.isClosed();
54 | }
55 |
56 | public InputStream getInputStream() {
57 | return socketInputStream;
58 | }
59 |
60 | public OutputStream getOutputStream() {
61 | return socketOutputStream;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/xyoye/smbplayhelper/smb/http/HttpStatus.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.smbplayhelper.smb.http;
2 |
3 | /**
4 | * Http状态码
5 | */
6 | public class HttpStatus {
7 | //请求者应当继续提出请求。服务器返回此代码则意味着,服务器已收到了请求的第一部分,现正在等待接收其余部分。
8 | public static final int CONTINUE = 100;
9 | //服务器已成功处理了请求
10 | public static final int OK = 200;
11 | //服务器成功处理了部分 GET 请求
12 | public static final int PARTIAL_CONTENT = 206;
13 | //服务器不理解请求的语法
14 | public static final int BAD_REQUEST = 400;
15 | //服务器找不到请求的网页
16 | public static final int NOT_FOUND = 404;
17 | //服务器未满足请求者在请求中设置的其中一个前提条件。
18 | public static final int PRECONDITION_FAILED = 412;
19 | //所请求的范围无法满足
20 | public static final int INVALID_RANGE = 416;
21 | //服务器遇到错误,无法完成请求
22 | public static final int INTERNAL_SERVER_ERROR = 500;
23 |
24 | // 将状态码转换成提示的字符串 ,如果没有此状态码返回一个空字符串
25 | public static String code2String(int code) {
26 | switch (code) {
27 | case CONTINUE:
28 | return "Continue";
29 | case OK:
30 | return "OK";
31 | case PARTIAL_CONTENT:
32 | return "Partial Content";
33 | case BAD_REQUEST:
34 | return "Bad Request";
35 | case NOT_FOUND:
36 | return "Not Found";
37 | case PRECONDITION_FAILED:
38 | return "Precondition Failed";
39 | case INVALID_RANGE:
40 | return "Invalid Range";
41 | case INTERNAL_SERVER_ERROR:
42 | return "Internal Server Error";
43 | }
44 | return "";
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/app/src/main/java/com/xyoye/smbplayhelper/utils/CommonUtils.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.smbplayhelper.utils;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.io.File;
6 |
7 | /**
8 | * Created by xyoye on 2019/7/23.
9 | */
10 |
11 | public class CommonUtils {
12 |
13 | /**
14 | * 判断视频格式
15 | */
16 | public static boolean isMediaFile(String fileName){
17 | switch (getFileExtension(fileName).toLowerCase()){
18 | case "3gp":
19 | case "avi":
20 | case "flv":
21 | case "mp4":
22 | case "m4v":
23 | case "mkv":
24 | case "mov":
25 | case "mpeg":
26 | case "mpg":
27 | case "mpe":
28 | case "rm":
29 | case "rmvb":
30 | case "wmv":
31 | case "asf":
32 | case "asx":
33 | case "dat":
34 | case "vob":
35 | case "m3u8":
36 | return true;
37 | default: return false;
38 | }
39 | }
40 | /**
41 | * 获取文件格式
42 | */
43 | public static String getFileExtension(final String filePath) {
44 | if (TextUtils.isEmpty(filePath)) return "";
45 | int lastPoi = filePath.lastIndexOf('.');
46 | int lastSep = filePath.lastIndexOf(File.separator);
47 | if (lastPoi == -1 || lastSep >= lastPoi) return "";
48 | return filePath.substring(lastPoi + 1);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/com/xyoye/smbplayhelper/utils/LoadingDialog.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.smbplayhelper.utils;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 | import android.os.Bundle;
6 | import android.text.TextUtils;
7 | import android.widget.TextView;
8 |
9 | import com.xyoye.smbplayhelper.R;
10 |
11 | public class LoadingDialog extends Dialog {
12 | private String msg;
13 | private TextView textView;
14 |
15 | public LoadingDialog(Context context) {
16 | super(context, R.style.LoadingDialog);
17 | }
18 |
19 | public LoadingDialog(Context context, String msg) {
20 | super(context, R.style.LoadingDialog);
21 | this.msg = msg;
22 | }
23 |
24 | public LoadingDialog(Context context, int theme) {
25 | super(context, theme);
26 | }
27 |
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.layout_loading);
33 |
34 | textView = this.findViewById(R.id.msg_tv);
35 | if (!TextUtils.isEmpty(msg)) {
36 | this.setCancelable(false);
37 | textView.setText(msg);
38 | }
39 | }
40 |
41 | public void updateText(String text) {
42 | textView.setText(text);
43 | }
44 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xyoye/smbplayhelper/utils/SPUtils.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.smbplayhelper.utils;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 | import com.xyoye.smbplayhelper.IApplication;
7 |
8 | public class SPUtils {
9 | private SharedPreferences sharedPreferences;
10 |
11 | private static class Holder {
12 | static SPUtils instance = new SPUtils();
13 | }
14 |
15 | private SPUtils() {
16 | sharedPreferences = IApplication._getContext()
17 | .getSharedPreferences("date", Context.MODE_PRIVATE);
18 | }
19 |
20 | public static SPUtils getInstance() {
21 | return Holder.instance;
22 | }
23 |
24 | public void putString(String key, String value) {
25 | SharedPreferences.Editor editor = sharedPreferences.edit();
26 | editor.putString(key, value);
27 | editor.apply();
28 | }
29 |
30 | public String getString(String key) {
31 | return sharedPreferences.getString(key, "");
32 | }
33 |
34 | public void putBoolean(String key, boolean value) {
35 | SharedPreferences.Editor editor = sharedPreferences.edit();
36 | editor.putBoolean(key, value);
37 | editor.apply();
38 | }
39 |
40 | public boolean getBoolean(String key) {
41 | return sharedPreferences.getBoolean(key, false);
42 | }
43 |
44 | public boolean getBoolean(String key, boolean defValue) {
45 | return sharedPreferences.getBoolean(key, defValue);
46 | }
47 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xyoye/smbplayhelper/utils/SmbFileAdapter.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.smbplayhelper.utils;
2 |
3 | import androidx.annotation.LayoutRes;
4 | import androidx.annotation.Nullable;
5 |
6 | import com.chad.library.adapter.base.BaseQuickAdapter;
7 | import com.chad.library.adapter.base.BaseViewHolder;
8 | import com.xyoye.libsmb.info.SmbFileInfo;
9 | import com.xyoye.smbplayhelper.R;
10 |
11 | import java.util.List;
12 |
13 | public class SmbFileAdapter extends BaseQuickAdapter {
14 |
15 | public SmbFileAdapter(@LayoutRes int layoutResId, @Nullable List data) {
16 | super(layoutResId, data);
17 | }
18 |
19 | @Override
20 | protected void convert(BaseViewHolder helper, SmbFileInfo item) {
21 | helper.setImageResource(R.id.iv, item.isDirectory() ? R.mipmap.ic_smb_folder : R.mipmap.ic_smb_video)
22 | .setText(R.id.tv, item.getFileName())
23 | .addOnClickListener(R.id.item_layout);
24 | }
25 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/background_line.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/background_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/btn_corner_blue.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
22 |
23 |
26 |
27 |
32 |
33 |
42 |
43 |
44 |
50 |
51 |
58 |
59 |
65 |
66 |
78 |
79 |
80 |
81 |
88 |
89 |
95 |
96 |
108 |
109 |
110 |
111 |
118 |
119 |
125 |
126 |
138 |
139 |
140 |
141 |
148 |
149 |
155 |
156 |
168 |
169 |
170 |
171 |
178 |
179 |
185 |
186 |
198 |
199 |
200 |
201 |
207 |
208 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
228 |
229 |
236 |
237 |
244 |
245 |
252 |
253 |
260 |
261 |
262 |
273 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_smb_file.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
19 |
20 |
21 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_smb.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
22 |
23 |
30 |
31 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/file_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_smb_folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/app/src/main/res/mipmap-xhdpi/ic_smb_folder.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_smb_video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/app/src/main/res/mipmap-xhdpi/ic_smb_video.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #2095f4
4 | #2095f4
5 | #2095f4
6 |
7 | #ffffff
8 | #333333
9 |
10 | #2095f4
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SmbPlayHelper
3 | IP:
4 | ACCOUNT:
5 | PASSWORD:
6 | DOMAIN:
7 | LOGIN
8 | 上一层
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/test/java/com/xyoye/smbplayhelper/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.smbplayhelper;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.50'
5 |
6 | repositories {
7 | google()
8 | jcenter()
9 |
10 | }
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:3.4.1'
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | google()
22 | jcenter()
23 | maven { url 'https://jitpack.io' }
24 | }
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | android.useAndroidX=true
15 | # Automatically convert third-party libraries to use AndroidX
16 | android.enableJetifier=true
17 |
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jul 12 15:28:33 CST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/hosts:
--------------------------------------------------------------------------------
1 | 127.0.0.1 localhost
2 | ::1 ip6-localhost
3 |
--------------------------------------------------------------------------------
/libsmb/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/libsmb/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.2"
6 |
7 |
8 | defaultConfig {
9 | minSdkVersion 19
10 | targetSdkVersion 29
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
15 | consumerProguardFiles 'consumer-rules.pro'
16 | }
17 |
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | lintOptions {
25 | disable 'InvalidPackage'
26 | }
27 | }
28 |
29 | dependencies {
30 | implementation fileTree(include: ['*.jar'], dir: 'libs')
31 | implementation 'androidx.appcompat:appcompat:1.1.0'
32 | testImplementation 'junit:junit:4.12'
33 | androidTestImplementation 'androidx.test.ext:junit:1.1.1'
34 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
35 |
36 | implementation files('libs/smbj-rpc.jar')
37 | implementation files('libs/jcifs-origin.jar')
38 | implementation files('libs/asn-one-0.4.0.jar')
39 | implementation files('libs/jcifs-ng-2.1.3.jar')
40 | implementation files('libs/smbj-0.9.1.jar')
41 | implementation files('libs/mbassador-1.3.0.jar')
42 | implementation files('libs/slf4j-api-1.7.25.jar')
43 | implementation files('libs/bcprov-jdk15on-1.61.jar')
44 |
45 | implementation ('de.psdev.slf4j-android-logger:slf4j-android-logger:1.0.5'){
46 | exclude group:'org.slf4j'
47 | }
48 | }
49 |
50 | task makeJar(type: Jar) {
51 | archivesBaseName = "libsmb"
52 | from(project.zipTree('build/intermediates/packaged-classes/release/classes.jar'))
53 | from(project.zipTree('build/intermediates/packaged-classes/release/libs/jcifs-origin.jar'))
54 | from(project.zipTree('build/intermediates/packaged-classes/release/libs/smbj-rpc.jar'))
55 | from(project.zipTree('build/intermediates/packaged-classes/release/libs/asn-one-0.4.0.jar'))
56 | from(project.zipTree('build/intermediates/packaged-classes/release/libs/jcifs-ng-2.1.3.jar'))
57 | from(project.zipTree('build/intermediates/packaged-classes/release/libs/smbj-0.9.1.jar'))
58 | from(project.zipTree('build/intermediates/packaged-classes/release/libs/mbassador-1.3.0.jar'))
59 | from(project.zipTree('build/intermediates/packaged-classes/release/libs/slf4j-api-1.7.25.jar'))
60 | from(project.zipTree('build/intermediates/packaged-classes/release/libs/bcprov-jdk15on-1.61.jar'))
61 | destinationDir = file('build/libs')
62 | }
63 | makeJar.dependsOn(build)
--------------------------------------------------------------------------------
/libsmb/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/libsmb/consumer-rules.pro
--------------------------------------------------------------------------------
/libsmb/libs/asn-one-0.4.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/libsmb/libs/asn-one-0.4.0.jar
--------------------------------------------------------------------------------
/libsmb/libs/bcprov-jdk15on-1.61.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/libsmb/libs/bcprov-jdk15on-1.61.jar
--------------------------------------------------------------------------------
/libsmb/libs/jcifs-ng-2.1.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/libsmb/libs/jcifs-ng-2.1.3.jar
--------------------------------------------------------------------------------
/libsmb/libs/jcifs-origin.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/libsmb/libs/jcifs-origin.jar
--------------------------------------------------------------------------------
/libsmb/libs/mbassador-1.3.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/libsmb/libs/mbassador-1.3.0.jar
--------------------------------------------------------------------------------
/libsmb/libs/slf4j-api-1.7.25.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/libsmb/libs/slf4j-api-1.7.25.jar
--------------------------------------------------------------------------------
/libsmb/libs/smbj-0.9.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/libsmb/libs/smbj-0.9.1.jar
--------------------------------------------------------------------------------
/libsmb/libs/smbj-rpc.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xyoye/SmbPlayHelper/48bbc8fbdbf6b320c3fcf273f45c4ba1dd171b09/libsmb/libs/smbj-rpc.jar
--------------------------------------------------------------------------------
/libsmb/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/libsmb/src/androidTest/java/com/xyoye/libsmb/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.libsmb;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 |
25 | assertEquals("com.xyoye.libsmb.test", appContext.getPackageName());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/libsmb/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/libsmb/src/main/java/com/xyoye/libsmb/SmbManager.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.libsmb;
2 |
3 | import com.xyoye.libsmb.controller.Controller;
4 | import com.xyoye.libsmb.controller.JCIFSController;
5 | import com.xyoye.libsmb.controller.JCIFS_NGController;
6 | import com.xyoye.libsmb.controller.SMBJController;
7 | import com.xyoye.libsmb.controller.SMBJ_RPCController;
8 | import com.xyoye.libsmb.exception.SmbLinkException;
9 | import com.xyoye.libsmb.info.SmbLinkInfo;
10 | import com.xyoye.libsmb.info.SmbType;
11 | import com.xyoye.libsmb.utils.SmbUtils;
12 |
13 | /**
14 | * Created by xyoye on 2019/12/20.
15 | */
16 |
17 | public class SmbManager {
18 | private SmbType mSmbType;
19 | private boolean isLinked;
20 | private Controller controller;
21 | private SmbLinkException smbLinkException;
22 |
23 | private boolean smbJRPCEnable = true;
24 | private boolean smbJEnable = true;
25 | private boolean jcifsNGEnable = true;
26 | private boolean jcifsEnable = true;
27 |
28 | private static class Holder {
29 | static SmbManager instance = new SmbManager();
30 | }
31 |
32 | private SmbManager() {
33 | smbLinkException = new SmbLinkException();
34 | }
35 |
36 | public static SmbManager getInstance() {
37 | return Holder.instance;
38 | }
39 |
40 | /**
41 | * link to the smb server from smbV2 to smbV1
42 | *
43 | * @param smbLinkInfo link data
44 | */
45 | public boolean linkStart(SmbLinkInfo smbLinkInfo) {
46 |
47 | smbLinkException.clearException();
48 |
49 | if (!smbLinkInfo.isAnonymous()) {
50 | if (SmbUtils.containsEmptyText(smbLinkInfo.getAccount(), smbLinkInfo.getAccount())) {
51 | throw new NullPointerException("Account And Password Must NotNull");
52 | }
53 | }
54 |
55 | //SMB V2
56 | isLinked = true;
57 |
58 | if (jcifsNGEnable) {
59 | controller = new JCIFS_NGController();
60 | if (controller.linkStart(smbLinkInfo, smbLinkException)) {
61 | mSmbType = SmbType.JCIFS_NG;
62 | return true;
63 | }
64 | }
65 |
66 | if (smbJRPCEnable) {
67 | controller = new SMBJ_RPCController();
68 | if (controller.linkStart(smbLinkInfo, smbLinkException)) {
69 | mSmbType = SmbType.SMBJ_RPC;
70 | return true;
71 | }
72 | }
73 |
74 | if (smbJEnable && !SmbUtils.isTextEmpty(smbLinkInfo.getRootFolder())) {
75 | controller = new SMBJController();
76 | if (controller.linkStart(smbLinkInfo, smbLinkException)) {
77 | mSmbType = SmbType.SMBJ;
78 | return true;
79 | }
80 | }
81 |
82 | //SMB V1
83 | if (jcifsEnable) {
84 | controller = new JCIFSController();
85 | if (controller.linkStart(smbLinkInfo, smbLinkException)) {
86 | mSmbType = SmbType.JCIFS;
87 | return true;
88 | }
89 | }
90 |
91 | isLinked = false;
92 | return false;
93 | }
94 |
95 | /**
96 | * get smb tools type
97 | */
98 | public String getSmbType() {
99 | return mSmbType == null ? "" : SmbType.getTypeName(mSmbType);
100 | }
101 |
102 | /**
103 | * is the link successful
104 | */
105 | public boolean isLinked() {
106 | return isLinked;
107 | }
108 |
109 | /**
110 | * get link controller
111 | */
112 | public Controller getController() {
113 | return controller;
114 | }
115 |
116 | /**
117 | * link error info
118 | */
119 | public SmbLinkException getException() {
120 | return smbLinkException;
121 | }
122 |
123 | public void setEnable(boolean jcifsNGEnable, boolean smbJRPCEnable, boolean smbJEnable, boolean jcifsEnable) {
124 | this.jcifsNGEnable = jcifsNGEnable;
125 | this.smbJRPCEnable = smbJRPCEnable;
126 | this.smbJEnable = smbJEnable;
127 | this.jcifsEnable = jcifsEnable;
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/libsmb/src/main/java/com/xyoye/libsmb/controller/Controller.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.libsmb.controller;
2 |
3 | import androidx.annotation.Nullable;
4 |
5 | import com.xyoye.libsmb.info.SmbFileInfo;
6 | import com.xyoye.libsmb.info.SmbLinkInfo;
7 | import com.xyoye.libsmb.exception.SmbLinkException;
8 |
9 | import java.io.InputStream;
10 | import java.util.List;
11 |
12 | /**
13 | * Created by xyoye on 2019/12/20.
14 | */
15 |
16 | public interface Controller {
17 |
18 | /**
19 | * link to smb server
20 | * @param smbLinkInfo link data
21 | * @param exception if link fails, put the error message in the exception
22 | * @return is the link successful
23 | */
24 | boolean linkStart(SmbLinkInfo smbLinkInfo, SmbLinkException exception);
25 |
26 | /**
27 | * get parent file list info
28 | */
29 | List getParentList();
30 |
31 | /**
32 | * get self file list info
33 | */
34 | List getSelfList();
35 |
36 | /**
37 | * get child file list info
38 | * @param dirName child directory file name
39 | */
40 | List getChildList(String dirName);
41 |
42 | /**
43 | * get file input stream
44 | * @param fileName file name
45 | */
46 | @Nullable
47 | InputStream getFileInputStream(String fileName);
48 |
49 | /**
50 | * get file length
51 | * @param fileName file name
52 | */
53 | long getFileLength(String fileName);
54 |
55 | /**
56 | * get current path
57 | */
58 | String getCurrentPath();
59 |
60 | /**
61 | * self directory is root directory
62 | */
63 | boolean isRootDir();
64 |
65 | void release();
66 | }
67 |
--------------------------------------------------------------------------------
/libsmb/src/main/java/com/xyoye/libsmb/controller/JCIFSController.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.libsmb.controller;
2 |
3 | import com.xyoye.jcifs_origin.smb.SmbException;
4 | import com.xyoye.jcifs_origin.smb.SmbFile;
5 | import com.xyoye.libsmb.exception.SmbLinkException;
6 | import com.xyoye.libsmb.info.SmbFileInfo;
7 | import com.xyoye.libsmb.info.SmbLinkInfo;
8 | import com.xyoye.libsmb.info.SmbType;
9 |
10 | import java.io.IOException;
11 | import java.io.InputStream;
12 | import java.net.MalformedURLException;
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | /**
17 | * Created by xyoye on 2019/12/20.
18 | */
19 |
20 | public class JCIFSController implements Controller {
21 | private static final String RootFlag = "/";
22 |
23 | private String mPath;
24 | private String mAuthUrl;
25 | private List rootFileList;
26 |
27 | private InputStream inputStream;
28 |
29 | @Override
30 | public boolean linkStart(SmbLinkInfo smbLinkInfo, SmbLinkException exception) {
31 |
32 | //build smb url
33 | mAuthUrl = "smb://" + (smbLinkInfo.isAnonymous()
34 | ? smbLinkInfo.getIP()
35 | : smbLinkInfo.getAccount() + ":" + smbLinkInfo.getPassword() + "@" + smbLinkInfo.getIP()
36 | );
37 |
38 | try {
39 | SmbFile smbFile = new SmbFile(mAuthUrl);
40 | rootFileList = getFileInfoList(smbFile.listFiles());
41 |
42 | mPath = RootFlag;
43 | return true;
44 | } catch (Exception e) {
45 | e.printStackTrace();
46 | exception.addException(SmbType.JCIFS, e.getMessage());
47 | }
48 | return false;
49 | }
50 |
51 | @Override
52 | public List getParentList() {
53 | if (isRootDir())
54 | return new ArrayList<>();
55 |
56 | List fileInfoList = new ArrayList<>();
57 | try {
58 | //is first directory like smbJ share
59 | String parentPath = mPath.substring(0, mPath.length() - 1);
60 | int index = parentPath.indexOf("/", 1);
61 |
62 | //get parent path index
63 | int endIndex = parentPath.lastIndexOf("/");
64 | mPath = mPath.substring(0, endIndex) + "/";
65 |
66 | if (index == -1)
67 | return rootFileList;
68 |
69 | SmbFile smbFile = new SmbFile(mAuthUrl + mPath);
70 | if (smbFile.isDirectory() && smbFile.canRead()) {
71 | fileInfoList.addAll(getFileInfoList(smbFile.listFiles()));
72 | }
73 | } catch (MalformedURLException | SmbException e) {
74 | e.printStackTrace();
75 | }
76 |
77 | return fileInfoList;
78 | }
79 |
80 | @Override
81 | public List getSelfList() {
82 | if (isRootDir())
83 | return rootFileList;
84 |
85 | List fileInfoList = new ArrayList<>();
86 | try {
87 | SmbFile smbFile = new SmbFile(mAuthUrl + mPath);
88 | if (smbFile.isDirectory() && smbFile.canRead()) {
89 | fileInfoList.addAll(getFileInfoList(smbFile.listFiles()));
90 | }
91 | } catch (MalformedURLException | SmbException e) {
92 | e.printStackTrace();
93 | }
94 |
95 | return fileInfoList;
96 | }
97 |
98 | @Override
99 | public List getChildList(String dirName) {
100 | List fileInfoList = new ArrayList<>();
101 | try {
102 | mPath += dirName + "/";
103 | SmbFile smbFile = new SmbFile(mAuthUrl + mPath);
104 | if (smbFile.isDirectory() && smbFile.canRead()) {
105 | fileInfoList.addAll(getFileInfoList(smbFile.listFiles()));
106 | }
107 | } catch (MalformedURLException | SmbException e) {
108 | e.printStackTrace();
109 | }
110 |
111 | return fileInfoList;
112 | }
113 |
114 | @Override
115 | public InputStream getFileInputStream(String fileName) {
116 | try {
117 | String path = mPath + fileName + "/";
118 | SmbFile smbFile = new SmbFile(mAuthUrl + path);
119 | if (smbFile.isFile() && smbFile.canRead()) {
120 | inputStream = smbFile.getInputStream();
121 | return inputStream;
122 | }
123 | } catch (IOException e) {
124 | e.printStackTrace();
125 | }
126 |
127 | return null;
128 | }
129 |
130 | @Override
131 | public long getFileLength(String fileName) {
132 | try {
133 | String filePath = mPath + fileName + "/";
134 | SmbFile smbFile = new SmbFile(mAuthUrl + filePath);
135 | return smbFile.getContentLength();
136 | } catch (MalformedURLException e) {
137 | e.printStackTrace();
138 | }
139 | return 0;
140 | }
141 |
142 | @Override
143 | public String getCurrentPath() {
144 | return mPath.length() == 1 ? mPath : mPath.substring(0, mPath.length() - 1);
145 | }
146 |
147 | @Override
148 | public boolean isRootDir() {
149 | return RootFlag.equals(mPath);
150 | }
151 |
152 | @Override
153 | public void release() {
154 |
155 | }
156 |
157 | private List getFileInfoList(SmbFile[] smbFiles) {
158 | List fileInfoList = new ArrayList<>();
159 | for (SmbFile smbFile : smbFiles) {
160 | boolean isDirectory = true;
161 | try {
162 | isDirectory = smbFile.isDirectory();
163 | } catch (SmbException e) {
164 | e.printStackTrace();
165 | }
166 |
167 | //remove / at the end of the path
168 | String smbFileName = smbFile.getName();
169 | smbFileName = smbFileName.endsWith("/")
170 | ? smbFileName.substring(0, smbFileName.length() - 1)
171 | : smbFileName;
172 |
173 | fileInfoList.add(new SmbFileInfo(smbFileName, isDirectory));
174 | }
175 |
176 | return fileInfoList;
177 | }
178 | }
179 |
--------------------------------------------------------------------------------
/libsmb/src/main/java/com/xyoye/libsmb/controller/JCIFS_NGController.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.libsmb.controller;
2 |
3 | import com.xyoye.libsmb.exception.SmbLinkException;
4 | import com.xyoye.libsmb.info.SmbFileInfo;
5 | import com.xyoye.libsmb.info.SmbLinkInfo;
6 | import com.xyoye.libsmb.info.SmbType;
7 |
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.net.MalformedURLException;
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import java.util.Properties;
14 |
15 | import jcifs.Address;
16 | import jcifs.CIFSContext;
17 | import jcifs.config.PropertyConfiguration;
18 | import jcifs.context.BaseContext;
19 | import jcifs.smb.NtlmPasswordAuthenticator;
20 | import jcifs.smb.SmbException;
21 | import jcifs.smb.SmbFile;
22 |
23 | /**
24 | * Created by xyoye on 2019/12/20.
25 | */
26 |
27 | public class JCIFS_NGController implements Controller {
28 | private static final String RootFlag = "/";
29 |
30 | private String mPath;
31 | private String mAuthUrl;
32 | private CIFSContext cifsContext;
33 | private List rootFileList;
34 |
35 | private InputStream inputStream;
36 |
37 | @Override
38 | public boolean linkStart(SmbLinkInfo smbLinkInfo, SmbLinkException exception) {
39 | try {
40 | //build smb url
41 | mAuthUrl = "smb://" + (smbLinkInfo.isAnonymous()
42 | ? smbLinkInfo.getIP()
43 | : smbLinkInfo.getAccount() + ":" + smbLinkInfo.getPassword() + "@" + smbLinkInfo.getIP()
44 | );
45 |
46 | NtlmPasswordAuthenticator auth = new NtlmPasswordAuthenticator(
47 | smbLinkInfo.getDomain(), smbLinkInfo.getAccount(), smbLinkInfo.getPassword());
48 |
49 | // set config
50 | Properties properties = new Properties();
51 | properties.setProperty("jcifs.smb.client.responseTimeout", "5000");
52 | PropertyConfiguration configuration = new PropertyConfiguration(properties);
53 |
54 | cifsContext = new BaseContext(configuration).withCredentials(auth);
55 | Address address = cifsContext.getNameServiceClient().getByName(smbLinkInfo.getIP());
56 | cifsContext.getTransportPool().logon(cifsContext, address);
57 |
58 | SmbFile rootFile = new SmbFile(mAuthUrl, cifsContext);
59 | rootFileList = getFileInfoList(rootFile.listFiles());
60 |
61 | mPath = RootFlag;
62 |
63 | return true;
64 | } catch (Exception e) {
65 | e.printStackTrace();
66 | exception.addException(SmbType.JCIFS_NG, e.getMessage());
67 | }
68 | return false;
69 | }
70 |
71 | @Override
72 | public List getParentList() {
73 | if (isRootDir())
74 | return new ArrayList<>();
75 |
76 | List fileInfoList = new ArrayList<>();
77 | try {
78 | //is first directory like smbJ share
79 | String parentPath = mPath.substring(0, mPath.length() - 1);
80 | int index = parentPath.indexOf("/", 1);
81 |
82 | //get parent path index
83 | int endIndex = parentPath.lastIndexOf("/");
84 | mPath = mPath.substring(0, endIndex) + "/";
85 |
86 | if (index == -1)
87 | return rootFileList;
88 |
89 | SmbFile smbFile = new SmbFile(mAuthUrl + mPath, cifsContext);
90 | if (smbFile.isDirectory() && smbFile.canRead()) {
91 | fileInfoList.addAll(getFileInfoList(smbFile.listFiles()));
92 | }
93 | } catch (MalformedURLException | SmbException e) {
94 | e.printStackTrace();
95 | }
96 |
97 | return fileInfoList;
98 | }
99 |
100 | @Override
101 | public List getSelfList() {
102 | if (isRootDir())
103 | return rootFileList;
104 |
105 | List fileInfoList = new ArrayList<>();
106 | try {
107 | SmbFile smbFile = new SmbFile(mAuthUrl + mPath, cifsContext);
108 | if (smbFile.isDirectory() && smbFile.canRead()) {
109 | fileInfoList.addAll(getFileInfoList(smbFile.listFiles()));
110 | }
111 | } catch (MalformedURLException | SmbException e) {
112 | e.printStackTrace();
113 | }
114 |
115 | return fileInfoList;
116 | }
117 |
118 | @Override
119 | public List getChildList(String dirName) {
120 | List fileInfoList = new ArrayList<>();
121 | try {
122 | mPath += dirName + "/";
123 | SmbFile smbFile = new SmbFile(mAuthUrl + mPath, cifsContext);
124 | if (smbFile.isDirectory() && smbFile.canRead()) {
125 | fileInfoList.addAll(getFileInfoList(smbFile.listFiles()));
126 | }
127 | } catch (MalformedURLException | SmbException e) {
128 | e.printStackTrace();
129 | }
130 |
131 | return fileInfoList;
132 | }
133 |
134 | @Override
135 | public InputStream getFileInputStream(String fileName) {
136 | try {
137 | String filePath = mPath + fileName + "/";
138 | SmbFile smbFile = new SmbFile(mAuthUrl + filePath, cifsContext);
139 | if (smbFile.isFile() && smbFile.canRead()) {
140 | inputStream = smbFile.getInputStream();
141 | return inputStream;
142 | }
143 | } catch (IOException e) {
144 | e.printStackTrace();
145 | }
146 |
147 | return null;
148 | }
149 |
150 | @Override
151 | public long getFileLength(String fileName) {
152 | try {
153 | String filePath = mPath + fileName + "/";
154 | SmbFile smbFile = new SmbFile(mAuthUrl + filePath, cifsContext);
155 | if (smbFile.isFile() && smbFile.canRead()) {
156 | return smbFile.getContentLengthLong();
157 | }
158 | } catch (IOException e) {
159 | e.printStackTrace();
160 | }
161 | return 0;
162 | }
163 |
164 | @Override
165 | public String getCurrentPath() {
166 | return mPath.length() == 1 ? mPath : mPath.substring(0, mPath.length() - 1);
167 | }
168 |
169 | @Override
170 | public boolean isRootDir() {
171 | return RootFlag.equals(mPath);
172 | }
173 |
174 | @Override
175 | public void release() {
176 | try {
177 | if (cifsContext != null)
178 | cifsContext.close();
179 | } catch (IOException e) {
180 | e.printStackTrace();
181 | }
182 | }
183 |
184 | private List getFileInfoList(SmbFile[] smbFiles) {
185 | List fileInfoList = new ArrayList<>();
186 | for (SmbFile smbFile : smbFiles) {
187 | boolean isDirectory = false;
188 | try {
189 | isDirectory = smbFile.isDirectory();
190 | } catch (SmbException ignore) {
191 | }
192 |
193 | //remove / at the end of the path
194 | String smbFileName = smbFile.getName();
195 | smbFileName = smbFileName.endsWith("/")
196 | ? smbFileName.substring(0, smbFileName.length() - 1)
197 | : smbFileName;
198 |
199 | fileInfoList.add(new SmbFileInfo(smbFileName, isDirectory));
200 | }
201 |
202 | return fileInfoList;
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/libsmb/src/main/java/com/xyoye/libsmb/controller/SMBJController.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.libsmb.controller;
2 |
3 | import com.hierynomus.msdtyp.AccessMask;
4 | import com.hierynomus.msfscc.fileinformation.FileIdBothDirectoryInformation;
5 | import com.hierynomus.msfscc.fileinformation.FileStandardInformation;
6 | import com.hierynomus.mssmb2.SMB2CreateDisposition;
7 | import com.hierynomus.mssmb2.SMB2ShareAccess;
8 | import com.hierynomus.smbj.SMBClient;
9 | import com.hierynomus.smbj.SmbConfig;
10 | import com.hierynomus.smbj.auth.AuthenticationContext;
11 | import com.hierynomus.smbj.connection.Connection;
12 | import com.hierynomus.smbj.session.Session;
13 | import com.hierynomus.smbj.share.Directory;
14 | import com.hierynomus.smbj.share.DiskEntry;
15 | import com.hierynomus.smbj.share.DiskShare;
16 | import com.hierynomus.smbj.share.File;
17 | import com.xyoye.libsmb.exception.SmbLinkException;
18 | import com.xyoye.libsmb.info.SmbFileInfo;
19 | import com.xyoye.libsmb.info.SmbLinkInfo;
20 | import com.xyoye.libsmb.info.SmbType;
21 | import com.xyoye.libsmb.utils.SmbUtils;
22 |
23 | import java.io.IOException;
24 | import java.io.InputStream;
25 | import java.util.ArrayList;
26 | import java.util.EnumSet;
27 | import java.util.List;
28 | import java.util.concurrent.TimeUnit;
29 |
30 | import static com.hierynomus.mssmb2.SMB2CreateDisposition.FILE_OPEN;
31 |
32 | /**
33 | * Created by xyoye on 2019/12/20.
34 | */
35 |
36 | public class SMBJController implements Controller {
37 |
38 | private String ROOT_FLAG = "\\";
39 | private String mPath;
40 | private DiskShare diskShare;
41 | private List rootFileList;
42 |
43 | private SMBClient smbClient;
44 | private Connection connection;
45 | private Session session;
46 | private InputStream inputStream;
47 |
48 | @Override
49 | public boolean linkStart(SmbLinkInfo smbLinkInfo, SmbLinkException exception) {
50 | String rootFolder = smbLinkInfo.getRootFolder();
51 | if (SmbUtils.isTextEmpty(rootFolder)) {
52 | exception.addException(SmbType.SMBJ, "Root Folder Must Not Empty");
53 | return false;
54 | }
55 |
56 | SmbConfig smbConfig = SmbConfig.builder()
57 | .withTimeout(5, TimeUnit.SECONDS)
58 | .withTimeout(5, TimeUnit.SECONDS)
59 | .withSoTimeout(5, TimeUnit.SECONDS)
60 | .build();
61 |
62 | try {
63 | smbClient = new SMBClient(smbConfig);
64 | connection = smbClient.connect(smbLinkInfo.getIP());
65 | AuthenticationContext ac = new AuthenticationContext(
66 | smbLinkInfo.getAccount(), smbLinkInfo.getPassword().toCharArray(), smbLinkInfo.getDomain());
67 | session = connection.authenticate(ac);
68 |
69 | ROOT_FLAG += smbLinkInfo.getRootFolder();
70 | mPath = ROOT_FLAG;
71 |
72 | diskShare = (DiskShare) session.connectShare(smbLinkInfo.getRootFolder());
73 | rootFileList = getFileInfoList(diskShare.list(""), diskShare);
74 |
75 | return true;
76 | } catch (Exception e) {
77 | e.printStackTrace();
78 | exception.addException(SmbType.SMBJ, e.getMessage());
79 | }
80 | return false;
81 | }
82 |
83 | @Override
84 | public List getParentList() {
85 | if (isRootDir()) {
86 | return new ArrayList<>();
87 | }
88 |
89 | //get parent path by mPath
90 | int startIndex = mPath.indexOf("\\", 1) + 1;
91 | int endIndex = mPath.lastIndexOf("\\");
92 | String parentPath = startIndex >= endIndex ? "" : mPath.substring(startIndex, endIndex);
93 |
94 | mPath = mPath.substring(0, endIndex);
95 |
96 | List infoList = new ArrayList<>();
97 | try {
98 | //get folder normal info by path
99 | Directory parentDir = openDirectory(diskShare, parentPath);
100 | List parentDirInfoList = parentDir.list();
101 | //get folder detail info
102 | infoList.addAll(getFileInfoList(parentDirInfoList, diskShare));
103 | } catch (Exception e) {
104 | e.printStackTrace();
105 | }
106 | return infoList;
107 | }
108 |
109 | @Override
110 | public List getSelfList() {
111 | if (isRootDir())
112 | return rootFileList;
113 |
114 | List infoList = new ArrayList<>();
115 | try {
116 | Directory selfDir = openDirectory(diskShare, getPathNotShare(""));
117 | List selfDirInfoList = selfDir.list();
118 |
119 | infoList.addAll(getFileInfoList(selfDirInfoList, diskShare));
120 | } catch (Exception e) {
121 | e.printStackTrace();
122 | }
123 | return infoList;
124 | }
125 |
126 | @Override
127 | public List getChildList(String dirName) {
128 | List infoList = new ArrayList<>();
129 | try {
130 |
131 | Directory childDir = openDirectory(diskShare, getPathNotShare(dirName));
132 | List childDirInfoList = childDir.list();
133 |
134 | mPath += "\\" + dirName;
135 | infoList.addAll(getFileInfoList(childDirInfoList, diskShare));
136 | } catch (Exception e) {
137 | e.printStackTrace();
138 | }
139 | return infoList;
140 | }
141 |
142 | @Override
143 | public InputStream getFileInputStream(String fileName) {
144 | String filePath = getPathNotShare(fileName);
145 |
146 | try {
147 | File file = openFile(diskShare, filePath);
148 | inputStream = file.getInputStream();
149 | return inputStream;
150 | } catch (Exception e) {
151 | e.printStackTrace();
152 | }
153 | return null;
154 | }
155 |
156 | @Override
157 | public long getFileLength(String fileName) {
158 | String filePath = getPathNotShare(fileName);
159 |
160 | try {
161 | File file = openFile(diskShare, filePath);
162 | FileStandardInformation standardInfo = file.getFileInformation(FileStandardInformation.class);
163 | return standardInfo.getEndOfFile();
164 | } catch (Exception e) {
165 | e.printStackTrace();
166 | }
167 | return 0;
168 | }
169 |
170 | @Override
171 | public String getCurrentPath() {
172 | return mPath.length() == 0 ? "/" : mPath.replace("\\", "/");
173 | }
174 |
175 | @Override
176 | public boolean isRootDir() {
177 | return mPath.equals(ROOT_FLAG);
178 | }
179 |
180 | @Override
181 | public void release() {
182 | try {
183 | if (inputStream != null)
184 | inputStream.close();
185 | if (diskShare != null)
186 | diskShare.close();
187 | if (session != null)
188 | session.close();
189 | if (connection != null)
190 | connection.close();
191 | if (smbClient != null)
192 | smbClient.close();
193 | } catch (IOException e) {
194 | e.printStackTrace();
195 | }
196 | }
197 |
198 | /**
199 | * traversal directory info list filtering does not use folders and get file types
200 | *
201 | * @param dirInfoList directory list
202 | * @param diskShare share
203 | * @return file info list
204 | */
205 | private List getFileInfoList(List dirInfoList, DiskShare diskShare) {
206 | List fileInfoList = new ArrayList<>();
207 | for (FileIdBothDirectoryInformation dirInfo : dirInfoList) {
208 | //ignore directories beginning with '.', like '.', '..'
209 | if (dirInfo.getFileName().startsWith("."))
210 | continue;
211 |
212 | //get file standard info by disk entry because file type unknown
213 | DiskEntry diskEntry = openDiskEntry(diskShare, getPathNotShare(dirInfo.getFileName()));
214 | FileStandardInformation standardInformation = diskEntry.getFileInformation(FileStandardInformation.class);
215 | fileInfoList.add(new SmbFileInfo(dirInfo.getFileName(), standardInformation.isDirectory()));
216 | }
217 | return fileInfoList;
218 | }
219 |
220 | /**
221 | * splicing child file name to mPath and removing shareName
222 | *
223 | * @param fileName child file name
224 | * @return child file path
225 | */
226 | private String getPathNotShare(String fileName) {
227 | int index = mPath.indexOf("\\", 1);
228 | if (index == -1) {
229 | return fileName;
230 | } else {
231 | fileName = fileName.length() == 0 ? "" : ("\\" + fileName);
232 | return mPath.substring(index + 1) + fileName;
233 | }
234 | }
235 |
236 | /**
237 | * get smb file, just need reed permission
238 | *
239 | * @param share share
240 | * @param filePath file path not share name
241 | * @return smb file
242 | */
243 | private File openFile(DiskShare share, String filePath) {
244 | return share.openFile(filePath,
245 | EnumSet.of(AccessMask.FILE_READ_DATA),
246 | null,
247 | SMB2ShareAccess.ALL,
248 | FILE_OPEN,
249 | null);
250 | }
251 |
252 | /**
253 | * get smb directory, just need reed permission
254 | *
255 | * @param share share
256 | * @param filePath directory path not share name
257 | * @return smb directory
258 | */
259 | private Directory openDirectory(DiskShare share, String filePath) {
260 | return share.openDirectory(
261 | filePath,
262 | EnumSet.of(AccessMask.GENERIC_READ),
263 | null,
264 | SMB2ShareAccess.ALL,
265 | SMB2CreateDisposition.FILE_OPEN,
266 | null);
267 | }
268 |
269 | /**
270 | * get smb disk entry, just need reed permission
271 | *
272 | * @param share share
273 | * @param filePath file or directory path nor share name
274 | * @return dis entry
275 | */
276 | private DiskEntry openDiskEntry(DiskShare share, String filePath) {
277 | return share.open(
278 | filePath,
279 | EnumSet.of(AccessMask.GENERIC_READ),
280 | null,
281 | SMB2ShareAccess.ALL,
282 | FILE_OPEN,
283 | null);
284 | }
285 | }
286 |
--------------------------------------------------------------------------------
/libsmb/src/main/java/com/xyoye/libsmb/controller/SMBJ_RPCController.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.libsmb.controller;
2 |
3 | import com.hierynomus.msdtyp.AccessMask;
4 | import com.hierynomus.msfscc.fileinformation.FileIdBothDirectoryInformation;
5 | import com.hierynomus.msfscc.fileinformation.FileStandardInformation;
6 | import com.hierynomus.mssmb2.SMB2CreateDisposition;
7 | import com.hierynomus.mssmb2.SMB2ShareAccess;
8 | import com.hierynomus.smbj.SMBClient;
9 | import com.hierynomus.smbj.SmbConfig;
10 | import com.hierynomus.smbj.auth.AuthenticationContext;
11 | import com.hierynomus.smbj.connection.Connection;
12 | import com.hierynomus.smbj.session.Session;
13 | import com.hierynomus.smbj.share.Directory;
14 | import com.hierynomus.smbj.share.DiskEntry;
15 | import com.hierynomus.smbj.share.DiskShare;
16 | import com.hierynomus.smbj.share.File;
17 | import com.rapid7.client.dcerpc.mssrvs.ServerService;
18 | import com.rapid7.client.dcerpc.mssrvs.dto.NetShareInfo0;
19 | import com.rapid7.client.dcerpc.transport.RPCTransport;
20 | import com.rapid7.client.dcerpc.transport.SMBTransportFactories;
21 | import com.xyoye.libsmb.exception.SmbLinkException;
22 | import com.xyoye.libsmb.info.SmbFileInfo;
23 | import com.xyoye.libsmb.info.SmbLinkInfo;
24 | import com.xyoye.libsmb.info.SmbType;
25 |
26 | import java.io.IOException;
27 | import java.io.InputStream;
28 | import java.util.ArrayList;
29 | import java.util.EnumSet;
30 | import java.util.List;
31 | import java.util.concurrent.TimeUnit;
32 |
33 | import static com.hierynomus.mssmb2.SMB2CreateDisposition.FILE_OPEN;
34 |
35 | /**
36 | * Created by xyoye on 2019/12/20.
37 | */
38 |
39 | public class SMBJ_RPCController implements Controller {
40 | private static final String ROOT_FLAG = "";
41 |
42 | private String mPath;
43 | private List rootFileList;
44 |
45 | private SMBClient smbClient;
46 | private Session session;
47 | private Connection smbConnection;
48 | private DiskShare diskShare;
49 | private InputStream inputStream;
50 |
51 | public SMBJ_RPCController() {
52 | rootFileList = new ArrayList<>();
53 | }
54 |
55 | @Override
56 | public boolean linkStart(SmbLinkInfo smbLinkInfo, SmbLinkException exception) {
57 |
58 | //set smb config
59 | SmbConfig smbConfig = SmbConfig.builder()
60 | .withTimeout(5, TimeUnit.SECONDS)
61 | .withTimeout(5, TimeUnit.SECONDS)
62 | .withSoTimeout(5, TimeUnit.SECONDS)
63 | .build();
64 |
65 | try {
66 | smbClient = new SMBClient(smbConfig);
67 | smbConnection = smbClient.connect(smbLinkInfo.getIP());
68 | AuthenticationContext authContext = new AuthenticationContext(
69 | smbLinkInfo.getAccount(), smbLinkInfo.getPassword().toCharArray(), smbLinkInfo.getDomain());
70 | session = smbConnection.authenticate(authContext);
71 |
72 | RPCTransport transport = SMBTransportFactories.SRVSVC.getTransport(session);
73 | ServerService serverService = new ServerService(transport);
74 | List shareInfoList = serverService.getShares0();
75 |
76 | mPath = ROOT_FLAG;
77 |
78 | //get root directory file list
79 | rootFileList = getFileInfoList(shareInfoList);
80 |
81 | return true;
82 | } catch (Exception e) {
83 | e.printStackTrace();
84 | exception.addException(SmbType.SMBJ_RPC, e.getMessage());
85 | }
86 | return false;
87 | }
88 |
89 | @Override
90 | public List getParentList() {
91 | //root directory not parent
92 | if (isRootDir())
93 | return new ArrayList<>();
94 |
95 | List infoList = new ArrayList<>();
96 | int index = mPath.indexOf("\\", 1);
97 | if (index == -1) {
98 | //in share directory, its parent is root directory
99 | mPath = ROOT_FLAG;
100 | return rootFileList;
101 | } else {
102 | try {
103 | //get parent path by mPath
104 | int startIndex = mPath.indexOf("\\", 1) + 1;
105 | int endIndex = mPath.lastIndexOf("\\");
106 | String parentPath = startIndex >= endIndex ? "" : mPath.substring(startIndex, endIndex);
107 |
108 | mPath = mPath.substring(0, endIndex);
109 | //get folder normal info by path
110 | Directory parentDir = openDirectory(diskShare, parentPath);
111 | List parentDirInfoList = parentDir.list();
112 | //get folder detail info
113 | infoList.addAll(getFileInfoList(parentDirInfoList, diskShare));
114 | } catch (Exception e) {
115 | e.printStackTrace();
116 | }
117 | }
118 | return infoList;
119 | }
120 |
121 | @Override
122 | public List getSelfList() {
123 | if (isRootDir())
124 | return rootFileList;
125 |
126 | List infoList = new ArrayList<>();
127 | try {
128 | Directory selfDir = openDirectory(diskShare, getPathNotShare(""));
129 | List selfDirInfoList = selfDir.list();
130 |
131 | infoList.addAll(getFileInfoList(selfDirInfoList, diskShare));
132 | } catch (Exception e) {
133 | e.printStackTrace();
134 | }
135 | return infoList;
136 | }
137 |
138 | @Override
139 | public List getChildList(String dirName) {
140 | List infoList = new ArrayList<>();
141 | try {
142 | Directory childDir;
143 | if (isRootDir()) {
144 | //in root directory the child is share
145 | diskShare = (DiskShare) session.connectShare(dirName);
146 | childDir = openDirectory(diskShare, "");
147 | } else {
148 | childDir = openDirectory(diskShare, getPathNotShare(dirName));
149 | }
150 |
151 | mPath += "\\" + dirName;
152 | List childDirInfoList = childDir.list();
153 | infoList.addAll(getFileInfoList(childDirInfoList, diskShare));
154 |
155 | } catch (Exception e) {
156 | e.printStackTrace();
157 | }
158 | return infoList;
159 | }
160 |
161 | @Override
162 | public InputStream getFileInputStream(String fileName) {
163 | String filePath = getPathNotShare(fileName);
164 |
165 | try {
166 | File file = openFile(diskShare, filePath);
167 | inputStream = file.getInputStream();
168 | } catch (Exception e) {
169 | e.printStackTrace();
170 | }
171 | return inputStream;
172 | }
173 |
174 | @Override
175 | public long getFileLength(String fileName) {
176 | String filePath = getPathNotShare(fileName);
177 |
178 | try {
179 | File file = openFile(diskShare, filePath);
180 | FileStandardInformation standardInfo = file.getFileInformation(FileStandardInformation.class);
181 | return standardInfo.getEndOfFile();
182 | } catch (Exception e) {
183 | e.printStackTrace();
184 | }
185 | return 0;
186 | }
187 |
188 | @Override
189 | public String getCurrentPath() {
190 | return mPath.length() == 0 ? "/" : mPath.replace("\\", "/");
191 | }
192 |
193 | @Override
194 | public boolean isRootDir() {
195 | return ROOT_FLAG.equals(mPath);
196 | }
197 |
198 | @Override
199 | public void release() {
200 | try {
201 | if (inputStream != null)
202 | inputStream.close();
203 | if (session != null)
204 | session.close();
205 | if (smbConnection != null)
206 | smbConnection.close();
207 | if (smbClient != null)
208 | smbClient.close();
209 | } catch (IOException e) {
210 | e.printStackTrace();
211 | }
212 | }
213 |
214 | /**
215 | * get share info list, just add file type directory
216 | *
217 | * @param shareInfoList file info list
218 | * @return file info list
219 | */
220 | private List getFileInfoList(List shareInfoList) {
221 | List fileInfoList = new ArrayList<>();
222 | for (NetShareInfo0 shareInfo : shareInfoList) {
223 | fileInfoList.add(new SmbFileInfo(shareInfo.getNetName(), true));
224 | }
225 | return fileInfoList;
226 | }
227 |
228 | /**
229 | * traversal directory info list filtering does not use folders and get file types
230 | *
231 | * @param dirInfoList directory list
232 | * @param diskShare share
233 | * @return file info list
234 | */
235 | private List getFileInfoList(List dirInfoList, DiskShare diskShare) {
236 | List fileInfoList = new ArrayList<>();
237 | for (FileIdBothDirectoryInformation dirInfo : dirInfoList) {
238 | //ignore directories beginning with '.', like '.', '..'
239 | if (dirInfo.getFileName().startsWith("."))
240 | continue;
241 |
242 | //get file standard info by disk entry because file type unknown
243 | DiskEntry diskEntry = openDiskEntry(diskShare, getPathNotShare(dirInfo.getFileName()));
244 | FileStandardInformation standardInformation = diskEntry.getFileInformation(FileStandardInformation.class);
245 | fileInfoList.add(new SmbFileInfo(dirInfo.getFileName(), standardInformation.isDirectory()));
246 | }
247 | return fileInfoList;
248 | }
249 |
250 | /**
251 | * splicing child file name to mPath and removing shareName
252 | *
253 | * @param fileName child file name
254 | * @return child file path
255 | */
256 | private String getPathNotShare(String fileName) {
257 | int index = mPath.indexOf("\\", 1);
258 | if (index == -1) {
259 | return fileName;
260 | } else {
261 | fileName = fileName.length() == 0 ? "" : ("\\" + fileName);
262 | return mPath.substring(index + 1) + fileName;
263 | }
264 | }
265 |
266 | /**
267 | * get smb file, just need reed permission
268 | *
269 | * @param share share
270 | * @param filePath file path not share name
271 | * @return smb file
272 | */
273 | private File openFile(DiskShare share, String filePath) {
274 | return share.openFile(filePath,
275 | EnumSet.of(AccessMask.FILE_READ_DATA),
276 | null,
277 | SMB2ShareAccess.ALL,
278 | FILE_OPEN,
279 | null);
280 | }
281 |
282 | /**
283 | * get smb directory, just need reed permission
284 | *
285 | * @param share share
286 | * @param filePath directory path not share name
287 | * @return smb directory
288 | */
289 | private Directory openDirectory(DiskShare share, String filePath) {
290 | return share.openDirectory(
291 | filePath,
292 | EnumSet.of(AccessMask.GENERIC_READ),
293 | null,
294 | SMB2ShareAccess.ALL,
295 | SMB2CreateDisposition.FILE_OPEN,
296 | null);
297 | }
298 |
299 | /**
300 | * get smb disk entry, just need reed permission
301 | *
302 | * @param share share
303 | * @param filePath file or directory path nor share name
304 | * @return dis entry
305 | */
306 | private DiskEntry openDiskEntry(DiskShare share, String filePath) {
307 | return share.open(
308 | filePath,
309 | EnumSet.of(AccessMask.GENERIC_READ),
310 | null,
311 | SMB2ShareAccess.ALL,
312 | FILE_OPEN,
313 | null);
314 | }
315 | }
316 |
--------------------------------------------------------------------------------
/libsmb/src/main/java/com/xyoye/libsmb/exception/SmbLinkException.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.libsmb.exception;
2 |
3 | import com.xyoye.libsmb.info.SmbType;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | /**
9 | * Created by xyoye on 2019/12/20.
10 | */
11 |
12 | public class SmbLinkException extends Exception {
13 | private List detailExceptions;
14 |
15 | public SmbLinkException() {
16 | detailExceptions = new ArrayList<>();
17 | }
18 |
19 | public void addException(SmbType smbType, String msg) {
20 | detailExceptions.add(new DetailException(smbType, msg));
21 | }
22 |
23 | public void clearException() {
24 | detailExceptions.clear();
25 | }
26 |
27 | public String getExceptionString() {
28 | StringBuilder stringBuilder = new StringBuilder();
29 | for (DetailException exception : detailExceptions) {
30 | String typeName = SmbType.getTypeName(exception.getSmbType());
31 | stringBuilder.append("\n")
32 | .append("Type: ")
33 | .append(typeName)
34 | .append("\n")
35 | .append("Error: ")
36 | .append(exception.getErrorMsg())
37 | .append("\n");
38 | }
39 | return stringBuilder.toString();
40 | }
41 |
42 | public List getDetailExceptions() {
43 | return detailExceptions;
44 | }
45 |
46 | public static class DetailException {
47 | private SmbType smbType;
48 | private String errorMsg;
49 |
50 | DetailException(SmbType smbType, String errorMsg) {
51 | this.smbType = smbType;
52 | this.errorMsg = errorMsg;
53 | }
54 |
55 | public String getErrorMsg() {
56 | return errorMsg;
57 | }
58 |
59 | public void setErrorMsg(String errorMsg) {
60 | this.errorMsg = errorMsg;
61 | }
62 |
63 | public SmbType getSmbType() {
64 | return smbType;
65 | }
66 |
67 | public void setSmbType(SmbType smbType) {
68 | this.smbType = smbType;
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/libsmb/src/main/java/com/xyoye/libsmb/info/SmbFileInfo.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.libsmb.info;
2 |
3 | /**
4 | * Created by xyoye on 2019/12/22.
5 | */
6 |
7 | public class SmbFileInfo {
8 | private String fileName;
9 | private boolean isDirectory;
10 |
11 | public SmbFileInfo(String fileName, boolean isDirectory) {
12 | this.fileName = fileName;
13 | this.isDirectory = isDirectory;
14 | }
15 |
16 | public String getFileName() {
17 | return fileName;
18 | }
19 |
20 | public void setFileName(String fileName) {
21 | this.fileName = fileName;
22 | }
23 |
24 | public boolean isDirectory() {
25 | return isDirectory;
26 | }
27 |
28 | public void setDirectory(boolean directory) {
29 | isDirectory = directory;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/libsmb/src/main/java/com/xyoye/libsmb/info/SmbLinkInfo.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.libsmb.info;
2 |
3 | import androidx.annotation.Nullable;
4 |
5 | /**
6 | * Created by xyoye on 2019/12/20.
7 | */
8 |
9 | public class SmbLinkInfo {
10 | private String IP;
11 | private String account;
12 | private String password;
13 | private String domain;
14 | private String rootFolder;
15 | private boolean isAnonymous;
16 |
17 | public String getIP() {
18 | return IP;
19 | }
20 |
21 | public void setIP(String IP) {
22 | this.IP = IP;
23 | }
24 |
25 | public String getAccount() {
26 | return account;
27 | }
28 |
29 | public void setAccount(String account) {
30 | this.account = account;
31 | }
32 |
33 | public String getPassword() {
34 | return password;
35 | }
36 |
37 | public void setPassword(String password) {
38 | this.password = password;
39 | }
40 |
41 | @Nullable
42 | public String getDomain() {
43 | return domain;
44 | }
45 |
46 | public void setDomain(@Nullable String domain) {
47 | this.domain = domain;
48 | }
49 |
50 | @Nullable
51 | public String getRootFolder() {
52 | return rootFolder;
53 | }
54 |
55 | public void setRootFolder(@Nullable String rootFolder) {
56 | this.rootFolder = rootFolder;
57 | }
58 |
59 | public boolean isAnonymous() {
60 | return isAnonymous;
61 | }
62 |
63 | public void setAnonymous(boolean anonymous) {
64 | isAnonymous = anonymous;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/libsmb/src/main/java/com/xyoye/libsmb/info/SmbType.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.libsmb.info;
2 |
3 | /**
4 | * Created by xyoye on 2019/12/20.
5 | */
6 |
7 | public enum SmbType {
8 | JCIFS,
9 |
10 | JCIFS_NG,
11 |
12 | SMBJ,
13 |
14 | SMBJ_RPC;
15 |
16 | public static String getTypeName(SmbType type){
17 | switch (type){
18 | case SMBJ:
19 | return "SMBJ";
20 | case JCIFS:
21 | return "JCIFS";
22 | case JCIFS_NG:
23 | return "JCIFS_NG";
24 | case SMBJ_RPC:
25 | return "SMBJ_RPC";
26 | default:
27 | return "";
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/libsmb/src/main/java/com/xyoye/libsmb/utils/SmbUtils.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.libsmb.utils;
2 |
3 | /**
4 | * Created by xyoye on 2019/12/20.
5 | */
6 |
7 | public class SmbUtils {
8 |
9 | public static boolean isTextEmpty(String str) {
10 | return str == null || str.length() == 0;
11 | }
12 |
13 | public static boolean containsEmptyText(String... strings) {
14 | for (String string : strings) {
15 | if (isTextEmpty(string))
16 | return true;
17 | }
18 | return false;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/libsmb/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | libsmb
3 |
4 |
--------------------------------------------------------------------------------
/libsmb/src/test/java/com/xyoye/libsmb/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.xyoye.libsmb;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':libsmb'
2 |
--------------------------------------------------------------------------------