Browse Source

Add data URL Link support to subscription

Shelikhoo 2 years ago
parent
commit
f112667190

+ 44 - 0
app/subscription/containers/dataurlsingle/dataurl.go

@@ -0,0 +1,44 @@
+package dataurlsingle
+
+import (
+	"bytes"
+	"strings"
+
+	"github.com/vincent-petithory/dataurl"
+
+	"github.com/v2fly/v2ray-core/v5/app/subscription/containers"
+	"github.com/v2fly/v2ray-core/v5/common"
+)
+
+//go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen
+
+func newSingularDataURLParser() containers.SubscriptionContainerDocumentParser {
+	return &parser{}
+}
+
+type parser struct{}
+
+func (p parser) ParseSubscriptionContainerDocument(rawConfig []byte) (*containers.Container, error) {
+	dataURL, err := dataurl.Decode(bytes.NewReader(rawConfig))
+	if err != nil {
+		return nil, newError("unable to decode dataURL").Base(err)
+	}
+	if dataURL.MediaType.Type != "application" {
+		return nil, newError("unsupported media type: ", dataURL.MediaType.Type)
+	}
+	if !strings.HasPrefix(dataURL.MediaType.Subtype, "vnd.v2ray.subscription-singular") {
+		return nil, newError("unsupported media subtype: ", dataURL.MediaType.Subtype)
+	}
+	result := &containers.Container{}
+	result.Kind = "DataURLSingle"
+	result.Metadata = make(map[string]string)
+	result.ServerSpecs = append(result.ServerSpecs, containers.UnparsedServerConf{
+		KindHint: "",
+		Content:  dataURL.Data,
+	})
+	return result, nil
+}
+
+func init() {
+	common.Must(containers.RegisterParser("DataURLSingle", newSingularDataURLParser()))
+}

+ 9 - 0
app/subscription/containers/dataurlsingle/errors.generated.go

@@ -0,0 +1,9 @@
+package dataurlsingle
+
+import "github.com/v2fly/v2ray-core/v5/common/errors"
+
+type errPathObjHolder struct{}
+
+func newError(values ...interface{}) *errors.Error {
+	return errors.New(values...).WithPathObj(errPathObjHolder{})
+}

+ 15 - 1
app/subscription/documentfetcher/dataurlfetcher/dataurl.go

