diff --git a/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java b/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java index fb93149d2..fbdb3cdfc 100644 --- a/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java +++ b/app/src/main/java/com/fongmi/android/tv/api/LiveParser.java @@ -4,6 +4,7 @@ import android.util.Base64; import com.fongmi.android.tv.R; import com.fongmi.android.tv.bean.Channel; +import com.fongmi.android.tv.bean.ClearKey; import com.fongmi.android.tv.bean.Drm; import com.fongmi.android.tv.bean.Group; import com.fongmi.android.tv.bean.Live; @@ -121,6 +122,7 @@ public class LiveParser { private String key; private String type; private String click; + private String origin; private String referer; private Integer parse; private Integer player; @@ -130,7 +132,7 @@ public class LiveParser { } public boolean find(String line) { - return line.startsWith("ua") || line.startsWith("parse") || line.startsWith("click") || line.startsWith("player") || line.startsWith("referer") || line.startsWith("#EXTVLCOPT:") || line.startsWith("#KODIPROP:"); + return line.startsWith("ua") || line.startsWith("parse") || line.startsWith("click") || line.startsWith("player") || line.startsWith("origin") || line.startsWith("referer") || line.startsWith("#EXTVLCOPT:") || line.startsWith("#KODIPROP:"); } public void check(String line) { @@ -139,20 +141,25 @@ public class LiveParser { else if (line.startsWith("parse")) parse(line); else if (line.startsWith("click")) click(line); else if (line.startsWith("player")) player(line); + else if (line.startsWith("origin")) origin(line); + else if (line.startsWith("Origin")) origin(line); else if (line.startsWith("user-agent")) ua(line); else if (line.startsWith("User-Agent")) ua(line); else if (line.startsWith("referer")) referer(line); else if (line.startsWith("Referer")) referer(line); + else if (line.startsWith("#EXTVLCOPT:http-origin")) origin(line); else if (line.startsWith("#EXTVLCOPT:http-user-agent")) ua(line); - else if (line.startsWith("#EXTVLCOPT:http-referer")) referer(line); + else if (line.startsWith("#EXTVLCOPT:http-referrer")) referer(line); else if (line.startsWith("#KODIPROP:inputstream.adaptive.license_key")) key(line); else if (line.startsWith("#KODIPROP:inputstream.adaptive.license_type")) type(line); + else if (line.startsWith("#KODIPROP:inputstream.adaptive.stream_headers")) headers(line); } public Setting copy(Channel channel) { if (ua != null) channel.setUa(ua); if (parse != null) channel.setParse(parse); if (click != null) channel.setClick(click); + if (origin != null) channel.setOrigin(origin); if (referer != null) channel.setReferer(referer); if (player != null) channel.setPlayerType(player); if (key != null && type != null) channel.setDrm(Drm.create(key, type)); @@ -161,7 +168,8 @@ public class LiveParser { private void ua(String line) { try { - ua = line.split("ua=")[1].trim().replace("\"", ""); + if (line.contains("ua=")) ua = line.split("ua=")[1].trim().replace("\"", ""); + if (line.contains("user-agent=")) ua = line.split("(?i)user-agent=")[1].trim().replace("\"", ""); } catch (Exception e) { ua = null; } @@ -169,7 +177,7 @@ public class LiveParser { private void referer(String line) { try { - referer = line.split("referer=")[1].trim().replace("\"", ""); + referer = line.split("(?i)referer=")[1].trim().replace("\"", ""); } catch (Exception e) { referer = null; } @@ -199,10 +207,18 @@ public class LiveParser { } } + private void origin(String line) { + try { + origin = line.split("(?i)origin=")[1].trim(); + } catch (Exception e) { + origin = null; + } + } + private void key(String line) { try { key = line.split("license_key=")[1].trim(); - if (!key.startsWith("http") && !key.startsWith("{") && key.contains(":")) convert(); + if (!key.startsWith("http")) convert(); } catch (Exception e) { key = null; } finally { @@ -220,11 +236,22 @@ public class LiveParser { } } + private void headers(String line) { + try { + check(line.split("headers=")[1].trim()); + } catch (Exception ignored) { + } + } + private void convert() { - String[] split = key.split(":"); - String k = Util.base64(Util.hex2byte(split[1])).replace("=", ""); - String kid = Util.base64(Util.hex2byte(split[0])).replace("=", ""); - key = String.format("{ \"keys\":[ { \"kty\":\"oct\", \"k\":\"%s\", \"kid\":\"%s\" } ], \"type\":\"temporary\" }", k, kid); + try { + ClearKey.objectFrom(key); + } catch (Exception e) { + String[] split = key.replace("\"", "").replace("{", "").replace("}", "").split(":"); + String kid = Util.base64(Util.hex2byte(split[0])).replace("=", ""); + String k = Util.base64(Util.hex2byte(split[1])).replace("=", ""); + key = ClearKey.get(kid, k).toString(); + } } private void clear() { @@ -234,6 +261,7 @@ public class LiveParser { parse = null; click = null; player = null; + origin = null; referer = null; } } diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Channel.java b/app/src/main/java/com/fongmi/android/tv/bean/Channel.java index d885be08c..692a8f01d 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Channel.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Channel.java @@ -35,6 +35,8 @@ public class Channel { private String ua; @SerializedName("click") private String click; + @SerializedName("origin") + private String origin; @SerializedName("referer") private String referer; @SerializedName("header") @@ -138,6 +140,14 @@ public class Channel { this.click = click; } + public String getOrigin() { + return TextUtils.isEmpty(origin) ? "" : origin; + } + + public void setOrigin(String origin) { + this.origin = origin; + } + public String getReferer() { return TextUtils.isEmpty(referer) ? "" : referer; } @@ -286,6 +296,7 @@ public class Channel { if (live.getUa().length() > 0 && getUa().isEmpty()) setUa(live.getUa()); if (live.getHeader() != null && getHeader() == null) setHeader(live.getHeader()); if (live.getClick().length() > 0 && getClick().isEmpty()) setClick(live.getClick()); + if (live.getOrigin().length() > 0 && getOrigin().isEmpty()) setOrigin(live.getOrigin()); if (live.getReferer().length() > 0 && getReferer().isEmpty()) setReferer(live.getReferer()); if (live.getPlayerType() != -1 && getPlayerType() == -1) setPlayerType(live.getPlayerType()); if (!getEpg().startsWith("http")) setEpg(live.getEpg().replace("{name}", getName()).replace("{epg}", getEpg())); @@ -299,6 +310,7 @@ public class Channel { public Map getHeaders() { Map headers = Json.toMap(getHeader()); if (!getUa().isEmpty()) headers.put(HttpHeaders.USER_AGENT, getUa()); + if (!getOrigin().isEmpty()) headers.put(HttpHeaders.ORIGIN, getOrigin()); if (!getReferer().isEmpty()) headers.put(HttpHeaders.REFERER, getReferer()); return headers; } @@ -308,6 +320,7 @@ public class Channel { setReferer(item.getReferer()); setHeader(item.getHeader()); setNumber(item.getNumber()); + setOrigin(item.getOrigin()); setParse(item.getParse()); setClick(item.getClick()); setLogo(item.getLogo()); diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Class.java b/app/src/main/java/com/fongmi/android/tv/bean/Class.java index 14f52c4f4..b0e115928 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Class.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Class.java @@ -4,8 +4,8 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import com.fongmi.android.tv.App; import com.github.catvod.utils.Trans; -import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; import org.simpleframework.xml.Attribute; @@ -50,7 +50,7 @@ public class Class implements Parcelable { } public static Class objectFrom(String json) { - return new Gson().fromJson(json, Class.class); + return App.gson().fromJson(json, Class.class); } public String getTypeId() { diff --git a/app/src/main/java/com/fongmi/android/tv/bean/ClearKey.java b/app/src/main/java/com/fongmi/android/tv/bean/ClearKey.java new file mode 100644 index 000000000..af799fb27 --- /dev/null +++ b/app/src/main/java/com/fongmi/android/tv/bean/ClearKey.java @@ -0,0 +1,52 @@ +package com.fongmi.android.tv.bean; + +import androidx.annotation.NonNull; + +import com.fongmi.android.tv.App; +import com.google.gson.annotations.SerializedName; + +import java.util.Arrays; +import java.util.List; + +public class ClearKey { + + @SerializedName("keys") + private List keys; + @SerializedName("type") + private String type; + + public static ClearKey objectFrom(String str) throws Exception { + ClearKey item = App.gson().fromJson(str, ClearKey.class); + if (item == null || item.keys == null) throw new Exception(); + return item; + } + + public static ClearKey get(String kid, String k) { + ClearKey key = new ClearKey(); + key.keys = Arrays.asList(new Keys(kid, k)); + key.type = "temporary"; + return key; + } + + public static class Keys { + + @SerializedName("kty") + private String kty; + @SerializedName("k") + private String k; + @SerializedName("kid") + private String kid; + + public Keys(String kid, String k) { + this.kty = "oct"; + this.kid = kid; + this.k = k; + } + } + + @NonNull + @Override + public String toString() { + return App.gson().toJson(this); + } +} diff --git a/app/src/main/java/com/fongmi/android/tv/bean/Live.java b/app/src/main/java/com/fongmi/android/tv/bean/Live.java index 286a7f3b5..f216e8236 100644 --- a/app/src/main/java/com/fongmi/android/tv/bean/Live.java +++ b/app/src/main/java/com/fongmi/android/tv/bean/Live.java @@ -21,7 +21,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -@Entity(ignoredColumns = {"type", "group", "url", "logo", "epg", "ua", "click", "referer", "timeout", "header", "playerType", "channels", "groups", "core", "activated", "width"}) +@Entity(ignoredColumns = {"type", "group", "url", "logo", "epg", "ua", "click", "origin", "referer", "timeout", "header", "playerType", "channels", "groups", "core", "activated", "width"}) public class Live { @NonNull @@ -46,6 +46,8 @@ public class Live { private String ua; @SerializedName("click") private String click; + @SerializedName("origin") + private String origin; @SerializedName("referer") private String referer; @SerializedName("timeout") @@ -135,6 +137,10 @@ public class Live { return TextUtils.isEmpty(ua) ? "" : ua; } + public String getOrigin() { + return TextUtils.isEmpty(origin) ? "" : origin; + } + public String getReferer() { return TextUtils.isEmpty(referer) ? "" : referer; }