diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 11d0dd55..102fa86e 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -28,5 +28,11 @@ # Sardine -keep class com.thegrizzlylabs.sardineandroid.** { *; } +# SMBJ +-keep class com.hierynomus.** { *; } +-keep class net.engio.mbassy.** { *; } +-dontwarn org.ietf.jgss.** +-dontwarn javax.** + # Logger -keep class com.orhanobut.logger.** { *; } \ No newline at end of file diff --git a/app/src/main/java/com/github/catvod/bean/samba/Drive.java b/app/src/main/java/com/github/catvod/bean/samba/Drive.java new file mode 100644 index 00000000..5cce4572 --- /dev/null +++ b/app/src/main/java/com/github/catvod/bean/samba/Drive.java @@ -0,0 +1,97 @@ +package com.github.catvod.bean.samba; + +import android.net.Uri; +import android.text.TextUtils; + +import com.github.catvod.bean.Class; +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; +import com.hierynomus.smbj.SMBClient; +import com.hierynomus.smbj.auth.AuthenticationContext; +import com.hierynomus.smbj.connection.Connection; +import com.hierynomus.smbj.session.Session; +import com.hierynomus.smbj.share.DiskShare; + +import java.lang.reflect.Type; +import java.util.List; + +public class Drive { + + @SerializedName("name") + private String name; + @SerializedName("server") + private String server; + + private Connection connection; + private SMBClient smbClient; + private DiskShare diskShare; + private Session session; + + public static List arrayFrom(String str) { + Type listType = new TypeToken>() {}.getType(); + return new Gson().fromJson(str, listType); + } + + public Drive(String name) { + this.name = name; + } + + public String getName() { + return TextUtils.isEmpty(name) ? "" : name; + } + + public String getServer() { + return TextUtils.isEmpty(server) ? "" : server; + } + + public DiskShare getShare() { + if (diskShare == null) init(); + return diskShare; + } + + public Class toType() { + return new Class(getName(), getName(), "1"); + } + + public void init() { + try { + smbClient = new SMBClient(); + Uri uri = Uri.parse(getServer()); + String share = uri.getPath().replaceFirst("^/", "").split("/")[0]; + connection = smbClient.connect(uri.getHost(), uri.getPort() != -1 ? uri.getPort() : SMBClient.DEFAULT_PORT); + session = connection.authenticate(getAuthentication(uri)); + diskShare = (DiskShare) session.connectShare(share); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private AuthenticationContext getAuthentication(Uri uri) { + String userInfo = uri.getUserInfo(); + if (userInfo == null) return AuthenticationContext.guest(); + String[] parts = userInfo.split(":", 2); + String username = parts[0]; + char[] password = parts.length > 1 ? parts[1].toCharArray() : new char[0]; + return new AuthenticationContext(username, password, null); + } + + public void release() { + try { + if (diskShare != null) diskShare.close(); + if (session != null) session.close(); + if (connection != null) connection.close(); + if (smbClient != null) smbClient.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof Drive)) return false; + Drive it = (Drive) obj; + return getName().equals(it.getName()); + } +} diff --git a/app/src/main/java/com/github/catvod/spider/AList.java b/app/src/main/java/com/github/catvod/spider/AList.java index 9f735deb..8889ff36 100644 --- a/app/src/main/java/com/github/catvod/spider/AList.java +++ b/app/src/main/java/com/github/catvod/spider/AList.java @@ -71,16 +71,12 @@ public class AList extends Spider { @Override public void init(Context context, String extend) { - try { - ext = extend; - fetchRule(); - } catch (Exception ignored) { - } + ext = extend; + fetchRule(); } @Override public String homeContent(boolean filter) throws Exception { - fetchRule(); List classes = new ArrayList<>(); LinkedHashMap> filters = new LinkedHashMap<>(); for (Drive drive : drives) if (!drive.hidden()) classes.add(drive.toType()); @@ -90,7 +86,6 @@ public class AList extends Spider { @Override public String categoryContent(String tid, String pg, boolean filter, HashMap extend) throws Exception { - fetchRule(); String type = extend.containsKey("type") ? extend.get("type") : ""; String order = extend.containsKey("order") ? extend.get("order") : ""; List folders = new ArrayList<>(); @@ -113,7 +108,6 @@ public class AList extends Spider { @Override public String detailContent(List ids) throws Exception { - fetchRule(); String id = ids.get(0); String key = id.contains("/") ? id.substring(0, id.indexOf("/")) : id; String path = id.substring(0, id.lastIndexOf("/")); @@ -142,7 +136,6 @@ public class AList extends Spider { @Override public String searchContent(String keyword, boolean quick) throws Exception { - fetchRule(); List list = new ArrayList<>(); List jobs = new ArrayList<>(); ExecutorService executor = Executors.newCachedThreadPool(); diff --git a/app/src/main/java/com/github/catvod/spider/Samba.java b/app/src/main/java/com/github/catvod/spider/Samba.java new file mode 100644 index 00000000..8fa8b416 --- /dev/null +++ b/app/src/main/java/com/github/catvod/spider/Samba.java @@ -0,0 +1,122 @@ +package com.github.catvod.spider; + +import android.content.Context; +import android.text.TextUtils; + +import com.github.catvod.bean.Class; +import com.github.catvod.bean.Result; +import com.github.catvod.bean.Vod; +import com.github.catvod.bean.samba.Drive; +import com.github.catvod.crawler.Spider; +import com.github.catvod.net.OkHttp; +import com.github.catvod.utils.Image; +import com.github.catvod.utils.Util; +import com.hierynomus.msfscc.FileAttributes; +import com.hierynomus.msfscc.fileinformation.FileIdBothDirectoryInformation; +import com.hierynomus.protocol.commons.EnumWithValue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +public class Samba extends Spider { + + private List drives; + private String extend; + + private void fetchRule() { + if (drives != null && !drives.isEmpty()) return; + if (extend.startsWith("http")) extend = OkHttp.string(extend); + drives = Drive.arrayFrom(extend); + } + + private Drive getDrive(String name) { + return drives.get(drives.indexOf(new Drive(name))); + } + + private boolean isFolder(FileIdBothDirectoryInformation item) { + return EnumWithValue.EnumUtils.isSet(item.getFileAttributes(), FileAttributes.FILE_ATTRIBUTE_DIRECTORY); + } + + private boolean isFile(FileIdBothDirectoryInformation item) { + return !EnumWithValue.EnumUtils.isSet(item.getFileAttributes(), FileAttributes.FILE_ATTRIBUTE_DIRECTORY); + } + + @Override + public void init(Context context, String extend) { + this.extend = extend; + fetchRule(); + } + + @Override + public String homeContent(boolean filter) { + List classes = new ArrayList<>(); + for (Drive drive : drives) classes.add(drive.toType()); + return Result.string(classes); + } + + @Override + public String categoryContent(String tid, String pg, boolean filter, HashMap hashMap) { + String key = tid.contains("/") ? tid.substring(0, tid.indexOf("/")) : tid; + String path = tid.contains("/") ? tid.substring(tid.indexOf("/") + 1) : ""; + Drive drive = getDrive(key); + List list = new ArrayList<>(); + for (FileIdBothDirectoryInformation item : getList(drive, path)) { + String vodId = TextUtils.join("/", path.isEmpty() ? Arrays.asList(key, item.getFileName()) : Arrays.asList(key, path, item.getFileName())); + if (isFolder(item)) list.add(new Vod(vodId, item.getFileName(), Image.FOLDER, "", true)); + if (isFile(item)) list.add(new Vod(vodId, item.getFileName(), Image.VIDEO, "", false)); + } + return Result.get().vod(list).page().string(); + } + + @Override + public String detailContent(List ids) { + String tid = ids.get(0); + String key = tid.contains("/") ? tid.substring(0, tid.indexOf("/")) : tid; + String path = tid.contains("/") ? tid.substring(tid.indexOf("/") + 1) : ""; + String parent = path.substring(0, path.lastIndexOf("/")); + String name = parent.substring(parent.lastIndexOf("/") + 1); + Drive drive = getDrive(key); + List playUrls = new ArrayList<>(); + for (FileIdBothDirectoryInformation item : getList(drive, parent)) { + if (isFile(item)) { + playUrls.add(item.getFileName() + "$" + drive.getServer() + "/" + parent + "/" + item.getFileName()); + } + } + Vod vod = new Vod(); + vod.setVodId(name); + vod.setVodName(name); + vod.setVodPlayFrom(key); + vod.setVodPlayUrl(TextUtils.join("#", playUrls)); + return Result.string(vod); + } + + @Override + public String playerContent(String flag, String id, List vipFlags) { + return Result.get().url(id).string(); + } + + private List getList(Drive drive, String path) { + List items = drive.getShare().list(path); + Iterator iterator = items.iterator(); + while (iterator.hasNext()) { + FileIdBothDirectoryInformation item = iterator.next(); + if (isFolder(item) && item.getFileName().startsWith(".")) iterator.remove(); + if (isFile(item) && !Util.MEDIA.contains(Util.getExt(item.getFileName()))) iterator.remove(); + } + Collections.sort(items, (o1, o2) -> { + if (isFolder(o1) && isFile(o2)) return -1; + if (isFile(o1) && isFolder(o2)) return 1; + return o1.getFileName().toLowerCase().compareTo(o2.getFileName().toLowerCase()); + }); + return items; + } + + @Override + public void destroy() { + for (Drive drive : drives) drive.release(); + } +} diff --git a/jar/custom_spider.jar b/jar/custom_spider.jar index afbc634f..b4252ff7 100644 Binary files a/jar/custom_spider.jar and b/jar/custom_spider.jar differ diff --git a/jar/custom_spider.jar.md5 b/jar/custom_spider.jar.md5 index 8c2392d8..5a781daf 100644 --- a/jar/custom_spider.jar.md5 +++ b/jar/custom_spider.jar.md5 @@ -1 +1 @@ -81b9ffd846c583616cd66635e8a34eb7 +5ff6b67b0a828c1a512c9df7c0d1e626 diff --git a/json/samba.json b/json/samba.json new file mode 100644 index 00000000..fdd89a20 --- /dev/null +++ b/json/samba.json @@ -0,0 +1,6 @@ +[ + { + "name": "Tangsan", + "server": "smb://192.168.0.2/Users" + } +] \ No newline at end of file