@@ -2,6 +2,10 @@ package dataurlfetcher
 
 
 import (
 import (
 	"context"
 	"context"
+	"strings"
+
+	"github.com/vincent-petithory/dataurl"
+
 	"github.com/v2fly/v2ray-core/v5/app/subscription"
 	"github.com/v2fly/v2ray-core/v5/app/subscription"
 	"github.com/v2fly/v2ray-core/v5/app/subscription/documentfetcher"
 	"github.com/v2fly/v2ray-core/v5/app/subscription/documentfetcher"
 	"github.com/v2fly/v2ray-core/v5/common"
 	"github.com/v2fly/v2ray-core/v5/common"
@@ -20,5 +24,15 @@ func init() {
 type dataURLFetcher struct{}
 type dataURLFetcher struct{}
 
 
 func (d *dataURLFetcher) DownloadDocument(ctx context.Context, source *subscription.ImportSource, opts ...documentfetcher.FetcherOptions) ([]byte, error) {
 func (d *dataURLFetcher) DownloadDocument(ctx context.Context, source *subscription.ImportSource, opts ...documentfetcher.FetcherOptions) ([]byte, error) {
-	panic("implement me")
+	dataURL, err := dataurl.DecodeString(source.Url)
+	if err != nil {
+		return nil, newError("unable to decode dataURL").Base(err)
+	}
+	if dataURL.MediaType.Type != "application" {
+		return nil, newError("unsupported media type: ", dataURL.MediaType.Type)
+	}
+	if !strings.HasPrefix(dataURL.MediaType.Subtype, "vnd.v2ray.subscription") {
+		return nil, newError("unsupported media subtype: ", dataURL.MediaType.Subtype)
+	}
+	return []byte(source.Url), nil
 }
 }

+ 9 - 0
app/subscription/documentfetcher/dataurlfetcher/errors.generated.go

@@ -0,0 +1,9 @@
+package dataurlfetcher
+
+import "github.com/v2fly/v2ray-core/v5/common/errors"
+
+type errPathObjHolder struct{}
+
+func newError(values ...interface{}) *errors.Error {
+	return errors.New(values...).WithPathObj(errPathObjHolder{})
+}

+ 6 - 1
app/subscription/subscriptionmanager/subdocupdater.go

@@ -21,11 +21,16 @@ func (s *SubscriptionManagerImpl) updateSubscription(subscriptionName string) er
 		trackedSub = trackedSubFound
 		trackedSub = trackedSubFound
 	}
 	}
 	importSource := trackedSub.importSource
 	importSource := trackedSub.importSource
-
 	docFetcher, err := documentfetcher.GetFetcher("http")
 	docFetcher, err := documentfetcher.GetFetcher("http")
 	if err != nil {
 	if err != nil {
 		return newError("failed to get fetcher: ", err)
 		return newError("failed to get fetcher: ", err)
 	}
 	}
+	if strings.HasPrefix(importSource.Url, "data:") {
+		docFetcher, err = documentfetcher.GetFetcher("dataurl")
+		if err != nil {
+			return newError("failed to get fetcher: ", err)
+		}
+	}
 
 
 	downloadedDocument, err := docFetcher.DownloadDocument(s.ctx, importSource)
 	downloadedDocument, err := docFetcher.DownloadDocument(s.ctx, importSource)
 	if err != nil {
 	if err != nil {

+ 1 - 0
go.mod

@@ -26,6 +26,7 @@ require (
 	github.com/v2fly/BrowserBridge v0.0.0-20210430233438-0570fc1d7d08
 	github.com/v2fly/BrowserBridge v0.0.0-20210430233438-0570fc1d7d08
 	github.com/v2fly/VSign v0.0.0-20201108000810-e2adc24bf848
 	github.com/v2fly/VSign v0.0.0-20201108000810-e2adc24bf848
 	github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
 	github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
+	github.com/vincent-petithory/dataurl v1.0.0
 	github.com/xiaokangwang/VLite v0.0.0-20220418190619-cff95160a432
 	github.com/xiaokangwang/VLite v0.0.0-20220418190619-cff95160a432
 	go.starlark.net v0.0.0-20230612165344-9532f5667272
 	go.starlark.net v0.0.0-20230612165344-9532f5667272
 	go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35
 	go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35

+ 2 - 0
go.sum

@@ -325,6 +325,8 @@ github.com/v2fly/VSign v0.0.0-20201108000810-e2adc24bf848 h1:p1UzXK6VAutXFFQMnre
 github.com/v2fly/VSign v0.0.0-20201108000810-e2adc24bf848/go.mod h1:p80Bv154ZtrGpXMN15slDCqc9UGmfBuUzheDFBYaW/M=
 github.com/v2fly/VSign v0.0.0-20201108000810-e2adc24bf848/go.mod h1:p80Bv154ZtrGpXMN15slDCqc9UGmfBuUzheDFBYaW/M=
 github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
 github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
 github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
 github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
+github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI=
+github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xiaokangwang/VLite v0.0.0-20220418190619-cff95160a432 h1:I/ATawgO2RerCq9ACwL0wBB8xNXZdE3J+93MCEHReRs=
 github.com/xiaokangwang/VLite v0.0.0-20220418190619-cff95160a432 h1:I/ATawgO2RerCq9ACwL0wBB8xNXZdE3J+93MCEHReRs=
 github.com/xiaokangwang/VLite v0.0.0-20220418190619-cff95160a432/go.mod h1:QN7Go2ftTVfx0aCTh9RXHV8pkpi0FtmbwQw40dy61wQ=
 github.com/xiaokangwang/VLite v0.0.0-20220418190619-cff95160a432/go.mod h1:QN7Go2ftTVfx0aCTh9RXHV8pkpi0FtmbwQw40dy61wQ=

+ 32 - 0
main/commands/all/engineering/encodedataurl.go

@@ -0,0 +1,32 @@
+package engineering
+
+import (
+	"flag"
+	"io"
+	"os"
+
+	"github.com/vincent-petithory/dataurl"
+
+	"github.com/v2fly/v2ray-core/v5/main/commands/base"
+)
+
+var cmdEncodeDataURLContentType *string
+
+var cmdEncodeDataURL = &base.Command{
+	UsageLine: "{{.Exec}} engineering encodeDataURL",
+	Flag: func() flag.FlagSet {
+		fs := flag.NewFlagSet("", flag.ExitOnError)
+		cmdEncodeDataURLContentType = fs.String("type", "application/vnd.v2ray.subscription-singular", "")
+		return *fs
+	}(),
+	Run: func(cmd *base.Command, args []string) {
+		cmd.Flag.Parse(args)
+
+		content, err := io.ReadAll(os.Stdin)
+		if err != nil {
+			base.Fatalf("%s", err)
+		}
+		dataURL := dataurl.New(content, *cmdEncodeDataURLContentType)
+		dataURL.WriteTo(os.Stdout)
+	},
+}

+ 1 - 0
main/commands/all/engineering/engineering.go

@@ -12,6 +12,7 @@ var cmdEngineering = &base.Command{
 		cmdNonNativeLinkExtract,
 		cmdNonNativeLinkExtract,
 		cmdNonNativeLinkExec,
 		cmdNonNativeLinkExec,
 		cmdSubscriptionEntriesExtract,
 		cmdSubscriptionEntriesExtract,
+		cmdEncodeDataURL,
 	},
 	},
 }
 }
 
 

+ 2 - 0
main/distro/all/all.go

@@ -118,10 +118,12 @@ import (
 
 
 	// Subscription Containers: general purpose
 	// Subscription Containers: general purpose
 	_ "github.com/v2fly/v2ray-core/v5/app/subscription/containers/base64urlline"
 	_ "github.com/v2fly/v2ray-core/v5/app/subscription/containers/base64urlline"
+	_ "github.com/v2fly/v2ray-core/v5/app/subscription/containers/dataurlsingle"
 	_ "github.com/v2fly/v2ray-core/v5/app/subscription/containers/jsonfieldarray"
 	_ "github.com/v2fly/v2ray-core/v5/app/subscription/containers/jsonfieldarray"
 	_ "github.com/v2fly/v2ray-core/v5/app/subscription/containers/jsonfieldarray/jsonified"
 	_ "github.com/v2fly/v2ray-core/v5/app/subscription/containers/jsonfieldarray/jsonified"
 
 
 	// Subscription Fetchers
 	// Subscription Fetchers
+	_ "github.com/v2fly/v2ray-core/v5/app/subscription/documentfetcher/dataurlfetcher"
 	_ "github.com/v2fly/v2ray-core/v5/app/subscription/documentfetcher/httpfetcher"
 	_ "github.com/v2fly/v2ray-core/v5/app/subscription/documentfetcher/httpfetcher"
 
 
 	// Subscription Entries Converters
 	// Subscription Entries Converters