diff --git a/README.md b/README.md index 32357c5..b9fd94e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## m3u8视频下载工具 * 提供windows图形界面(Qt), mac、linux命令行, linux支持arm、386、mipsle * 程序会自动将下载的ts文件合并转换格式为mp4 -* windows自带GUI界面的版本下载: [m3u8d_qt_v1.4.3_windows_amd64.exe](https://github.com/orestonce/m3u8d/releases/download/v1.4.3/m3u8d_qt_v1.4.3_windows_amd64.exe): +* windows自带GUI界面的版本下载: [m3u8d_qt_v1.5.0_windows_amd64.exe](https://github.com/orestonce/m3u8d/releases/download/v1.5.0/m3u8d_qt_v1.5.0_windows_amd64.exe): ![](m3u8d-qt/screenshot.png) * 全部版本下载, 包括windows图形界面/linux命令行/mac命令行: https://github.com/orestonce/m3u8d/releases @@ -24,7 +24,7 @@ * [x] 支持嵌套m3u8的url * [x] 支持设置代理 * [x] 增加openwrt路由器的mipsle二进制 - * [ ] 支持从curl命令解析出需要的header、auth-basic、cookie等信息,正如 https://github.com/cxjava/m3u8-downloader 一样 + * [x] 支持从curl命令解析出需要的信息,正如 https://github.com/cxjava/m3u8-downloader 一样 ## 二次开发操作手册: * 如果只开发命令行版本, 则只需要修改*.go文件, 然后编译 cmd/main.go 即可 * 如果涉及到Qt界面打包, 则需要运行 export/main.go 将 *.go导出为Qt界面需要的 diff --git a/cmd/main.go b/cmd/main.go index e1193b3..d5bae95 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -6,38 +6,61 @@ import ( "m3u8d" ) -var rootCmd = cobra.Command{ - Use: "m3u8下载工具", +var rootCmd = &cobra.Command{ + Use: "m3u8d", +} + +var downloadCmd = &cobra.Command{ + Use: "download", Run: func(cmd *cobra.Command, args []string) { if gRunReq.M3u8Url == "" { cmd.Help() return } - m3u8d.SetShowProgressBar() - resp := m3u8d.RunDownload(gRunReq) - fmt.Println() // 有进度条,所以需要换行 - if resp.ErrMsg != "" { - fmt.Println(resp.ErrMsg) + downloadFromCmd(gRunReq) + }, +} + +func downloadFromCmd(req m3u8d.RunDownload_Req) { + m3u8d.SetShowProgressBar() + resp := m3u8d.RunDownload(req) + fmt.Println() // 有进度条,所以需要换行 + if resp.ErrMsg != "" { + fmt.Println(resp.ErrMsg) + return + } + if resp.IsSkipped { + fmt.Println("已经下载过了: " + resp.SaveFileTo) + return + } + fmt.Println("下载成功, 保存路径", resp.SaveFileTo) +} + +var curlCmd = &cobra.Command{ + Use: "curl", + Run: func(cmd *cobra.Command, args []string) { + resp1 := m3u8d.ParseCurl(args) + if resp1.ErrMsg != "" { + fmt.Println(resp1.ErrMsg) return } - if resp.IsSkipped { - fmt.Println("已经下载过了: " + resp.SaveFileTo) - return - } - fmt.Println("下载成功, 保存路径", resp.SaveFileTo) + downloadFromCmd(resp1.DownloadReq) }, } var gRunReq m3u8d.RunDownload_Req func init() { - rootCmd.Flags().StringVarP(&gRunReq.M3u8Url, "M3u8Url", "u", "", "M3u8Url") - rootCmd.Flags().StringVarP(&gRunReq.HostType, "HostType", "", "apiv1", "设置getHost的方式(apiv1: `http(s):// + url.Host + filepath.Dir(url.Path)`; apiv2: `http(s)://+ u.Host`") - rootCmd.Flags().BoolVarP(&gRunReq.Insecure, "Insecure", "", false, "是否允许不安全的请求") - rootCmd.Flags().StringVarP(&gRunReq.SaveDir, "SaveDir", "d", "", "文件保存路径(默认为当前路径)") - rootCmd.Flags().StringVarP(&gRunReq.FileName, "FileName", "f", "", "文件名") - rootCmd.Flags().IntVarP(&gRunReq.SkipTsCountFromHead, "SkipTsCountFromHead", "", 0, "跳过前面几个ts") - rootCmd.Flags().StringVarP(&gRunReq.SetProxy, "SetProxy", "", "", "代理设置, http://127.0.0.1:8080 socks5://127.0.0.1:1089") + downloadCmd.Flags().StringVarP(&gRunReq.M3u8Url, "M3u8Url", "u", "", "M3u8Url") + downloadCmd.Flags().StringVarP(&gRunReq.HostType, "HostType", "", "apiv1", "设置getHost的方式(apiv1: `http(s):// + url.Host + filepath.Dir(url.Path)`; apiv2: `http(s)://+ u.Host`") + downloadCmd.Flags().BoolVarP(&gRunReq.Insecure, "Insecure", "", false, "是否允许不安全的请求") + downloadCmd.Flags().StringVarP(&gRunReq.SaveDir, "SaveDir", "d", "", "文件保存路径(默认为当前路径)") + downloadCmd.Flags().StringVarP(&gRunReq.FileName, "FileName", "f", "", "文件名") + downloadCmd.Flags().IntVarP(&gRunReq.SkipTsCountFromHead, "SkipTsCountFromHead", "", 0, "跳过前面几个ts") + downloadCmd.Flags().StringVarP(&gRunReq.SetProxy, "SetProxy", "", "", "代理设置, http://127.0.0.1:8080 socks5://127.0.0.1:1089") + rootCmd.AddCommand(downloadCmd) + curlCmd.DisableFlagParsing = true + rootCmd.AddCommand(curlCmd) } func main() { diff --git a/curl.go b/curl.go new file mode 100644 index 0000000..70c1c2f --- /dev/null +++ b/curl.go @@ -0,0 +1,135 @@ +package m3u8d + +import ( + "bytes" + "net/http" + "strconv" + "strings" + "unicode" +) + +type ParseCurl_Resp struct { + ErrMsg string + DownloadReq RunDownload_Req +} + +func ParseCurlStr(s string) (resp ParseCurl_Resp) { + r := strings.NewReader(strings.ReplaceAll(s, "\\\n", "")) + var tmp []string + for { + b, _, err := r.ReadRune() + if err != nil { + break + } + if unicode.IsSpace(b) { + continue + } + if b == '"' || b == '\'' { + str := parseQuotedStr(r, b) + tmp = append(tmp, str) + } else { + var buf bytes.Buffer + buf.WriteRune(b) + for { + b, _, err = r.ReadRune() + if err != nil || unicode.IsSpace(b) { + break + } + buf.WriteRune(b) + } + tmp = append(tmp, buf.String()) + } + } + if len(tmp) > 0 && strings.ToLower(tmp[0]) == "curl" { + tmp = tmp[1:] + } + return ParseCurl(tmp) +} + +func parseQuotedStr(r *strings.Reader, b rune) string { + var buf bytes.Buffer + var prevHasQ = false + + for { + nextB, _, err := r.ReadRune() + if err != nil { + break + } + if nextB == b && prevHasQ == false { + break + } + if nextB == '\\' && b == '"' && prevHasQ == false { + prevHasQ = true + continue + } + prevHasQ = false + buf.WriteRune(nextB) + } + return buf.String() +} + +func ParseCurl(cmdList []string) (resp ParseCurl_Resp) { + header := http.Header{} + + isHeader := false + isMethod := false + + for idx := 0; idx < len(cmdList); idx++ { + value := cmdList[idx] + if isHeader { + idx1 := strings.Index(value, ": ") + if idx1 >= 0 { + k := value[:idx1] + v := value[idx1+2:] + header.Set(k, v) + } + isHeader = false + continue + } + if isMethod { + if strings.ToUpper(value) != http.MethodGet { + resp.ErrMsg = "不支持的method: " + strconv.Quote(value) + return resp + } + isMethod = false + continue + } + valueLow := strings.ToLower(value) + switch valueLow { + case "-h": + isHeader = true + case "--compressed": + case "-x": + isMethod = true + case "-k", "--insecure": + resp.DownloadReq.Insecure = true + default: + if resp.DownloadReq.M3u8Url != "" { + resp.ErrMsg = "重复的url" + return resp + } + resp.DownloadReq.M3u8Url = value + } + } + resp.DownloadReq.HeaderMap = header + return resp +} + +func RunDownload_Req_ToCurlStr(req RunDownload_Req) string { + if req.M3u8Url == "" { + return "" + } + var buf bytes.Buffer + buf.WriteString("curl " + strconv.Quote(req.M3u8Url)) + if req.Insecure { + buf.WriteString(" \\\n -insecure") + } + for key, vList := range req.HeaderMap { + if len(vList) == 0 { + continue + } + buf.WriteString(" \\\n -H ") + buf.WriteString(`'` + key + `: ` + vList[0] + `'`) + } + return buf.String() +} diff --git a/download.go b/download.go index 89f89ff..3ee39da 100644 --- a/download.go +++ b/download.go @@ -70,6 +70,7 @@ type RunDownload_Req struct { FileName string // 文件名 SkipTsCountFromHead int // 跳过前面几个ts SetProxy string + HeaderMap map[string][]string } type downloadEnv struct { @@ -110,6 +111,9 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp "Accept-Language": []string{"zh-CN,zh;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5"}, "Referer": []string{host}, } + for key, valueList := range req.HeaderMap { + this.header[key] = valueList + } SetProgressBarTitle("嗅探m3u8") var m3u8Body []byte req.M3u8Url, m3u8Body, err = this.sniffM3u8(req.M3u8Url) diff --git a/export/main.go b/export/main.go index 18e38de..1f7cd15 100644 --- a/export/main.go +++ b/export/main.go @@ -22,7 +22,6 @@ func BuildCliBinary() { type buildCfg struct { GOOS string GOARCH string - Ext string } var list = []buildCfg{ { @@ -43,8 +42,8 @@ func BuildCliBinary() { }, } for _, cfg := range list { - name := "m3u8d_cli_v1.4.3_" + cfg.GOOS + "_" + cfg.GOARCH + cfg.Ext - cmd := exec.Command("go", "build", "-ldflags", "-s -w", "-o", filepath.Join(wd, "bin", name)) + name := "m3u8d_cli_v1.5.0_" + cfg.GOOS + "_" + cfg.GOARCH + cmd := exec.Command("go", "build", "-trimpath", "-ldflags", "-s -w", "-o", filepath.Join(wd, "bin", name)) cmd.Dir = filepath.Join(wd, "cmd") cmd.Env = append(os.Environ(), "GOOS="+cfg.GOOS) cmd.Env = append(cmd.Env, "GOARCH="+cfg.GOARCH) @@ -69,5 +68,7 @@ func CreateLibForQtUi() { ctx.Generate1(m3u8d.CloseOldEnv) ctx.Generate1(m3u8d.GetProgress) ctx.Generate1(m3u8d.GetWd) + ctx.Generate1(m3u8d.ParseCurlStr) + ctx.Generate1(m3u8d.RunDownload_Req_ToCurlStr) ctx.MustCreateAmd64LibraryInDir("m3u8d-qt") } diff --git a/go.mod b/go.mod index 7c14504..d4a5166 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.17 require ( github.com/orestonce/cdb v0.0.0-20220528005855-d187c22240e2 - github.com/orestonce/go2cpp v0.0.0-20220605110533-c77a8dd7fdfd + github.com/orestonce/go2cpp v0.0.0-20220625112310-a96256cb266b github.com/orestonce/gopool v0.0.0-20220508090328-d7d56d45b171 github.com/spf13/cobra v1.4.0 github.com/yapingcat/gomedia v0.0.0-20220623101430-02bb90c39484 diff --git a/go.sum b/go.sum index 2a1d452..9ceb0c3 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/orestonce/cdb v0.0.0-20220528005855-d187c22240e2 h1:AmGkuxSIOW0gA/jetY8d1DVV0cyQ08FMCxa1arkI6HQ= github.com/orestonce/cdb v0.0.0-20220528005855-d187c22240e2/go.mod h1:HMNNdA1LMQFJRwobtCzVevWcInFSo9rfs1fYeVYwU+c= -github.com/orestonce/go2cpp v0.0.0-20220605110533-c77a8dd7fdfd h1:q4MMzJG2Zdh9OLSiQfhPqL0/GGQ+B+SZmYDjbOjGW7Y= -github.com/orestonce/go2cpp v0.0.0-20220605110533-c77a8dd7fdfd/go.mod h1:1fsOAZftk08/dOTRqlp6f/MVwaEKOhrnPUg0RtWiSdY= +github.com/orestonce/go2cpp v0.0.0-20220625112310-a96256cb266b h1:fCPoY14Bm8725Ndki1OWKJ0wQrhFOMxeOEOEHpqMcVg= +github.com/orestonce/go2cpp v0.0.0-20220625112310-a96256cb266b/go.mod h1:1fsOAZftk08/dOTRqlp6f/MVwaEKOhrnPUg0RtWiSdY= github.com/orestonce/gopool v0.0.0-20220508090328-d7d56d45b171 h1:NnOl6HTrhrlTT7aaAybVOtq+fEztGFMoQtegckgwLdk= github.com/orestonce/gopool v0.0.0-20220508090328-d7d56d45b171/go.mod h1:MCQUrAPiG9/PTjHJuGqWLasKbIaG6z62KO6kfp90byM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= diff --git a/m3u8d-qt/curldialog.cpp b/m3u8d-qt/curldialog.cpp new file mode 100644 index 0000000..5ab39c8 --- /dev/null +++ b/m3u8d-qt/curldialog.cpp @@ -0,0 +1,33 @@ +#include "curldialog.h" +#include "ui_curldialog.h" + +CurlDialog::CurlDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::CurlDialog) +{ + ui->setupUi(this); +} + +CurlDialog::~CurlDialog() +{ + delete ui; +} + +void CurlDialog::SetText(QString v) +{ + if (v.isEmpty()) { + return; + } + ui->plainTextEdit->setPlainText(v); +} + +void CurlDialog::on_buttonBox_accepted() +{ + ParseCurl_Resp resp= ParseCurlStr(ui->plainTextEdit->toPlainText().toStdString()); + if (resp.ErrMsg.empty() == false) { + Toast::Instance()->SetError(resp.ErrMsg.c_str()); + this->reject(); + return; + } + this->Resp = resp; +} diff --git a/m3u8d-qt/curldialog.h b/m3u8d-qt/curldialog.h new file mode 100644 index 0000000..4975f87 --- /dev/null +++ b/m3u8d-qt/curldialog.h @@ -0,0 +1,29 @@ +#ifndef CURLDIALOG_H +#define CURLDIALOG_H + +#include +#include "m3u8d.h" + +namespace Ui { +class CurlDialog; +} + +class CurlDialog : public QDialog +{ + Q_OBJECT + +public: + explicit CurlDialog(QWidget *parent = 0); + ~CurlDialog(); + + void SetText(QString v); +public: + ParseCurl_Resp Resp; +private slots: + void on_buttonBox_accepted(); + +private: + Ui::CurlDialog *ui; +}; + +#endif // CURLDIALOG_H diff --git a/m3u8d-qt/curldialog.ui b/m3u8d-qt/curldialog.ui new file mode 100644 index 0000000..51fa029 --- /dev/null +++ b/m3u8d-qt/curldialog.ui @@ -0,0 +1,77 @@ + + + CurlDialog + + + + 0 + 0 + 879 + 445 + + + + curl模式 + + + + + + + + + + + + 从chrome中复制curl命令,然后粘贴在此处 + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + CurlDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + CurlDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/m3u8d-qt/m3u8d-qt.pro b/m3u8d-qt/m3u8d-qt.pro index 7c6109d..ff72c99 100644 --- a/m3u8d-qt/m3u8d-qt.pro +++ b/m3u8d-qt/m3u8d-qt.pro @@ -26,13 +26,17 @@ RC_FILE += version.rc SOURCES += \ main.cpp \ mainwindow.cpp \ - m3u8d.cpp + m3u8d.cpp \ + curldialog.cpp HEADERS += \ mainwindow.h \ - m3u8d.h + m3u8d.h \ + curldialog.h \ + version.rc FORMS += \ - mainwindow.ui + mainwindow.ui \ + curldialog.ui LIBS += -L$$PWD -lm3u8d-impl diff --git a/m3u8d-qt/m3u8d.cpp b/m3u8d-qt/m3u8d.cpp index cd21b23..4c71eec 100644 --- a/m3u8d-qt/m3u8d.cpp +++ b/m3u8d-qt/m3u8d.cpp @@ -73,6 +73,8 @@ extern __declspec(dllexport) void Go2cppFn_RunDownload(char* in, int inLen, char extern __declspec(dllexport) void Go2cppFn_CloseOldEnv(char* in, int inLen, char** out, int* outLen); extern __declspec(dllexport) void Go2cppFn_GetProgress(char* in, int inLen, char** out, int* outLen); extern __declspec(dllexport) void Go2cppFn_GetWd(char* in, int inLen, char** out, int* outLen); +extern __declspec(dllexport) void Go2cppFn_ParseCurlStr(char* in, int inLen, char** out, int* outLen); +extern __declspec(dllexport) void Go2cppFn_RunDownload_Req_ToCurlStr(char* in, int inLen, char** out, int* outLen); #ifdef __cplusplus } @@ -83,64 +85,106 @@ RunDownload_Resp RunDownload(RunDownload_Req in0){ std::string in; { { - uint32_t tmp22 = in0.M3u8Url.length(); - char tmp23[4]; - tmp23[0] = (uint32_t(tmp22) >> 24) & 0xFF; - tmp23[1] = (uint32_t(tmp22) >> 16) & 0xFF; - tmp23[2] = (uint32_t(tmp22) >> 8) & 0xFF; - tmp23[3] = (uint32_t(tmp22) >> 0) & 0xFF; - in.append(tmp23, 4); + uint32_t tmp36 = in0.M3u8Url.length(); + char tmp37[4]; + tmp37[0] = (uint32_t(tmp36) >> 24) & 0xFF; + tmp37[1] = (uint32_t(tmp36) >> 16) & 0xFF; + tmp37[2] = (uint32_t(tmp36) >> 8) & 0xFF; + tmp37[3] = (uint32_t(tmp36) >> 0) & 0xFF; + in.append(tmp37, 4); in.append(in0.M3u8Url); } { - uint32_t tmp24 = in0.HostType.length(); - char tmp25[4]; - tmp25[0] = (uint32_t(tmp24) >> 24) & 0xFF; - tmp25[1] = (uint32_t(tmp24) >> 16) & 0xFF; - tmp25[2] = (uint32_t(tmp24) >> 8) & 0xFF; - tmp25[3] = (uint32_t(tmp24) >> 0) & 0xFF; - in.append(tmp25, 4); + uint32_t tmp38 = in0.HostType.length(); + char tmp39[4]; + tmp39[0] = (uint32_t(tmp38) >> 24) & 0xFF; + tmp39[1] = (uint32_t(tmp38) >> 16) & 0xFF; + tmp39[2] = (uint32_t(tmp38) >> 8) & 0xFF; + tmp39[3] = (uint32_t(tmp38) >> 0) & 0xFF; + in.append(tmp39, 4); in.append(in0.HostType); } in.append((char*)(&in0.Insecure), 1); { - uint32_t tmp26 = in0.SaveDir.length(); - char tmp27[4]; - tmp27[0] = (uint32_t(tmp26) >> 24) & 0xFF; - tmp27[1] = (uint32_t(tmp26) >> 16) & 0xFF; - tmp27[2] = (uint32_t(tmp26) >> 8) & 0xFF; - tmp27[3] = (uint32_t(tmp26) >> 0) & 0xFF; - in.append(tmp27, 4); + uint32_t tmp40 = in0.SaveDir.length(); + char tmp41[4]; + tmp41[0] = (uint32_t(tmp40) >> 24) & 0xFF; + tmp41[1] = (uint32_t(tmp40) >> 16) & 0xFF; + tmp41[2] = (uint32_t(tmp40) >> 8) & 0xFF; + tmp41[3] = (uint32_t(tmp40) >> 0) & 0xFF; + in.append(tmp41, 4); in.append(in0.SaveDir); } { - uint32_t tmp28 = in0.FileName.length(); - char tmp29[4]; - tmp29[0] = (uint32_t(tmp28) >> 24) & 0xFF; - tmp29[1] = (uint32_t(tmp28) >> 16) & 0xFF; - tmp29[2] = (uint32_t(tmp28) >> 8) & 0xFF; - tmp29[3] = (uint32_t(tmp28) >> 0) & 0xFF; - in.append(tmp29, 4); + uint32_t tmp42 = in0.FileName.length(); + char tmp43[4]; + tmp43[0] = (uint32_t(tmp42) >> 24) & 0xFF; + tmp43[1] = (uint32_t(tmp42) >> 16) & 0xFF; + tmp43[2] = (uint32_t(tmp42) >> 8) & 0xFF; + tmp43[3] = (uint32_t(tmp42) >> 0) & 0xFF; + in.append(tmp43, 4); in.append(in0.FileName); } { - char tmp30[4]; - tmp30[0] = (uint32_t(in0.SkipTsCountFromHead) >> 24) & 0xFF; - tmp30[1] = (uint32_t(in0.SkipTsCountFromHead) >> 16) & 0xFF; - tmp30[2] = (uint32_t(in0.SkipTsCountFromHead) >> 8) & 0xFF; - tmp30[3] = (uint32_t(in0.SkipTsCountFromHead) >> 0) & 0xFF; - in.append(tmp30, 4); + char tmp44[4]; + tmp44[0] = (uint32_t(in0.SkipTsCountFromHead) >> 24) & 0xFF; + tmp44[1] = (uint32_t(in0.SkipTsCountFromHead) >> 16) & 0xFF; + tmp44[2] = (uint32_t(in0.SkipTsCountFromHead) >> 8) & 0xFF; + tmp44[3] = (uint32_t(in0.SkipTsCountFromHead) >> 0) & 0xFF; + in.append(tmp44, 4); } { - uint32_t tmp31 = in0.SetProxy.length(); - char tmp32[4]; - tmp32[0] = (uint32_t(tmp31) >> 24) & 0xFF; - tmp32[1] = (uint32_t(tmp31) >> 16) & 0xFF; - tmp32[2] = (uint32_t(tmp31) >> 8) & 0xFF; - tmp32[3] = (uint32_t(tmp31) >> 0) & 0xFF; - in.append(tmp32, 4); + uint32_t tmp45 = in0.SetProxy.length(); + char tmp46[4]; + tmp46[0] = (uint32_t(tmp45) >> 24) & 0xFF; + tmp46[1] = (uint32_t(tmp45) >> 16) & 0xFF; + tmp46[2] = (uint32_t(tmp45) >> 8) & 0xFF; + tmp46[3] = (uint32_t(tmp45) >> 0) & 0xFF; + in.append(tmp46, 4); in.append(in0.SetProxy); } + { + uint32_t tmp47 = in0.HeaderMap.size(); + char tmp48[4]; + tmp48[0] = (uint32_t(tmp47) >> 24) & 0xFF; + tmp48[1] = (uint32_t(tmp47) >> 16) & 0xFF; + tmp48[2] = (uint32_t(tmp47) >> 8) & 0xFF; + tmp48[3] = (uint32_t(tmp47) >> 0) & 0xFF; + in.append(tmp48, 4); + for(std::map>::iterator tmp49 = in0.HeaderMap.begin(); tmp49 != in0.HeaderMap.end(); ++tmp49) { + { + uint32_t tmp50 = tmp49->first.length(); + char tmp51[4]; + tmp51[0] = (uint32_t(tmp50) >> 24) & 0xFF; + tmp51[1] = (uint32_t(tmp50) >> 16) & 0xFF; + tmp51[2] = (uint32_t(tmp50) >> 8) & 0xFF; + tmp51[3] = (uint32_t(tmp50) >> 0) & 0xFF; + in.append(tmp51, 4); + in.append(tmp49->first); + } + { + uint32_t tmp52 = tmp49->second.size(); + char tmp53[4]; + tmp53[0] = (uint32_t(tmp52) >> 24) & 0xFF; + tmp53[1] = (uint32_t(tmp52) >> 16) & 0xFF; + tmp53[2] = (uint32_t(tmp52) >> 8) & 0xFF; + tmp53[3] = (uint32_t(tmp52) >> 0) & 0xFF; + in.append(tmp53, 4); + for (uint32_t tmp54=0; tmp54 < tmp52; ++tmp54) { + { + uint32_t tmp55 = tmp49->second[tmp54].length(); + char tmp56[4]; + tmp56[0] = (uint32_t(tmp55) >> 24) & 0xFF; + tmp56[1] = (uint32_t(tmp55) >> 16) & 0xFF; + tmp56[2] = (uint32_t(tmp55) >> 8) & 0xFF; + tmp56[3] = (uint32_t(tmp55) >> 0) & 0xFF; + in.append(tmp56, 4); + in.append(tmp49->second[tmp54]); + } + } + } + } + } } char *out = NULL; int outLen = 0; @@ -149,30 +193,30 @@ RunDownload_Resp RunDownload(RunDownload_Req in0){ int outIdx = 0; { { - uint32_t tmp33 = 0; - uint32_t tmp34 = uint32_t(uint8_t(out[outIdx+0]) << 24); - uint32_t tmp35 = uint32_t(uint8_t(out[outIdx+1]) << 16); - uint32_t tmp36 = uint32_t(uint8_t(out[outIdx+2]) << 8); - uint32_t tmp37 = uint32_t(uint8_t(out[outIdx+3]) << 0); - tmp33 = tmp34 | tmp35 | tmp36 | tmp37; + uint32_t tmp57 = 0; + uint32_t tmp58 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp59 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp60 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp61 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp57 = tmp58 | tmp59 | tmp60 | tmp61; outIdx+=4; - retValue.ErrMsg = std::string(out+outIdx, out+outIdx+tmp33); - outIdx+=tmp33; + retValue.ErrMsg = std::string(out+outIdx, out+outIdx+tmp57); + outIdx+=tmp57; } retValue.IsSkipped = (bool) out[outIdx]; outIdx++; retValue.IsCancel = (bool) out[outIdx]; outIdx++; { - uint32_t tmp38 = 0; - uint32_t tmp39 = uint32_t(uint8_t(out[outIdx+0]) << 24); - uint32_t tmp40 = uint32_t(uint8_t(out[outIdx+1]) << 16); - uint32_t tmp41 = uint32_t(uint8_t(out[outIdx+2]) << 8); - uint32_t tmp42 = uint32_t(uint8_t(out[outIdx+3]) << 0); - tmp38 = tmp39 | tmp40 | tmp41 | tmp42; + uint32_t tmp62 = 0; + uint32_t tmp63 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp64 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp65 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp66 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp62 = tmp63 | tmp64 | tmp65 | tmp66; outIdx+=4; - retValue.SaveFileTo = std::string(out+outIdx, out+outIdx+tmp38); - outIdx+=tmp38; + retValue.SaveFileTo = std::string(out+outIdx, out+outIdx+tmp62); + outIdx+=tmp62; } } if (out != NULL) { @@ -249,6 +293,285 @@ std::string GetWd(){ return retValue; } +ParseCurl_Resp ParseCurlStr(std::string in0){ + std::string in; + { + uint32_t tmp19 = in0.length(); + char tmp20[4]; + tmp20[0] = (uint32_t(tmp19) >> 24) & 0xFF; + tmp20[1] = (uint32_t(tmp19) >> 16) & 0xFF; + tmp20[2] = (uint32_t(tmp19) >> 8) & 0xFF; + tmp20[3] = (uint32_t(tmp19) >> 0) & 0xFF; + in.append(tmp20, 4); + in.append(in0); + } + char *out = NULL; + int outLen = 0; + Go2cppFn_ParseCurlStr((char *)in.data(), in.length(), &out, &outLen); + ParseCurl_Resp retValue; + int outIdx = 0; + { + { + uint32_t tmp21 = 0; + uint32_t tmp22 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp23 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp24 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp25 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp21 = tmp22 | tmp23 | tmp24 | tmp25; + outIdx+=4; + retValue.ErrMsg = std::string(out+outIdx, out+outIdx+tmp21); + outIdx+=tmp21; + } + { + { + uint32_t tmp26 = 0; + uint32_t tmp27 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp28 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp29 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp30 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp26 = tmp27 | tmp28 | tmp29 | tmp30; + outIdx+=4; + retValue.DownloadReq.M3u8Url = std::string(out+outIdx, out+outIdx+tmp26); + outIdx+=tmp26; + } + { + uint32_t tmp31 = 0; + uint32_t tmp32 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp33 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp34 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp35 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp31 = tmp32 | tmp33 | tmp34 | tmp35; + outIdx+=4; + retValue.DownloadReq.HostType = std::string(out+outIdx, out+outIdx+tmp31); + outIdx+=tmp31; + } + retValue.DownloadReq.Insecure = (bool) out[outIdx]; + outIdx++; + { + uint32_t tmp36 = 0; + uint32_t tmp37 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp38 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp39 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp40 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp36 = tmp37 | tmp38 | tmp39 | tmp40; + outIdx+=4; + retValue.DownloadReq.SaveDir = std::string(out+outIdx, out+outIdx+tmp36); + outIdx+=tmp36; + } + { + uint32_t tmp41 = 0; + uint32_t tmp42 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp43 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp44 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp45 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp41 = tmp42 | tmp43 | tmp44 | tmp45; + outIdx+=4; + retValue.DownloadReq.FileName = std::string(out+outIdx, out+outIdx+tmp41); + outIdx+=tmp41; + } + { + uint32_t tmp46 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp47 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp48 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp49 = uint32_t(uint8_t(out[outIdx+3]) << 0); + retValue.DownloadReq.SkipTsCountFromHead = tmp46 | tmp47 | tmp48 | tmp49; + outIdx+=4; + } + { + uint32_t tmp50 = 0; + uint32_t tmp51 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp52 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp53 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp54 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp50 = tmp51 | tmp52 | tmp53 | tmp54; + outIdx+=4; + retValue.DownloadReq.SetProxy = std::string(out+outIdx, out+outIdx+tmp50); + outIdx+=tmp50; + } + { + uint32_t tmp55 = 0; + uint32_t tmp56 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp57 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp58 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp59 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp55 = tmp56 | tmp57 | tmp58 | tmp59; + outIdx+=4; + for (uint32_t tmp60 = 0; tmp60 < tmp55; tmp60++) { + std::string tmp61; + { + uint32_t tmp62 = 0; + uint32_t tmp63 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp64 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp65 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp66 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp62 = tmp63 | tmp64 | tmp65 | tmp66; + outIdx+=4; + tmp61 = std::string(out+outIdx, out+outIdx+tmp62); + outIdx+=tmp62; + } + std::vector tmp67; + { + uint32_t tmp68 = 0; + uint32_t tmp69 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp70 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp71 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp72 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp68 = tmp69 | tmp70 | tmp71 | tmp72; + outIdx+=4; + for (uint32_t tmp73 = 0; tmp73 < tmp68; tmp73++) { + std::string tmp74; + { + uint32_t tmp75 = 0; + uint32_t tmp76 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp77 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp78 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp79 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp75 = tmp76 | tmp77 | tmp78 | tmp79; + outIdx+=4; + tmp74 = std::string(out+outIdx, out+outIdx+tmp75); + outIdx+=tmp75; + } + tmp67.push_back(tmp74); + } + } + retValue.DownloadReq.HeaderMap[tmp61] = tmp67; + } + } + } + } + if (out != NULL) { + free(out); + } + return retValue; +} + +std::string RunDownload_Req_ToCurlStr(RunDownload_Req in0){ + std::string in; + { + { + uint32_t tmp33 = in0.M3u8Url.length(); + char tmp34[4]; + tmp34[0] = (uint32_t(tmp33) >> 24) & 0xFF; + tmp34[1] = (uint32_t(tmp33) >> 16) & 0xFF; + tmp34[2] = (uint32_t(tmp33) >> 8) & 0xFF; + tmp34[3] = (uint32_t(tmp33) >> 0) & 0xFF; + in.append(tmp34, 4); + in.append(in0.M3u8Url); + } + { + uint32_t tmp35 = in0.HostType.length(); + char tmp36[4]; + tmp36[0] = (uint32_t(tmp35) >> 24) & 0xFF; + tmp36[1] = (uint32_t(tmp35) >> 16) & 0xFF; + tmp36[2] = (uint32_t(tmp35) >> 8) & 0xFF; + tmp36[3] = (uint32_t(tmp35) >> 0) & 0xFF; + in.append(tmp36, 4); + in.append(in0.HostType); + } + in.append((char*)(&in0.Insecure), 1); + { + uint32_t tmp37 = in0.SaveDir.length(); + char tmp38[4]; + tmp38[0] = (uint32_t(tmp37) >> 24) & 0xFF; + tmp38[1] = (uint32_t(tmp37) >> 16) & 0xFF; + tmp38[2] = (uint32_t(tmp37) >> 8) & 0xFF; + tmp38[3] = (uint32_t(tmp37) >> 0) & 0xFF; + in.append(tmp38, 4); + in.append(in0.SaveDir); + } + { + uint32_t tmp39 = in0.FileName.length(); + char tmp40[4]; + tmp40[0] = (uint32_t(tmp39) >> 24) & 0xFF; + tmp40[1] = (uint32_t(tmp39) >> 16) & 0xFF; + tmp40[2] = (uint32_t(tmp39) >> 8) & 0xFF; + tmp40[3] = (uint32_t(tmp39) >> 0) & 0xFF; + in.append(tmp40, 4); + in.append(in0.FileName); + } + { + char tmp41[4]; + tmp41[0] = (uint32_t(in0.SkipTsCountFromHead) >> 24) & 0xFF; + tmp41[1] = (uint32_t(in0.SkipTsCountFromHead) >> 16) & 0xFF; + tmp41[2] = (uint32_t(in0.SkipTsCountFromHead) >> 8) & 0xFF; + tmp41[3] = (uint32_t(in0.SkipTsCountFromHead) >> 0) & 0xFF; + in.append(tmp41, 4); + } + { + uint32_t tmp42 = in0.SetProxy.length(); + char tmp43[4]; + tmp43[0] = (uint32_t(tmp42) >> 24) & 0xFF; + tmp43[1] = (uint32_t(tmp42) >> 16) & 0xFF; + tmp43[2] = (uint32_t(tmp42) >> 8) & 0xFF; + tmp43[3] = (uint32_t(tmp42) >> 0) & 0xFF; + in.append(tmp43, 4); + in.append(in0.SetProxy); + } + { + uint32_t tmp44 = in0.HeaderMap.size(); + char tmp45[4]; + tmp45[0] = (uint32_t(tmp44) >> 24) & 0xFF; + tmp45[1] = (uint32_t(tmp44) >> 16) & 0xFF; + tmp45[2] = (uint32_t(tmp44) >> 8) & 0xFF; + tmp45[3] = (uint32_t(tmp44) >> 0) & 0xFF; + in.append(tmp45, 4); + for(std::map>::iterator tmp46 = in0.HeaderMap.begin(); tmp46 != in0.HeaderMap.end(); ++tmp46) { + { + uint32_t tmp47 = tmp46->first.length(); + char tmp48[4]; + tmp48[0] = (uint32_t(tmp47) >> 24) & 0xFF; + tmp48[1] = (uint32_t(tmp47) >> 16) & 0xFF; + tmp48[2] = (uint32_t(tmp47) >> 8) & 0xFF; + tmp48[3] = (uint32_t(tmp47) >> 0) & 0xFF; + in.append(tmp48, 4); + in.append(tmp46->first); + } + { + uint32_t tmp49 = tmp46->second.size(); + char tmp50[4]; + tmp50[0] = (uint32_t(tmp49) >> 24) & 0xFF; + tmp50[1] = (uint32_t(tmp49) >> 16) & 0xFF; + tmp50[2] = (uint32_t(tmp49) >> 8) & 0xFF; + tmp50[3] = (uint32_t(tmp49) >> 0) & 0xFF; + in.append(tmp50, 4); + for (uint32_t tmp51=0; tmp51 < tmp49; ++tmp51) { + { + uint32_t tmp52 = tmp46->second[tmp51].length(); + char tmp53[4]; + tmp53[0] = (uint32_t(tmp52) >> 24) & 0xFF; + tmp53[1] = (uint32_t(tmp52) >> 16) & 0xFF; + tmp53[2] = (uint32_t(tmp52) >> 8) & 0xFF; + tmp53[3] = (uint32_t(tmp52) >> 0) & 0xFF; + in.append(tmp53, 4); + in.append(tmp46->second[tmp51]); + } + } + } + } + } + } + char *out = NULL; + int outLen = 0; + Go2cppFn_RunDownload_Req_ToCurlStr((char *)in.data(), in.length(), &out, &outLen); + std::string retValue; + int outIdx = 0; + { + uint32_t tmp54 = 0; + uint32_t tmp55 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp56 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp57 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp58 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp54 = tmp55 | tmp56 | tmp57 | tmp58; + outIdx+=4; + retValue = std::string(out+outIdx, out+outIdx+tmp54); + outIdx+=tmp54; + } + if (out != NULL) { + free(out); + } + return retValue; +} + // Qt: diff --git a/m3u8d-qt/m3u8d.h b/m3u8d-qt/m3u8d.h index ebba006..b15d1ab 100644 --- a/m3u8d-qt/m3u8d.h +++ b/m3u8d-qt/m3u8d.h @@ -15,6 +15,7 @@ struct RunDownload_Req{ std::string FileName; int32_t SkipTsCountFromHead; std::string SetProxy; + std::map> HeaderMap; RunDownload_Req(): Insecure(false),SkipTsCountFromHead(0){} }; struct RunDownload_Resp{ @@ -33,6 +34,12 @@ struct GetProgress_Resp{ }; GetProgress_Resp GetProgress(); std::string GetWd(); +struct ParseCurl_Resp{ + std::string ErrMsg; + RunDownload_Req DownloadReq; +}; +ParseCurl_Resp ParseCurlStr(std::string in0); +std::string RunDownload_Req_ToCurlStr(RunDownload_Req in0); #include #include diff --git a/m3u8d-qt/mainwindow.cpp b/m3u8d-qt/mainwindow.cpp index abf3f5e..6f56224 100644 --- a/m3u8d-qt/mainwindow.cpp +++ b/m3u8d-qt/mainwindow.cpp @@ -3,6 +3,7 @@ #include "m3u8d.h" #include #include +#include "curldialog.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), @@ -64,6 +65,7 @@ void MainWindow::on_pushButton_RunDownload_clicked() req.FileName = ui->lineEdit_FileName->text().toStdString(); req.SkipTsCountFromHead = ui->lineEdit_SkipTsCountFromHead->text().toInt(); req.SetProxy = ui->lineEdit_SetProxy->text().toStdString(); + req.HeaderMap = m_HeaderMap; m_syncUi.AddRunFnOn_OtherThread([req, this](){ RunDownload_Resp resp = RunDownload(req); @@ -106,3 +108,21 @@ void MainWindow::on_pushButton_StopDownload_clicked() { CloseOldEnv(); } + +void MainWindow::on_pushButton_curlMode_clicked() +{ + RunDownload_Req req; + req.M3u8Url = ui->lineEdit_M3u8Url->text().toStdString(); + req.Insecure = ui->checkBox_Insecure->isChecked(); + req.HeaderMap = m_HeaderMap; + CurlDialog dlg(this); + dlg.SetText(QString::fromStdString(RunDownload_Req_ToCurlStr(req))); + dlg.show(); + if (dlg.exec() != QDialog::Accepted) { + return; + } + ParseCurl_Resp resp= dlg.Resp; + ui->lineEdit_M3u8Url->setText(QString::fromStdString(resp.DownloadReq.M3u8Url)); + ui->checkBox_Insecure->setChecked(resp.DownloadReq.Insecure); + this->m_HeaderMap = resp.DownloadReq.HeaderMap; +} diff --git a/m3u8d-qt/mainwindow.h b/m3u8d-qt/mainwindow.h index 5ef614e..fffea9d 100644 --- a/m3u8d-qt/mainwindow.h +++ b/m3u8d-qt/mainwindow.h @@ -23,9 +23,12 @@ private slots: void on_pushButton_StopDownload_clicked(); + void on_pushButton_curlMode_clicked(); + private: Ui::MainWindow *ui; RunOnUiThread m_syncUi; + std::map> m_HeaderMap; }; #endif // MAINWINDOW_H diff --git a/m3u8d-qt/mainwindow.ui b/m3u8d-qt/mainwindow.ui index a07c9e4..ef8ca47 100644 --- a/m3u8d-qt/mainwindow.ui +++ b/m3u8d-qt/mainwindow.ui @@ -67,16 +67,22 @@ + + + 0 + 0 + + - 40 - 20 + 0 + 0 - 40 - 20 + 99999 + 99999 @@ -122,6 +128,13 @@ + + + + curl模式 + + + diff --git a/m3u8d-qt/version.rc b/m3u8d-qt/version.rc index 9446f11..81c1679 100644 --- a/m3u8d-qt/version.rc +++ b/m3u8d-qt/version.rc @@ -7,8 +7,8 @@ IDI_ICON1 ICON "favicon.ico" #endif VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,4,3,0 - PRODUCTVERSION 1,4,3,0 + FILEVERSION 1,5,0,0 + PRODUCTVERSION 1,5,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS VS_FF_DEBUG @@ -23,7 +23,7 @@ VS_VERSION_INFO VERSIONINFO BEGIN BLOCK "080404b0" BEGIN - VALUE "ProductVersion", "1.4.3.0\0" + VALUE "ProductVersion", "1.5.0.0\0" VALUE "ProductName", "m3u8Ƶع\0" VALUE "LegalCopyright", "https://github.com/orestonce/m3u8d\0" VALUE "FileDescription", "m3u8Ƶع\0" @@ -34,4 +34,4 @@ VS_VERSION_INFO VERSIONINFO BEGIN VALUE "Translation", 0x804, 1200 END - END \ No newline at end of file + END