package curl2info import ( "fmt" "io/ioutil" "log" "net/http" "net/http/cookiejar" "net/url" "os" "regexp" "strconv" "strings" "474420502.top/eson/requests" ) // CURL 信息结构 type CURL struct { ParsedURL *url.URL Method string Header http.Header CookieJar http.CookieJar Cookies []*http.Cookie Body *requests.Body Auth *requests.BasicAuth Timeout int // second Insecure bool ITask string } // New new 一个 curl 出来 func New() *CURL { u := &CURL{} u.Insecure = false u.Header = make(http.Header) u.CookieJar, _ = cookiejar.New(nil) u.Body = requests.NewBody() u.Timeout = 30 return u } func (curl *CURL) String() string { if curl != nil { return fmt.Sprintf("Method: %s\nParsedURL: %s\nHeader: %s\nCookie: %s", curl.Method, curl.ParsedURL.String(), curl.Header, curl.Cookies) } return "" } // CreateSession 创建Session func (curl *CURL) CreateSession() *requests.Session { ses := requests.NewSession() ses.SetHeader(curl.Header) ses.SetCookies(curl.ParsedURL, curl.Cookies) ses.SetConfig(requests.CRequestTimeout, curl.Timeout) if curl.Auth != nil { ses.SetConfig(requests.CBasicAuth, curl.Auth) } if curl.Insecure { ses.SetConfig(requests.CInsecure, curl.Insecure) } return ses } // CreateWorkflow 根据Session 创建Workflow func (curl *CURL) CreateWorkflow(ses *requests.Session) *requests.Workflow { var wf *requests.Workflow if ses == nil { ses = curl.CreateSession() } switch curl.Method { case "HEAD": wf = ses.Head(curl.ParsedURL.String()) case "GET": wf = ses.Get(curl.ParsedURL.String()) case "POST": wf = ses.Post(curl.ParsedURL.String()) case "PUT": wf = ses.Put(curl.ParsedURL.String()) case "PATCH": wf = ses.Patch(curl.ParsedURL.String()) case "OPTIONS": wf = ses.Options(curl.ParsedURL.String()) case "DELETE": wf = ses.Delete(curl.ParsedURL.String()) } wf.SetBody(curl.Body) return wf } // ParseRawCURL curl_bash 可以用trie改进 没空改 func ParseRawCURL(scurl string) (cURL *CURL, err error) { defer func() { if _err := recover(); _err != nil { cURL = nil err = _err.(error) } }() executor := newPQueueExecute() curl := New() if scurl[0] == '"' && scurl[len(scurl)-1] == '"' { scurl = strings.Trim(scurl, `"`) } else if scurl[0] == '\'' && scurl[len(scurl)-1] == '\'' { scurl = strings.Trim(scurl, `'`) } scurl = strings.TrimSpace(scurl) scurl = strings.TrimLeft(scurl, "curl") mathches := regexp.MustCompile(`--[^ ]+ +'[^']+'|--[^ ]+ +[^ ]+|-[A-Za-z] +'[^']+'|-[A-Za-z] +[^ ]+| '[^']+'|--[a-z]+ {0,}`).FindAllString(scurl, -1) for _, m := range mathches { m = strings.TrimSpace(m) switch v := m[0]; v { case '\'': purl, err := url.Parse(strings.Trim(m, "'")) if err != nil { panic(err) } curl.ParsedURL = purl case '-': exec := judgeOptions(curl, m) if exec != nil { executor.Push(exec) } } } for executor.Len() > 0 { exec := executor.Pop() exec.Execute() } if curl.Method == "" { curl.Method = "GET" } return curl, nil } func judgeOptions(u *CURL, soption string) *parseFunction { word := trieStrWord(soption) if ioe := optionTrie.SearchMostPrefix(&word); ioe != nil { oe := ioe.(*optionExecute) return oe.BuildFunction(u, soption) } log.Println(soption, " no haved this option") return nil } func extractData(re, soption string) string { datas := regexp.MustCompile(re).FindStringSubmatch(soption) return strings.Trim(datas[1], "'") } func parseITask(u *CURL, value string) { u.ITask = value } func parseTimeout(u *CURL, value string) { timeout, err := strconv.Atoi(value) if err != nil { panic(err) } u.Timeout = timeout } func parseInsecure(u *CURL, soption string) { u.Insecure = true } func parseUser(u *CURL, soption string) { auth := strings.Split(soption, ":") u.Auth = &requests.BasicAuth{User: auth[0], Password: auth[1]} } func parseUserAgent(u *CURL, value string) { u.Header.Add("User-Agent", value) } func parseOptI(u *CURL, soption string) { u.Method = "HEAD" } func parseOptX(u *CURL, soption string) { matches := regexp.MustCompile("-X +(.+)").FindStringSubmatch(soption) method := strings.Trim(matches[1], "'") u.Method = method } func parseBodyURLEncode(u *CURL, data string) { if u.Method != "" { u.Method = "POST" } u.Body.SetPrefix(requests.TypeURLENCODED) u.Body.SetIOBody(data) } func parseBodyRaw(u *CURL, data string) { if u.Method != "" { u.Method = "POST" } u.Body.SetPrefix(requests.TypeURLENCODED) u.Body.SetIOBody(data) } func parseBodyASCII(u *CURL, data string) { if u.Method != "" { u.Method = "POST" } u.Body.SetPrefix(requests.TypeURLENCODED) if data[0] != '@' { u.Body.SetIOBody(data) } else { f, err := os.Open(data[1:]) if err != nil { panic(err) } defer f.Close() bdata, err := ioutil.ReadAll(f) if err != nil { panic(err) } u.Body.SetIOBody(bdata) } } // 处理@ 并且替/r/n符号 func parseBodyBinary(u *CURL, data string) { if u.Method != "" { u.Method = "POST" } u.Body.SetPrefix(requests.TypeURLENCODED) if data[0] != '@' { u.Body.SetIOBody(data) } else { f, err := os.Open(data[1:]) if err != nil { panic(err) } defer f.Close() bdata, err := ioutil.ReadAll(f) if err != nil { panic(err) } bdata = regexp.MustCompile("\n|\r").ReplaceAll(bdata, []byte("")) u.Body.SetIOBody(bdata) } } func parseHeader(u *CURL, soption string) { matches := regexp.MustCompile(`'([^:]+): ([^']+)'`).FindAllStringSubmatch(soption, 1)[0] key := matches[1] value := matches[2] switch key { case "Cookie": u.Cookies = ReadRawCookies(value, "") u.CookieJar.SetCookies(u.ParsedURL, u.Cookies) case "Content-Type": u.Body.SetPrefix(value) default: u.Header.Add(key, value) } }