├── .gitignore ├── go.mod ├── NOTICE ├── callback.h ├── examples ├── https.go ├── simple.go ├── https_skip_peer_verify.go ├── https_callback.go ├── multi_sample.go ├── ftpget.go ├── renren_login.go ├── channal_callback.go ├── post-callback.go ├── sendrecv.go ├── sepheaders.go ├── progress.go ├── renren_upload.go ├── multi_and_select.go └── misc.go ├── .travis.yml ├── core_test.go ├── c-callback.c ├── logging.go ├── share.go ├── callback.go ├── easy_test.go ├── logging_test.go ├── README.md ├── core.go ├── misc ├── codegen.py └── compatgen.py ├── multi.go ├── const.go ├── LICENSE ├── const_gen.go ├── easy.go └── compat.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.6 2 | *.o 3 | src/_cgo_* 4 | src/_obj/ 5 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/andelf/go-curl 2 | 3 | go 1.21.5 4 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | https://github.com/andelf/go-curl 2 | Copyright 2014 Shuyu Wang 3 | -------------------------------------------------------------------------------- /callback.h: -------------------------------------------------------------------------------- 1 | 2 | void *return_header_function(); 3 | void *return_write_function(); 4 | void *return_read_function(); 5 | 6 | void *return_progress_function(); 7 | -------------------------------------------------------------------------------- /examples/https.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | curl "github.com/andelf/go-curl" 5 | ) 6 | 7 | func main() { 8 | easy := curl.EasyInit() 9 | defer easy.Cleanup() 10 | if easy != nil { 11 | easy.Setopt(curl.OPT_URL, "https://baidu.com/") 12 | easy.Perform() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/simple.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | curl "github.com/andelf/go-curl" 5 | ) 6 | 7 | func main() { 8 | easy := curl.EasyInit() 9 | defer easy.Cleanup() 10 | if easy != nil { 11 | easy.Setopt(curl.OPT_URL, "http://www.google.com/") 12 | easy.Perform() 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.9 4 | - 1.8 5 | - 1.7 6 | - 1.6 7 | before_install: 8 | - sudo apt-get update -qq > apt-get.out 2>&1 || (cat apt-get.out && exit 1) 9 | install: go build -x -v 10 | script: go test -v 11 | notifications: 12 | email: 13 | recipients: 14 | - fledna@foxmail.com 15 | on_success: change 16 | on_failure: always 17 | -------------------------------------------------------------------------------- /examples/https_skip_peer_verify.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | curl "github.com/andelf/go-curl" 5 | ) 6 | 7 | func main() { 8 | easy := curl.EasyInit() 9 | defer easy.Cleanup() 10 | if easy != nil { 11 | easy.Setopt(curl.OPT_URL, "https://mail.google.com/") 12 | 13 | // OPT_SSL_VERIFYPEER determines whether curl verifies the authenticity of the peer's certificate. 14 | // Do not disable OPT_SSL_VERIFYPEER unless you absolutely sure of the security implications. 15 | // https://curl.se/libcurl/c/CURLOPT_SSL_VERIFYPEER.html 16 | easy.Setopt(curl.OPT_SSL_VERIFYPEER, false) // 0 also means false 17 | 18 | easy.Perform() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/https_callback.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | curl "github.com/andelf/go-curl" 6 | ) 7 | 8 | func main() { 9 | easy := curl.EasyInit() 10 | defer easy.Cleanup() 11 | 12 | easy.Setopt(curl.OPT_URL, "https://www.baidu.com/") 13 | 14 | // OPTIONAL - make a callback function 15 | fooTest := func (buf []byte, userdata interface{}) bool { 16 | println("DEBUG: size=>", len(buf)) 17 | println("DEBUG: content=>", string(buf)) 18 | return true 19 | } 20 | 21 | easy.Setopt(curl.OPT_WRITEFUNCTION, fooTest) 22 | 23 | if err := easy.Perform(); err != nil { 24 | fmt.Printf("ERROR: %v\n", err) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /core_test.go: -------------------------------------------------------------------------------- 1 | package curl 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestVersionInfo(t *testing.T) { 8 | info := VersionInfo(VERSION_FIRST) 9 | expectedProtocols := []string{"dict", "file", "ftp", "ftps", "gopher", "http", "https", "imap", "imaps", "ldap", "ldaps", "pop3", "pop3s", "rtmp", "rtsp", "smtp", "smtps", "telnet", "tftp", "scp", "sftp", "smb", "smbs"} 10 | protocols := info.Protocols 11 | for _, protocol := range protocols { 12 | found := false 13 | for _, expectedProtocol := range expectedProtocols { 14 | if expectedProtocol == protocol { 15 | found = true 16 | break 17 | } 18 | } 19 | if !found { 20 | t.Errorf("protocol should be in %v and is %v.", expectedProtocols, protocol) 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/multi_sample.go: -------------------------------------------------------------------------------- 1 | 2 | package main 3 | 4 | import ( 5 | curl "github.com/andelf/go-curl" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | 11 | ch1 := curl.EasyInit() 12 | ch2 := curl.EasyInit() 13 | 14 | ch1.Setopt(curl.OPT_URL, "http://www.163.com") 15 | ch1.Setopt(curl.OPT_HEADER, 0) 16 | ch1.Setopt(curl.OPT_VERBOSE, true) 17 | ch2.Setopt(curl.OPT_URL, "http://www.baidu.com") 18 | ch2.Setopt(curl.OPT_HEADER, 0) 19 | ch2.Setopt(curl.OPT_VERBOSE, true) 20 | 21 | mh := curl.MultiInit() 22 | 23 | mh.AddHandle(ch1) 24 | mh.AddHandle(ch2) 25 | 26 | for { 27 | nRunning, _ := mh.Perform() 28 | // println("n =", nRunning) 29 | if nRunning == 0 { 30 | println("ok") 31 | break 32 | } 33 | time.Sleep(1000) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /examples/ftpget.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | curl "github.com/andelf/go-curl" 5 | "os" 6 | ) 7 | 8 | const filename = "README" 9 | 10 | func main() { 11 | curl.GlobalInit(curl.GLOBAL_DEFAULT) 12 | defer curl.GlobalCleanup() 13 | easy := curl.EasyInit() 14 | defer easy.Cleanup() 15 | 16 | easy.Setopt(curl.OPT_URL, "ftp://ftp.gnu.org/README") 17 | 18 | // define our callback use lambda function 19 | easy.Setopt(curl.OPT_WRITEFUNCTION, func(ptr []byte, userdata interface{}) bool { 20 | file := userdata.(*os.File) 21 | if _, err := file.Write(ptr); err != nil { 22 | return false 23 | } 24 | return true 25 | }) 26 | 27 | fp, _ := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0777) 28 | defer fp.Close() // defer close 29 | 30 | easy.Setopt(curl.OPT_WRITEDATA, fp) 31 | 32 | easy.Setopt(curl.OPT_VERBOSE, true) 33 | 34 | if err := easy.Perform(); err != nil { 35 | println("ERROR", err.Error()) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/renren_login.go: -------------------------------------------------------------------------------- 1 | // 测试人人网登录, 并保存cookiejar 2 | package main 3 | 4 | import ( 5 | "flag" 6 | curl "github.com/andelf/go-curl" 7 | ) 8 | 9 | func main() { 10 | // init the curl session 11 | 12 | var username *string = flag.String("username", "test", "renren.com email") 13 | var password *string = flag.String("password", "test", "renren.com password") 14 | 15 | flag.Parse() 16 | 17 | easy := curl.EasyInit() 18 | defer easy.Cleanup() 19 | 20 | easy.Setopt(curl.OPT_URL, "http://m.renren.com/home.do") 21 | 22 | easy.Setopt(curl.OPT_PORT, 80) 23 | easy.Setopt(curl.OPT_VERBOSE, true) 24 | 25 | easy.Setopt(curl.OPT_COOKIEJAR, "./cookie.jar") 26 | 27 | // disable HTTP/1.1 Expect: 100-continue 28 | easy.Setopt(curl.OPT_HTTPHEADER, []string{"Expect:"}) 29 | 30 | postdata := "email=" + *username + "&password=" + *password + "&login=" + easy.Escape("登录") 31 | easy.Setopt(curl.OPT_POSTFIELDS, postdata) 32 | 33 | if err := easy.Perform(); err != nil { 34 | println("ERROR: ", err.Error()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/channal_callback.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | curl "github.com/andelf/go-curl" 5 | "time" 6 | ) 7 | 8 | func write_data(ptr []byte, userdata interface{}) bool { 9 | ch, ok := userdata.(chan string) 10 | if ok { 11 | ch <- string(ptr) 12 | return true // ok 13 | } else { 14 | println("ERROR!") 15 | return false 16 | } 17 | return false 18 | } 19 | 20 | func main() { 21 | curl.GlobalInit(curl.GLOBAL_ALL) 22 | 23 | // init the curl session 24 | easy := curl.EasyInit() 25 | defer easy.Cleanup() 26 | 27 | easy.Setopt(curl.OPT_URL, "http://cn.bing.com/") 28 | 29 | easy.Setopt(curl.OPT_WRITEFUNCTION, write_data) 30 | 31 | // make a chan 32 | ch := make(chan string, 100) 33 | go func(ch chan string) { 34 | for { 35 | data := <-ch 36 | println("Got data size=", len(data)) 37 | } 38 | }(ch) 39 | 40 | easy.Setopt(curl.OPT_WRITEDATA, ch) 41 | 42 | if err := easy.Perform(); err != nil { 43 | println("ERROR: ", err.Error()) 44 | } 45 | 46 | time.Sleep(10000) // wait gorotine 47 | } 48 | -------------------------------------------------------------------------------- /examples/post-callback.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | curl "github.com/andelf/go-curl" 5 | "time" 6 | ) 7 | 8 | const POST_DATA = "a_test_data_only" 9 | 10 | var sent = false 11 | 12 | func main() { 13 | // init the curl session 14 | easy := curl.EasyInit() 15 | defer easy.Cleanup() 16 | 17 | easy.Setopt(curl.OPT_URL, "http://www.google.com") 18 | 19 | easy.Setopt(curl.OPT_POST, true) 20 | easy.Setopt(curl.OPT_VERBOSE, true) 21 | 22 | easy.Setopt(curl.OPT_READFUNCTION, 23 | func(ptr []byte, userdata interface{}) int { 24 | // WARNING: never use append() 25 | if !sent { 26 | sent = true 27 | ret := copy(ptr, POST_DATA) 28 | return ret 29 | } 30 | return 0 // sent ok 31 | }) 32 | 33 | // disable HTTP/1.1 Expect 100 34 | easy.Setopt(curl.OPT_HTTPHEADER, []string{"Expect:"}) 35 | // must set 36 | easy.Setopt(curl.OPT_POSTFIELDSIZE, len(POST_DATA)) 37 | 38 | if err := easy.Perform(); err != nil { 39 | println("ERROR: ", err.Error()) 40 | } 41 | 42 | time.Sleep(10000) // wait gorotine 43 | } 44 | -------------------------------------------------------------------------------- /examples/sendrecv.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | curl "github.com/andelf/go-curl" 6 | "time" 7 | ) 8 | 9 | const POST_DATA = "a_test_data_only" 10 | 11 | var sent = false 12 | 13 | func main() { 14 | // init the curl session 15 | 16 | easy := curl.EasyInit() 17 | defer easy.Cleanup() 18 | 19 | easy.Setopt(curl.OPT_URL, "http://www.renren.com") 20 | 21 | easy.Setopt(curl.OPT_PORT, 80) 22 | easy.Setopt(curl.OPT_VERBOSE, true) 23 | easy.Setopt(curl.OPT_CONNECT_ONLY, true) 24 | 25 | easy.Setopt(curl.OPT_WRITEFUNCTION, nil) 26 | 27 | if err := easy.Perform(); err != nil { 28 | println("ERROR: ", err.Error()) 29 | } 30 | 31 | easy.Send([]byte("HEAD / HTTP/1.0\r\nHost: www.renren.com\r\n\r\n")) 32 | 33 | buf := make([]byte, 1000) 34 | time.Sleep(1000000000) // wait gorotine 35 | num, err := easy.Recv(buf) 36 | if err != nil { 37 | println("ERROR:", err.Error()) 38 | } 39 | println("recv num = ", num) 40 | // NOTE: must use buf[:num] 41 | println(string(buf[:num])) 42 | 43 | fmt.Printf("got:\n%#v\n", string(buf[:num])) 44 | } 45 | -------------------------------------------------------------------------------- /examples/sepheaders.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | curl "github.com/andelf/go-curl" 5 | "os" 6 | ) 7 | 8 | const ( 9 | headerfilename = "head.out" 10 | bodyfilename = "body.out" 11 | ) 12 | 13 | func write_data(ptr []byte, userdata interface{}) bool { 14 | //println("DEBUG(write_data): ", userdata) 15 | //println("DEBUG", userdata.(interface{})) 16 | fp := userdata.(*os.File) 17 | if _, err := fp.Write(ptr); err == nil { 18 | return true 19 | } 20 | return false 21 | } 22 | 23 | func main() { 24 | curl.GlobalInit(curl.GLOBAL_ALL) 25 | 26 | // init the curl session 27 | easy := curl.EasyInit() 28 | defer easy.Cleanup() 29 | 30 | // set URL to get 31 | easy.Setopt(curl.OPT_URL, "http://cn.bing.com/") 32 | 33 | // no progress meter 34 | easy.Setopt(curl.OPT_NOPROGRESS, true) 35 | 36 | easy.Setopt(curl.OPT_WRITEFUNCTION, write_data) 37 | 38 | // write file 39 | fp, _ := os.OpenFile(bodyfilename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0777) 40 | defer fp.Close() 41 | easy.Setopt(curl.OPT_WRITEDATA, fp) 42 | 43 | // easy.Setopt(curl.OPT_WRITEHEADER, 0) 44 | 45 | if err := easy.Perform(); err != nil { 46 | println("ERROR: ", err.Error()) 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /c-callback.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "callback.h" 4 | #include "_cgo_export.h" 5 | 6 | /* for OPT_HEADERFUNCTION */ 7 | size_t header_function( char *ptr, size_t size, size_t nmemb, void *ctx) { 8 | return goCallHeaderFunction(ptr, size*nmemb, ctx); 9 | } 10 | 11 | void *return_header_function() { 12 | return (void *)&header_function; 13 | } 14 | 15 | 16 | /* for OPT_WRITEFUNCTION */ 17 | size_t write_function( char *ptr, size_t size, size_t nmemb, void *ctx) { 18 | return goCallWriteFunction(ptr, size*nmemb, ctx); 19 | } 20 | 21 | void *return_write_function() { 22 | return (void *)&write_function; 23 | } 24 | 25 | /* for OPT_READFUNCTION */ 26 | size_t read_function( char *ptr, size_t size, size_t nmemb, void *ctx) { 27 | return goCallReadFunction(ptr, size*nmemb, ctx); 28 | } 29 | 30 | void *return_read_function() { 31 | return (void *)&read_function; 32 | } 33 | 34 | 35 | /* for OPT_PROGRESSFUNCTION */ 36 | int progress_function(void *ctx, double dltotal, double dlnow, double ultotal, double ulnow) { 37 | return goCallProgressFunction(dltotal, dlnow, ultotal, ulnow, ctx); 38 | } 39 | 40 | void *return_progress_function() { 41 | return (void *)progress_function; 42 | } 43 | -------------------------------------------------------------------------------- /examples/progress.go: -------------------------------------------------------------------------------- 1 | // A sample program to show how to use PROGRESS callback to calculate 2 | // downloading percentage and speed 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | curl "github.com/andelf/go-curl" 8 | "time" 9 | ) 10 | 11 | func write_data(ptr []byte, userdata interface{}) bool { 12 | // make it ok, do nothing 13 | return true 14 | } 15 | 16 | func main() { 17 | curl.GlobalInit(curl.GLOBAL_ALL) 18 | 19 | // init the curl session 20 | easy := curl.EasyInit() 21 | defer easy.Cleanup() 22 | 23 | easy.Setopt(curl.OPT_URL, "http://curl.haxx.se/download/curl-7.22.0.tar.gz") 24 | 25 | easy.Setopt(curl.OPT_WRITEFUNCTION, write_data) 26 | 27 | easy.Setopt(curl.OPT_NOPROGRESS, false) 28 | 29 | started := int64(0) 30 | easy.Setopt(curl.OPT_PROGRESSFUNCTION, func(dltotal, dlnow, ultotal, ulnow float64, userdata interface{}) bool { 31 | // canceled when 50% finished 32 | if dlnow/dltotal > 0.5 { 33 | println("") 34 | // abort downloading 35 | return false 36 | } 37 | if started == 0 { 38 | started = time.Now().Unix() 39 | } 40 | fmt.Printf("Downloaded: %3.2f%%, Speed: %.1fKiB/s \r", dlnow/dltotal*100, dlnow/1000/float64((time.Now().Unix()-started))) 41 | return true 42 | }) 43 | 44 | if err := easy.Perform(); err != nil { 45 | fmt.Printf("ERROR: %v\n", err) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /logging.go: -------------------------------------------------------------------------------- 1 | package curl 2 | 3 | import ( 4 | "log" 5 | ) 6 | 7 | const ( 8 | _DEBUG = 10 * (iota + 1) 9 | _INFO 10 | _WARN 11 | _ERROR 12 | ) 13 | 14 | const _DEFAULT_LOG_LEVEL = _WARN 15 | 16 | var log_level = _DEFAULT_LOG_LEVEL 17 | 18 | // SetLogLevel changes the log level which determines the granularity of the 19 | // messages that are logged. Available log levels are: "DEBUG", "INFO", 20 | // "WARN", "ERROR" and "DEFAULT_LOG_LEVEL". 21 | func SetLogLevel(levelName string) { 22 | switch levelName { 23 | case "DEBUG": 24 | log_level = _DEBUG 25 | case "INFO": 26 | log_level = _INFO 27 | case "WARN": 28 | log_level = _WARN 29 | case "ERROR": 30 | log_level = _ERROR 31 | case "DEFAULT_LOG_LEVEL": 32 | log_level = _DEFAULT_LOG_LEVEL 33 | } 34 | } 35 | 36 | func logf(limitLevel int, format string, args ...interface{}) { 37 | if log_level <= limitLevel { 38 | log.Printf(format, args...) 39 | } 40 | } 41 | 42 | func debugf(format string, args ...interface{}) { 43 | logf(_DEBUG, format, args...) 44 | } 45 | 46 | func infof(format string, args ...interface{}) { 47 | logf(_INFO, format, args...) 48 | } 49 | 50 | func warnf(format string, args ...interface{}) { 51 | logf(_WARN, format, args...) 52 | } 53 | 54 | func errorf(format string, args ...interface{}) { 55 | logf(_ERROR, format, args...) 56 | } 57 | -------------------------------------------------------------------------------- /share.go: -------------------------------------------------------------------------------- 1 | package curl 2 | 3 | /* 4 | #include 5 | 6 | static CURLSHcode curl_share_setopt_long(CURLSH *handle, CURLSHoption option, long parameter) { 7 | return curl_share_setopt(handle, option, parameter); 8 | } 9 | static CURLSHcode curl_share_setopt_pointer(CURLSH *handle, CURLSHoption option, void *parameter) { 10 | return curl_share_setopt(handle, option, parameter); 11 | } 12 | */ 13 | import "C" 14 | 15 | import "unsafe" 16 | 17 | // implement os.Error interface 18 | type CurlShareError C.CURLMcode 19 | 20 | func (e CurlShareError) Error() string { 21 | // ret is const char*, no need to free 22 | ret := C.curl_share_strerror(C.CURLSHcode(e)) 23 | return C.GoString(ret) 24 | } 25 | 26 | func newCurlShareError(errno C.CURLSHcode) error { 27 | if errno == 0 { // if nothing wrong 28 | return nil 29 | } 30 | return CurlShareError(errno) 31 | } 32 | 33 | type CURLSH struct { 34 | handle unsafe.Pointer 35 | } 36 | 37 | func ShareInit() *CURLSH { 38 | p := C.curl_share_init() 39 | return &CURLSH{p} 40 | } 41 | 42 | func (shcurl *CURLSH) Cleanup() error { 43 | p := shcurl.handle 44 | return newCurlShareError(C.curl_share_cleanup(p)) 45 | } 46 | 47 | func (shcurl *CURLSH) Setopt(opt int, param interface{}) error { 48 | p := shcurl.handle 49 | if param == nil { 50 | return newCurlShareError(C.curl_share_setopt_pointer(p, C.CURLSHoption(opt), nil)) 51 | } 52 | switch opt { 53 | // case SHOPT_LOCKFUNC, SHOPT_UNLOCKFUNC, SHOPT_USERDATA: 54 | // panic("not supported") 55 | case SHOPT_SHARE, SHOPT_UNSHARE: 56 | if val, ok := param.(int); ok { 57 | return newCurlShareError(C.curl_share_setopt_long(p, C.CURLSHoption(opt), C.long(val))) 58 | } 59 | } 60 | panic("not supported CURLSH.Setopt opt or param") 61 | return nil 62 | } 63 | -------------------------------------------------------------------------------- /callback.go: -------------------------------------------------------------------------------- 1 | package curl 2 | 3 | /* 4 | #cgo freebsd CFLAGS: -I/usr/local/include 5 | #cgo freebsd LDFLAGS: -L/usr/local/lib -lcurl 6 | #include 7 | #include 8 | #include 9 | 10 | */ 11 | import "C" 12 | 13 | import ( 14 | "unsafe" 15 | ) 16 | 17 | //export goCallHeaderFunction 18 | func goCallHeaderFunction(ptr *C.char, size C.size_t, ctx unsafe.Pointer) uintptr { 19 | curl := context_map.Get(uintptr(ctx)) 20 | buf := C.GoBytes(unsafe.Pointer(ptr), C.int(size)) 21 | if (*curl.headerFunction)(buf, curl.headerData) { 22 | return uintptr(size) 23 | } 24 | return C.CURL_WRITEFUNC_PAUSE 25 | } 26 | 27 | //export goCallWriteFunction 28 | func goCallWriteFunction(ptr *C.char, size C.size_t, ctx unsafe.Pointer) uintptr { 29 | curl := context_map.Get(uintptr(ctx)) 30 | buf := C.GoBytes(unsafe.Pointer(ptr), C.int(size)) 31 | if (*curl.writeFunction)(buf, curl.writeData) { 32 | return uintptr(size) 33 | } 34 | return C.CURL_WRITEFUNC_PAUSE 35 | } 36 | 37 | //export goCallProgressFunction 38 | func goCallProgressFunction(dltotal, dlnow, ultotal, ulnow C.double, ctx unsafe.Pointer) int { 39 | curl := context_map.Get(uintptr(ctx)) 40 | if (*curl.progressFunction)(float64(dltotal), float64(dlnow), 41 | float64(ultotal), float64(ulnow), 42 | curl.progressData) { 43 | return 0 44 | } 45 | return 1 46 | } 47 | 48 | //export goCallReadFunction 49 | func goCallReadFunction(ptr *C.char, size C.size_t, ctx unsafe.Pointer) uintptr { 50 | curl := context_map.Get(uintptr(ctx)) 51 | buf := C.GoBytes(unsafe.Pointer(ptr), C.int(size)) 52 | ret := (*curl.readFunction)(buf, curl.readData) 53 | str := C.CString(string(buf)) 54 | defer C.free(unsafe.Pointer(str)) 55 | if C.memcpy(unsafe.Pointer(ptr), unsafe.Pointer(str), C.size_t(ret)) == nil { 56 | panic("read_callback memcpy error!") 57 | } 58 | return uintptr(ret) 59 | } 60 | -------------------------------------------------------------------------------- /easy_test.go: -------------------------------------------------------------------------------- 1 | package curl 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "net/http/httptest" 7 | "testing" 8 | "sync" 9 | ) 10 | 11 | func setupTestServer(serverContent string) *httptest.Server { 12 | return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 13 | fmt.Fprintln(w, serverContent) 14 | })) 15 | } 16 | 17 | func TestEasyInterface(t *testing.T) { 18 | ts := setupTestServer("") 19 | defer ts.Close() 20 | 21 | easy := EasyInit() 22 | defer easy.Cleanup() 23 | 24 | easy.Setopt(OPT_URL, ts.URL) 25 | if err := easy.Perform(); err != nil { 26 | t.Fatal(err) 27 | } 28 | } 29 | 30 | func TestCallbackFunction(t *testing.T) { 31 | serverContent := "A random string" 32 | ts := setupTestServer(serverContent) 33 | defer ts.Close() 34 | 35 | easy := EasyInit() 36 | defer easy.Cleanup() 37 | 38 | easy.Setopt(OPT_URL, ts.URL) 39 | easy.Setopt(OPT_WRITEFUNCTION, func(buf []byte, userdata interface{}) bool { 40 | result := string(buf) 41 | expected := serverContent + "\n" 42 | if result != expected { 43 | t.Errorf("output should be %q and is %q.", expected, result) 44 | } 45 | return true 46 | }) 47 | if err := easy.Perform(); err != nil { 48 | t.Fatal(err) 49 | } 50 | } 51 | 52 | func TestEscape(t *testing.T) { 53 | easy := EasyInit() 54 | defer easy.Cleanup() 55 | 56 | payload := `payload={"msg": "First line\nSecond Line"}` 57 | expected := `payload%3D%7B%22msg%22%3A%20%22First%20line%5CnSecond%20Line%22%7D` 58 | result := easy.Escape(payload) 59 | if result != expected { 60 | t.Errorf("escaped output should be %q and is %q.", expected, result) 61 | } 62 | } 63 | 64 | func TestConcurrentInitAndCleanup(t *testing.T) { 65 | c := 2 66 | var wg sync.WaitGroup 67 | wg.Add(c) 68 | for i := 0; i < c; i++ { 69 | go func() { 70 | wg.Done() 71 | easy := EasyInit() 72 | defer easy.Cleanup() 73 | }() 74 | } 75 | 76 | wg.Wait() 77 | } 78 | -------------------------------------------------------------------------------- /logging_test.go: -------------------------------------------------------------------------------- 1 | 2 | package curl 3 | 4 | import ( 5 | "testing" 6 | "bytes" 7 | "log" 8 | "os" 9 | "fmt" 10 | "regexp" 11 | ) 12 | 13 | func TestDefaultLogLevel(t *testing.T) { 14 | if log_level != _DEFAULT_LOG_LEVEL {t.Error("Test failed, expected DEFAULT_LOG_LEVEL level.")} 15 | } 16 | 17 | func TestSetLogLevel(t *testing.T) { 18 | SetLogLevel("DEBUG") 19 | defer SetLogLevel("DEFAULT_LOG_LEVEL") 20 | if log_level != _DEBUG {t.Error("Test failed, expected DEBUG level.")} 21 | SetLogLevel("INFO") 22 | if log_level != _INFO {t.Error("Test failed, expected INFO level.")} 23 | SetLogLevel("WARN") 24 | if log_level != _WARN {t.Error("Test failed, expected WARN level.")} 25 | SetLogLevel("ERROR") 26 | if log_level != _ERROR {t.Error("Test failed, expected ERROR level.")} 27 | } 28 | 29 | var ( 30 | testFormat = "test format %s" 31 | testArgument = "test string 1" 32 | expectedRegexp = regexp.MustCompile(".*" + fmt.Sprintf(testFormat, testArgument) + "\n$") 33 | ) 34 | 35 | 36 | func TestLogf(t *testing.T) { 37 | buf := new(bytes.Buffer) 38 | log.SetOutput(buf) 39 | defer log.SetOutput(os.Stderr) 40 | SetLogLevel("DEBUG") 41 | defer SetLogLevel("DEFAULT_LOG_LEVEL") 42 | 43 | logf(_DEBUG, testFormat, testArgument) 44 | line := buf.String() 45 | matched := expectedRegexp.MatchString(line) 46 | if !matched { 47 | t.Errorf("log output should match %q and is %q.", expectedRegexp, line) 48 | } 49 | } 50 | 51 | func TestLogfUsesLogLevel(t *testing.T) { 52 | buf := new(bytes.Buffer) 53 | log.SetOutput(buf) 54 | defer log.SetOutput(os.Stderr) 55 | SetLogLevel("WARN") 56 | defer SetLogLevel("DEFAULT_LOG_LEVEL") 57 | 58 | logf(_DEBUG, testFormat, testArgument) 59 | line := buf.String() 60 | expectedLine := "" 61 | if line != expectedLine { 62 | t.Errorf("log output should match %q and is %q.", expectedLine, line) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /examples/renren_upload.go: -------------------------------------------------------------------------------- 1 | // 人人网图片上传 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | curl "github.com/andelf/go-curl" 7 | "regexp" 8 | "time" 9 | ) 10 | 11 | func getUploadUrl() string { 12 | page := "" 13 | easy := curl.EasyInit() 14 | defer easy.Cleanup() 15 | 16 | u := "http://3g.renren.com/album/wuploadphoto.do" 17 | easy.Setopt(curl.OPT_URL, u) 18 | easy.Setopt(curl.OPT_COOKIEFILE, "./cookie.jar") 19 | easy.Setopt(curl.OPT_COOKIEJAR, "./cookie.jar") 20 | easy.Setopt(curl.OPT_VERBOSE, true) 21 | easy.Setopt(curl.OPT_WRITEFUNCTION, func(ptr []byte, _ interface{}) bool { 22 | page += string(ptr) 23 | return true 24 | }) 25 | easy.Perform() 26 | // extract url from 27 | //
5 | #include 6 | static inline void go_FD_ZERO(void *set) { 7 | FD_ZERO((fd_set*)set); 8 | } 9 | static inline void go_FD_SET(int sysfd, void *set) { 10 | FD_SET(sysfd, (fd_set*)set); 11 | } 12 | static inline int go_FD_ISSET(int sysfd, void *set) { 13 | return FD_ISSET(sysfd, (fd_set*)set); 14 | } 15 | */ 16 | import "C" 17 | 18 | import ( 19 | curl "github.com/andelf/go-curl" 20 | "syscall" 21 | "unsafe" 22 | "fmt" 23 | ) 24 | 25 | func FD_ZERO(set *syscall.FdSet) { 26 | s := unsafe.Pointer(set) 27 | C.go_FD_ZERO(s) 28 | } 29 | 30 | func FD_SET(sysfd int, set *syscall.FdSet) { 31 | s := unsafe.Pointer(set) 32 | fd := C.int(sysfd) 33 | C.go_FD_SET(fd, s) 34 | } 35 | 36 | func FD_ISSET(sysfd int, set *syscall.FdSet) bool { 37 | s := unsafe.Pointer(set) 38 | fd := C.int(sysfd) 39 | return C.go_FD_ISSET(fd, s) != 0 40 | } 41 | 42 | func main() { 43 | var ( 44 | rset, wset, eset syscall.FdSet 45 | still_running, curl_timeout int = 0, 0 46 | err error 47 | ) 48 | 49 | ch1 := curl.EasyInit() 50 | ch2 := curl.EasyInit() 51 | 52 | ch1.Setopt(curl.OPT_URL, "http://www.163.com") 53 | ch1.Setopt(curl.OPT_HEADER, 0) 54 | ch1.Setopt(curl.OPT_VERBOSE, true) 55 | ch2.Setopt(curl.OPT_URL, "http://www.baidu.com") 56 | ch2.Setopt(curl.OPT_HEADER, 0) 57 | ch2.Setopt(curl.OPT_VERBOSE, true) 58 | 59 | mh := curl.MultiInit() 60 | 61 | mh.AddHandle(ch1) 62 | mh.AddHandle(ch2) 63 | 64 | for { 65 | FD_ZERO(&rset) 66 | FD_ZERO(&wset) 67 | FD_ZERO(&eset) 68 | 69 | timeout := syscall.Timeval{Sec:1, Usec:0} 70 | curl_timeout, err = mh.Timeout() 71 | if err != nil { 72 | fmt.Printf("Error multi_timeout: %s\n", err) 73 | } 74 | if curl_timeout >= 0 { 75 | timeout.Sec = int64(curl_timeout / 1000) 76 | if timeout.Sec > 1 { 77 | timeout.Sec = 1 78 | } else { 79 | timeout.Usec = int32((curl_timeout % 1000)) * 1000 80 | } 81 | } 82 | 83 | max_fd, err := mh.Fdset(&rset, &wset, &eset) 84 | if err != nil { 85 | fmt.Printf("Error FDSET: %s\n", err) 86 | } 87 | 88 | err = syscall.Select(int(max_fd + 1), &rset, &wset, &eset, &timeout) 89 | if err != nil { 90 | fmt.Printf("Error select: %s\n", err) 91 | } else { 92 | still_running, err = mh.Perform() 93 | if still_running > 0 { 94 | fmt.Printf("Still running: %d\n", still_running) 95 | } else { 96 | break 97 | } 98 | } 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /core.go: -------------------------------------------------------------------------------- 1 | // libcurl go bingding 2 | package curl 3 | 4 | /* 5 | #cgo linux pkg-config: libcurl 6 | #cgo darwin LDFLAGS: -lcurl 7 | #cgo windows LDFLAGS: -lcurl 8 | #include 9 | #include 10 | 11 | static char *string_array_index(char **p, int i) { 12 | return p[i]; 13 | } 14 | */ 15 | import "C" 16 | 17 | import ( 18 | "time" 19 | "unsafe" 20 | ) 21 | 22 | // curl_global_init - Global libcurl initialisation 23 | func GlobalInit(flags int) error { 24 | return newCurlError(C.curl_global_init(C.long(flags))) 25 | } 26 | 27 | // curl_global_cleanup - global libcurl cleanup 28 | func GlobalCleanup() { 29 | C.curl_global_cleanup() 30 | } 31 | 32 | type VersionInfoData struct { 33 | Age C.CURLversion 34 | // age >= 0 35 | Version string 36 | VersionNum uint 37 | Host string 38 | Features int 39 | SslVersion string 40 | SslVersionNum int 41 | LibzVersion string 42 | Protocols []string 43 | // age >= 1 44 | Ares string 45 | AresNum int 46 | // age >= 2 47 | Libidn string 48 | // age >= 3 49 | IconvVerNum int 50 | LibsshVersion string 51 | } 52 | 53 | // curl_version - returns the libcurl version string 54 | func Version() string { 55 | return C.GoString(C.curl_version()) 56 | } 57 | 58 | // curl_version_info - returns run-time libcurl version info 59 | func VersionInfo(ver C.CURLversion) *VersionInfoData { 60 | data := C.curl_version_info(ver) 61 | ret := new(VersionInfoData) 62 | ret.Age = data.age 63 | switch age := ret.Age; { 64 | case age >= 0: 65 | ret.Version = string(C.GoString(data.version)) 66 | ret.VersionNum = uint(data.version_num) 67 | ret.Host = C.GoString(data.host) 68 | ret.Features = int(data.features) 69 | ret.SslVersion = C.GoString(data.ssl_version) 70 | ret.SslVersionNum = int(data.ssl_version_num) 71 | ret.LibzVersion = C.GoString(data.libz_version) 72 | // ugly but works 73 | ret.Protocols = []string{} 74 | for i := C.int(0); C.string_array_index(data.protocols, i) != nil; i++ { 75 | p := C.string_array_index(data.protocols, i) 76 | ret.Protocols = append(ret.Protocols, C.GoString(p)) 77 | } 78 | fallthrough 79 | case age >= 1: 80 | ret.Ares = C.GoString(data.ares) 81 | ret.AresNum = int(data.ares_num) 82 | fallthrough 83 | case age >= 2: 84 | ret.Libidn = C.GoString(data.libidn) 85 | fallthrough 86 | case age >= 3: 87 | ret.IconvVerNum = int(data.iconv_ver_num) 88 | ret.LibsshVersion = C.GoString(data.libssh_version) 89 | } 90 | return ret 91 | } 92 | 93 | // curl_getdate - Convert a date string to number of seconds since January 1, 1970 94 | // In golang, we convert it to a *time.Time 95 | func Getdate(date string) *time.Time { 96 | datestr := C.CString(date) 97 | defer C.free(unsafe.Pointer(datestr)) 98 | t := C.curl_getdate(datestr, nil) 99 | if t == -1 { 100 | return nil 101 | } 102 | unix := time.Unix(int64(t), 0).UTC() 103 | return &unix 104 | 105 | /* 106 | // curl_getenv - return value for environment name 107 | func Getenv(name string) string { 108 | namestr := C.CString(name) 109 | defer C.free(unsafe.Pointer(namestr)) 110 | ret := C.curl_getenv(unsafe.Pointer(namestr)) 111 | defer C.free(unsafe.Pointer(ret)) 112 | 113 | return C.GoString(ret) 114 | } 115 | */ 116 | } 117 | 118 | // TODO: curl_global_init_mem 119 | -------------------------------------------------------------------------------- /examples/misc.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "reflect" 7 | 8 | curl "github.com/andelf/go-curl" 9 | ) 10 | 11 | const endl = "\n" 12 | 13 | func main() { 14 | println("DEBUG chdir=>", os.Chdir("/sadf")) 15 | ret := curl.EasyInit() 16 | defer ret.Cleanup() 17 | print("init =>", ret, " ", reflect.TypeOf(ret).String(), endl) 18 | ret = ret.Duphandle() 19 | defer ret.Cleanup() 20 | 21 | print("dup =>", ret, " ", reflect.TypeOf(ret).String(), endl) 22 | print("global init =>", curl.GlobalInit(curl.GLOBAL_ALL), endl) 23 | print("version =>", curl.Version(), endl) 24 | // debug 25 | //print("set verbose =>", ret.Setopt(curl.OPT_VERBOSE, true), endl) 26 | 27 | //print("set header =>", ret.Setopt(curl.OPT_HEADER, true), endl) 28 | 29 | // auto calculate port 30 | // print("set port =>", ret.EasySetopt(curl.OPT_PORT, 6060), endl) 31 | fmt.Printf("XXXX debug setopt %#v \n", ret.Setopt(30000, 19).Error()) 32 | 33 | print("set timeout =>", ret.Setopt(curl.OPT_TIMEOUT, 20), endl) 34 | 35 | //print("set post size =>", ret.Setopt(curl.OPT_POSTFIELDSIZE, 10), endl) 36 | if ret.Setopt(curl.OPT_URL, "http://www.baidu.com:8000/") != nil { 37 | println("set url ok!") 38 | } 39 | //print("set url =>", ret.Setopt(curl.OPT_URL, "http://commondatastorage.googleapis.com/chromium-browser-continuous/Linux_x64/104547/chrome-linux.zip"), endl) 40 | 41 | print("set user_agent =>", ret.Setopt(curl.OPT_USERAGENT, "github.com/andelf/go-curl v0.0.1") == nil, endl) 42 | // add to DNS cache 43 | print("set resolve =>", ret.Setopt(curl.OPT_RESOLVE, []string{"www.baidu.com:8000:127.0.0.1"}) == nil, endl) 44 | // ret.EasyReset() clean seted 45 | 46 | // currently not finished! 47 | // 48 | fooTest := func(buf []byte, userdata interface{}) bool { 49 | // buf := ptr.([]byte) 50 | println("size=>", len(buf)) 51 | println("DEBUG(in callback)", buf, userdata) 52 | println("data = >", string(buf)) 53 | return true 54 | } 55 | 56 | ret.Setopt(curl.OPT_WRITEFUNCTION, fooTest) // curl.CallbackWriteFunction(fooTest)) 57 | println("set opt!") 58 | // for test only 59 | 60 | code := ret.Perform() 61 | // dump.Dump(code) 62 | fmt.Printf("code -> %v\n", code) 63 | 64 | println("================================") 65 | print("pause =>", ret.Pause(curl.PAUSE_ALL), endl) 66 | 67 | print("escape =>", ret.Escape("http://baidu.com/"), endl) 68 | print("unescape =>", ret.Unescape("http://baidu.com/-%00-%5c"), endl) 69 | 70 | print("unescape lenght =>", len(ret.Unescape("http://baidu.com/-%00-%5c")), endl) 71 | // print("version info data =>", curl.VersionInfo(1), endl) 72 | ver := curl.VersionInfo(curl.VERSION_NOW) 73 | fmt.Printf("VersionInfo: Age: %d, Version:%s, Host:%s, Features:%d, SslVer: %s, LibzV: %s, ssh: %s\n", 74 | ver.Age, ver.Version, ver.Host, ver.Features, ver.SslVersion, ver.LibzVersion, ver.LibsshVersion) 75 | 76 | print("Protocols:") 77 | for _, p := range ver.Protocols { 78 | print(p, ", ") 79 | } 80 | print(endl) 81 | println(curl.Getdate("20111002 15:05:58 +0800").String()) 82 | ret.Getinfo(curl.INFO_EFFECTIVE_URL) 83 | ret.Getinfo(curl.INFO_RESPONSE_CODE) 84 | 85 | ret.Getinfo(curl.INFO_FILETIME) 86 | ret.Getinfo(curl.INFO_SSL_ENGINES) 87 | 88 | ret.Getinfo(curl.INFO_TOTAL_TIME) 89 | 90 | println("================================") 91 | 92 | // ret.Getinfo(curl.INFO_SSL_ENGINES) 93 | 94 | /* mret := curl.MultiInit() 95 | mret.AddHandle(ret) // works 96 | defer mret.Cleanup() 97 | if ok, handles := mret.Perform(); ok == curl.OK { 98 | fmt.Printf("ok=%s, handles=%d\n", ok, handles) 99 | } else { 100 | fmt.Printf("error calling multi\n") 101 | } 102 | */ 103 | println("================================") 104 | //println(curl.GlobalInit(curl.GLOBAL_SSL)) 105 | } 106 | -------------------------------------------------------------------------------- /misc/codegen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ codegen.py reads curl project's curl.h, outputting go-curl's const_gen.go 5 | 6 | codegen.py should be run from the go-curl source root, where it will 7 | attempt to locate 'curl.h' in the locations defined by `target_dirs`. 8 | 9 | 10 | CURL_GIT_PATH (if defined) must point to the location of your curl source 11 | repository. For example you might check out curl from 12 | https://github.com/curl/curl and have that saved to your local 13 | directory `/Users/example-home/git/curl` 14 | 15 | Usage: 16 | 17 | CURL_GIT_PATH=/path-to-git-repos/curl ./misc/codegen.py 18 | 19 | Example: 20 | CURL_GIT_PATH=/Users/example-user/Projects/c/curl python3 ./misc/codegen.py 21 | 22 | File Input: 23 | (curl project) include/curl/header.h 24 | 25 | File Output: 26 | const_gen.go 27 | 28 | Todo: 29 | * Further code review ("help wanted") 30 | * More docstrings/help. Error checking. Cleanup redefined variable scopes. 31 | """ 32 | 33 | import os 34 | import re 35 | 36 | # CURL_GIT_PATH is the location you git checked out the curl project. 37 | # You will need to supply this variable and value when invoking this script. 38 | CURL_GIT_PATH = os.environ.get("CURL_GIT_PATH", './curl') 39 | 40 | target_dirs = [ 41 | '{}/include/curl'.format(CURL_GIT_PATH), 42 | '/usr/local/include', 43 | 'libdir/gcc/target/version/include' 44 | '/usr/target/include', 45 | '/usr/include', 46 | ] 47 | 48 | def get_curl_path() -> str: 49 | for d in target_dirs: 50 | for root, dirs, files in os.walk(d): 51 | if 'curl.h' in files: 52 | return os.path.join(root, 'curl.h') 53 | raise Exception("Not found") 54 | 55 | 56 | opts = [] 57 | codes = [] 58 | infos = [] 59 | auths = [] 60 | init_pattern = re.compile(r'CINIT\((.*?),\s+(LONG|OBJECTPOINT|FUNCTIONPOINT|STRINGPOINT|OFF_T),\s+(\d+)\)') 61 | error_pattern = re.compile('^\s+(CURLE_[A-Z_0-9]+),') 62 | info_pattern = re.compile('^\s+(CURLINFO_[A-Z_0-9]+)\s+=') 63 | 64 | with open(get_curl_path()) as f: 65 | for line in f: 66 | match = init_pattern.findall(line) 67 | if match: 68 | opts.append(match[0][0]) 69 | if line.startswith('#define CURLOPT_'): 70 | o = line.split() 71 | opts.append(o[1][8:]) # strip :( 72 | 73 | if line.startswith('#define CURLAUTH_'): 74 | o = line.split() 75 | auths.append(o[1][9:]) 76 | 77 | match = error_pattern.findall(line) 78 | if match: 79 | codes.append(match[0]) 80 | 81 | if line.startswith('#define CURLE_'): 82 | c = line.split() 83 | codes.append(c[1]) 84 | 85 | match = info_pattern.findall(line) 86 | if match: 87 | infos.append(match[0]) 88 | 89 | if line.startswith('#define CURLINFO_'): 90 | i = line.split() 91 | if '0x' not in i[2]: # :( 92 | infos.append(i[1]) 93 | 94 | template = """//go:generate /usr/bin/env python ./misc/codegen.py 95 | 96 | package curl 97 | /* 98 | #include 99 | #include "compat.h" 100 | */ 101 | import "C" 102 | 103 | // CURLcode 104 | const ( 105 | {code_part} 106 | ) 107 | 108 | // easy.Setopt(flag, ...) 109 | const ( 110 | {opt_part} 111 | ) 112 | 113 | // easy.Getinfo(flag) 114 | const ( 115 | {info_part} 116 | ) 117 | 118 | // Auth 119 | const ( 120 | {auth_part} 121 | ) 122 | 123 | // generated ends 124 | """ 125 | 126 | code_part = [] 127 | for c in codes: 128 | code_part.append("\t{:<25} = C.{}".format(c[4:], c)) 129 | 130 | code_part = '\n'.join(code_part) 131 | 132 | opt_part = [] 133 | for o in opts: 134 | opt_part.append("\tOPT_{0:<25} = C.CURLOPT_{0}".format(o)) 135 | 136 | opt_part = '\n'.join(opt_part) 137 | 138 | info_part = [] 139 | for i in infos: 140 | info_part.append("\t{:<25} = C.{}".format(i[4:], i)) 141 | 142 | info_part = '\n'.join(info_part) 143 | 144 | auth_part = [] 145 | for a in auths: 146 | auth_part.append("\tAUTH_{0:<25} = C.CURLAUTH_{0} & (1<<32 - 1)".format(a)) 147 | 148 | auth_part = '\n'.join(auth_part) 149 | 150 | with open('./const_gen.go', 'w', encoding="utf-8") as fp: 151 | fp.write(template.format(**locals())) 152 | -------------------------------------------------------------------------------- /multi.go: -------------------------------------------------------------------------------- 1 | // This file depends on functionality not available on Windows, hence we 2 | // must skip it. https://github.com/andelf/go-curl/issues/48 3 | 4 | // +build !windows 5 | 6 | package curl 7 | 8 | /* 9 | #include 10 | #include 11 | 12 | static CURLMcode curl_multi_setopt_long(CURLM *handle, CURLMoption option, long parameter) { 13 | return curl_multi_setopt(handle, option, parameter); 14 | } 15 | static CURLMcode curl_multi_setopt_pointer(CURLM *handle, CURLMoption option, void *parameter) { 16 | return curl_multi_setopt(handle, option, parameter); 17 | } 18 | static CURLMcode curl_multi_fdset_pointer(CURLM *handle, 19 | void *read_fd_set, 20 | void *write_fd_set, 21 | void *exc_fd_set, 22 | int *max_fd) 23 | { 24 | return curl_multi_fdset(handle, read_fd_set, write_fd_set, exc_fd_set, max_fd); 25 | } 26 | static CURLMsg *curl_multi_info_read_pointer(CURLM *handle, int *msgs_in_queue) 27 | { 28 | return curl_multi_info_read(handle, msgs_in_queue); 29 | } 30 | */ 31 | import "C" 32 | 33 | import ( 34 | "unsafe" 35 | "syscall" 36 | ) 37 | 38 | type CurlMultiError C.CURLMcode 39 | type CurlMultiMsg C.CURLMSG 40 | 41 | func (e CurlMultiError) Error() string { 42 | // ret is const char*, no need to free 43 | ret := C.curl_multi_strerror(C.CURLMcode(e)) 44 | return C.GoString(ret) 45 | } 46 | 47 | func newCurlMultiError(errno C.CURLMcode) error { 48 | // cannot use C.CURLM_OK here, cause multi.h use a undefined emum num 49 | if errno == 0 { // if nothing wrong 50 | return nil 51 | } 52 | return CurlMultiError(errno) 53 | } 54 | 55 | func newCURLMessage(message *C.CURLMsg) (msg *CURLMessage){ 56 | if message == nil { 57 | return nil 58 | } 59 | msg = new(CURLMessage) 60 | msg.Msg = CurlMultiMsg(message.msg) 61 | msg.Easy_handle = &CURL{handle: message.easy_handle} 62 | msg.Data = message.data 63 | return msg 64 | } 65 | 66 | type CURLM struct { 67 | handle unsafe.Pointer 68 | } 69 | 70 | var dummy unsafe.Pointer 71 | type CURLMessage struct { 72 | Msg CurlMultiMsg 73 | Easy_handle *CURL 74 | Data [unsafe.Sizeof(dummy)]byte 75 | } 76 | 77 | // curl_multi_init - create a multi handle 78 | func MultiInit() *CURLM { 79 | p := C.curl_multi_init() 80 | return &CURLM{p} 81 | } 82 | 83 | // curl_multi_cleanup - close down a multi session 84 | func (mcurl *CURLM) Cleanup() error { 85 | p := mcurl.handle 86 | return newCurlMultiError(C.curl_multi_cleanup(p)) 87 | } 88 | 89 | // curl_multi_perform - reads/writes available data from each easy handle 90 | func (mcurl *CURLM) Perform() (int, error) { 91 | p := mcurl.handle 92 | running_handles := C.int(-1) 93 | err := newCurlMultiError(C.curl_multi_perform(p, &running_handles)) 94 | return int(running_handles), err 95 | } 96 | 97 | // curl_multi_add_handle - add an easy handle to a multi session 98 | func (mcurl *CURLM) AddHandle(easy *CURL) error { 99 | mp := mcurl.handle 100 | easy_handle := easy.handle 101 | return newCurlMultiError(C.curl_multi_add_handle(mp, easy_handle)) 102 | } 103 | 104 | // curl_multi_remove_handle - remove an easy handle from a multi session 105 | func (mcurl *CURLM) RemoveHandle(easy *CURL) error { 106 | mp := mcurl.handle 107 | easy_handle := easy.handle 108 | return newCurlMultiError(C.curl_multi_remove_handle(mp, easy_handle)) 109 | } 110 | 111 | func (mcurl *CURLM) Timeout() (int, error) { 112 | p := mcurl.handle 113 | timeout := C.long(-1) 114 | err := newCurlMultiError(C.curl_multi_timeout(p, &timeout)) 115 | return int(timeout), err 116 | } 117 | 118 | func (mcurl *CURLM) Setopt(opt int, param interface{}) error { 119 | p := mcurl.handle 120 | if param == nil { 121 | return newCurlMultiError(C.curl_multi_setopt_pointer(p, C.CURLMoption(opt), nil)) 122 | } 123 | switch { 124 | // currently cannot support these option 125 | // case MOPT_SOCKETFUNCTION, MOPT_SOCKETDATA, MOPT_TIMERFUNCTION, MOPT_TIMERDATA: 126 | // panic("not supported CURLM.Setopt opt") 127 | case opt >= C.CURLOPTTYPE_LONG: 128 | val := C.long(0) 129 | switch t := param.(type) { 130 | case int: 131 | val := C.long(t) 132 | return newCurlMultiError(C.curl_multi_setopt_long(p, C.CURLMoption(opt), val)) 133 | case bool: 134 | val = C.long(0) 135 | if t { 136 | val = C.long(1) 137 | } 138 | return newCurlMultiError(C.curl_multi_setopt_long(p, C.CURLMoption(opt), val)) 139 | } 140 | } 141 | panic("not supported CURLM.Setopt opt or param") 142 | return nil 143 | } 144 | 145 | func (mcurl *CURLM) Fdset(rset, wset, eset *syscall.FdSet) (int, error) { 146 | p := mcurl.handle 147 | read := unsafe.Pointer(rset) 148 | write := unsafe.Pointer(wset) 149 | exc := unsafe.Pointer(eset) 150 | maxfd := C.int(-1) 151 | err := newCurlMultiError(C.curl_multi_fdset_pointer(p, read, write, 152 | exc, &maxfd)) 153 | return int(maxfd), err 154 | } 155 | 156 | func (mcurl *CURLM) Info_read() (*CURLMessage, int) { 157 | p := mcurl.handle 158 | left := C.int(0) 159 | return newCURLMessage(C.curl_multi_info_read_pointer(p, &left)), int(left) 160 | } 161 | -------------------------------------------------------------------------------- /const.go: -------------------------------------------------------------------------------- 1 | package curl 2 | 3 | /* 4 | #include 5 | #include "compat.h" 6 | 7 | */ 8 | import "C" 9 | 10 | // for GlobalInit(flag) 11 | const ( 12 | GLOBAL_SSL = C.CURL_GLOBAL_SSL 13 | GLOBAL_WIN32 = C.CURL_GLOBAL_WIN32 14 | GLOBAL_ALL = C.CURL_GLOBAL_ALL 15 | GLOBAL_NOTHING = C.CURL_GLOBAL_NOTHING 16 | GLOBAL_DEFAULT = C.CURL_GLOBAL_DEFAULT 17 | ) 18 | 19 | // CURLMcode 20 | const ( 21 | M_CALL_MULTI_PERFORM = C.CURLM_CALL_MULTI_PERFORM 22 | // M_OK = C.CURLM_OK 23 | M_BAD_HANDLE = C.CURLM_BAD_HANDLE 24 | M_BAD_EASY_HANDLE = C.CURLM_BAD_EASY_HANDLE 25 | M_OUT_OF_MEMORY = C.CURLM_OUT_OF_MEMORY 26 | M_INTERNAL_ERROR = C.CURLM_INTERNAL_ERROR 27 | M_BAD_SOCKET = C.CURLM_BAD_SOCKET 28 | M_UNKNOWN_OPTION = C.CURLM_UNKNOWN_OPTION 29 | ) 30 | 31 | // for multi.Setopt(flag, ...) 32 | const ( 33 | MOPT_SOCKETFUNCTION = C.CURLMOPT_SOCKETFUNCTION 34 | MOPT_SOCKETDATA = C.CURLMOPT_SOCKETDATA 35 | MOPT_PIPELINING = C.CURLMOPT_PIPELINING 36 | MOPT_TIMERFUNCTION = C.CURLMOPT_TIMERFUNCTION 37 | MOPT_TIMERDATA = C.CURLMOPT_TIMERDATA 38 | MOPT_MAXCONNECTS = C.CURLMOPT_MAXCONNECTS 39 | ) 40 | 41 | // CURLSHcode 42 | const ( 43 | // SHE_OK = C.CURLSHE_OK 44 | SHE_BAD_OPTION = C.CURLSHE_BAD_OPTION 45 | SHE_IN_USE = C.CURLSHE_IN_USE 46 | SHE_INVALID = C.CURLSHE_INVALID 47 | SHE_NOMEM = C.CURLSHE_NOMEM 48 | ) 49 | 50 | // for share.Setopt(flat, ...) 51 | const ( 52 | SHOPT_SHARE = C.CURLSHOPT_SHARE 53 | SHOPT_UNSHARE = C.CURLSHOPT_UNSHARE 54 | SHOPT_LOCKFUNC = C.CURLSHOPT_LOCKFUNC 55 | SHOPT_UNLOCKFUNC = C.CURLSHOPT_UNLOCKFUNC 56 | SHOPT_USERDATA = C.CURLSHOPT_USERDATA 57 | ) 58 | 59 | // for share.Setopt(SHOPT_SHARE/SHOPT_UNSHARE, flag) 60 | const ( 61 | LOCK_DATA_SHARE = C.CURL_LOCK_DATA_SHARE 62 | LOCK_DATA_COOKIE = C.CURL_LOCK_DATA_COOKIE 63 | LOCK_DATA_DNS = C.CURL_LOCK_DATA_DNS 64 | LOCK_DATA_SSL_SESSION = C.CURL_LOCK_DATA_SSL_SESSION 65 | LOCK_DATA_CONNECT = C.CURL_LOCK_DATA_CONNECT 66 | ) 67 | 68 | // for VersionInfo(flag) 69 | const ( 70 | VERSION_FIRST = C.CURLVERSION_FIRST 71 | VERSION_SECOND = C.CURLVERSION_SECOND 72 | VERSION_THIRD = C.CURLVERSION_THIRD 73 | // VERSION_FOURTH = C.CURLVERSION_FOURTH 74 | VERSION_LAST = C.CURLVERSION_LAST 75 | VERSION_NOW = C.CURLVERSION_NOW 76 | ) 77 | 78 | // for VersionInfo(...).Features mask flag 79 | const ( 80 | VERSION_IPV6 = C.CURL_VERSION_IPV6 81 | VERSION_KERBEROS4 = C.CURL_VERSION_KERBEROS4 82 | VERSION_SSL = C.CURL_VERSION_SSL 83 | VERSION_LIBZ = C.CURL_VERSION_LIBZ 84 | VERSION_NTLM = C.CURL_VERSION_NTLM 85 | VERSION_GSSNEGOTIATE = C.CURL_VERSION_GSSNEGOTIATE 86 | VERSION_DEBUG = C.CURL_VERSION_DEBUG 87 | VERSION_ASYNCHDNS = C.CURL_VERSION_ASYNCHDNS 88 | VERSION_SPNEGO = C.CURL_VERSION_SPNEGO 89 | VERSION_LARGEFILE = C.CURL_VERSION_LARGEFILE 90 | VERSION_IDN = C.CURL_VERSION_IDN 91 | VERSION_SSPI = C.CURL_VERSION_SSPI 92 | VERSION_CONV = C.CURL_VERSION_CONV 93 | VERSION_CURLDEBUG = C.CURL_VERSION_CURLDEBUG 94 | VERSION_TLSAUTH_SRP = C.CURL_VERSION_TLSAUTH_SRP 95 | VERSION_NTLM_WB = C.CURL_VERSION_NTLM_WB 96 | ) 97 | 98 | // for OPT_READFUNCTION, return a int flag 99 | const ( 100 | READFUNC_ABORT = C.CURL_READFUNC_ABORT 101 | READFUNC_PAUSE = C.CURL_READFUNC_PAUSE 102 | ) 103 | 104 | // for easy.Setopt(OPT_HTTP_VERSION, flag) 105 | const ( 106 | HTTP_VERSION_NONE = C.CURL_HTTP_VERSION_NONE 107 | HTTP_VERSION_1_0 = C.CURL_HTTP_VERSION_1_0 108 | HTTP_VERSION_1_1 = C.CURL_HTTP_VERSION_1_1 109 | ) 110 | 111 | // for easy.Setopt(OPT_PROXYTYPE, flag) 112 | const ( 113 | PROXY_HTTP = C.CURLPROXY_HTTP /* added in 7.10, new in 7.19.4 default is to use CONNECT HTTP/1.1 */ 114 | PROXY_HTTP_1_0 = C.CURLPROXY_HTTP_1_0 /* added in 7.19.4, force to use CONNECT HTTP/1.0 */ 115 | PROXY_SOCKS4 = C.CURLPROXY_SOCKS4 /* support added in 7.15.2, enum existed already in 7.10 */ 116 | PROXY_SOCKS5 = C.CURLPROXY_SOCKS5 /* added in 7.10 */ 117 | PROXY_SOCKS4A = C.CURLPROXY_SOCKS4A /* added in 7.18.0 */ 118 | // Use the SOCKS5 protocol but pass along the host name rather than the IP address. 119 | PROXY_SOCKS5_HOSTNAME = C.CURLPROXY_SOCKS5_HOSTNAME 120 | ) 121 | 122 | // for easy.Setopt(OPT_SSLVERSION, flag) 123 | const ( 124 | SSLVERSION_DEFAULT = C.CURL_SSLVERSION_DEFAULT 125 | SSLVERSION_TLSv1 = C.CURL_SSLVERSION_TLSv1 126 | SSLVERSION_SSLv2 = C.CURL_SSLVERSION_SSLv2 127 | SSLVERSION_SSLv3 = C.CURL_SSLVERSION_SSLv3 128 | ) 129 | 130 | // for easy.Setopt(OPT_TIMECONDITION, flag) 131 | const ( 132 | TIMECOND_NONE = C.CURL_TIMECOND_NONE 133 | TIMECOND_IFMODSINCE = C.CURL_TIMECOND_IFMODSINCE 134 | TIMECOND_IFUNMODSINCE = C.CURL_TIMECOND_IFUNMODSINCE 135 | TIMECOND_LASTMOD = C.CURL_TIMECOND_LASTMOD 136 | ) 137 | 138 | // for easy.Setopt(OPT_NETRC, flag) 139 | const ( 140 | NETRC_IGNORED = C.CURL_NETRC_IGNORED 141 | NETRC_OPTIONAL = C.CURL_NETRC_OPTIONAL 142 | NETRC_REQUIRED = C.CURL_NETRC_REQUIRED 143 | ) 144 | 145 | // for easy.Setopt(OPT_FTP_CREATE_MISSING_DIRS, flag) 146 | const ( 147 | FTP_CREATE_DIR_NONE = C.CURLFTP_CREATE_DIR_NONE 148 | FTP_CREATE_DIR = C.CURLFTP_CREATE_DIR 149 | FTP_CREATE_DIR_RETRY = C.CURLFTP_CREATE_DIR_RETRY 150 | ) 151 | 152 | // for easy.Setopt(OPT_IPRESOLVE, flag) 153 | const ( 154 | IPRESOLVE_WHATEVER = C.CURL_IPRESOLVE_WHATEVER 155 | IPRESOLVE_V4 = C.CURL_IPRESOLVE_V4 156 | IPRESOLVE_V6 = C.CURL_IPRESOLVE_V6 157 | ) 158 | 159 | // for easy.Setopt(OPT_SSL_OPTIONS, flag) 160 | const ( 161 | SSLOPT_ALLOW_BEAST = 1 162 | ) 163 | 164 | // for easy.Pause(flat) 165 | const ( 166 | PAUSE_RECV = C.CURLPAUSE_RECV 167 | PAUSE_RECV_CONT = C.CURLPAUSE_RECV_CONT 168 | PAUSE_SEND = C.CURLPAUSE_SEND 169 | PAUSE_SEND_CONT = C.CURLPAUSE_SEND_CONT 170 | PAUSE_ALL = C.CURLPAUSE_ALL 171 | PAUSE_CONT = C.CURLPAUSE_CONT 172 | ) 173 | 174 | // for multi.Info_read() 175 | const ( 176 | CURLMSG_NONE = C.CURLMSG_NONE 177 | CURLMSG_DONE = C.CURLMSG_DONE 178 | CURLMSG_LAST = C.CURLMSG_LAST 179 | ) 180 | -------------------------------------------------------------------------------- /misc/compatgen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | """ codegen.py reads curl project's curl.h, outputting go-curl's compat.h 6 | 7 | The purpose of compatggen.py is to generate compat.h defines which are needed 8 | by go-curl build process. Most users of co-curl can stop reading here, 9 | because a usable compat.h is already included in the go-curl source. 10 | 11 | compatgen.py should be run from the go-curl source root, where it will 12 | attempt to locate 'curl.h' in the locations defined by `target_dirs`. 13 | 14 | 15 | CURL_GIT_PATH (if defined) must point to the location of your curl source 16 | repository. For example you might check out curl from 17 | https://github.com/curl/curl and have that saved to your local 18 | directory `/Users/example-home/git/curl` 19 | 20 | Usage: 21 | 22 | CURL_GIT_PATH=/path-to-git-repos/curl python ./misc/compatgen.py 23 | 24 | Example: 25 | CURL_GIT_PATH=/Users/example-user/Projects/c/curl ./misc/compatgen.py 26 | 27 | File Input: 28 | (curl project) include/curl/header.h 29 | 30 | File Output: 31 | compat.h 32 | 33 | Todo: 34 | * Further code review ("help wanted") 35 | * More docstrings/help. Error checking. Cleanup redefined variable scopes. 36 | """ 37 | 38 | import os 39 | import re 40 | 41 | # CURL_GIT_PATH is the location you git checked out the curl project. 42 | # You will need to supply this variable and value when invoking this script. 43 | CURL_GIT_PATH = os.environ.get("CURL_GIT_PATH", "./curl") 44 | 45 | target_dirs = [ 46 | "{}/include/curl".format(CURL_GIT_PATH), 47 | "/usr/local/include", 48 | "libdir/gcc/target/version/include" "/usr/target/include", 49 | "/usr/include", 50 | ] 51 | 52 | 53 | def get_curl_path() -> str: 54 | for d in target_dirs: 55 | for root, dirs, files in os.walk(d): 56 | if "curl.h" in files: 57 | return os.path.join(root, "curl.h") 58 | raise Exception("Not found") 59 | 60 | 61 | def version_symbol(ver: str) -> tuple[list[str], list[str], list[str], list[str], list[str]]: 62 | """Returns lists of symbol info, when given argument of curl's Git tag.""" 63 | 64 | # force switch (discard changes) and checkout each of the curl branches 65 | checkout_cmd = 'cd "{}" && git status --porcelain && git -c advice.detachedHead=false checkout -f "{}"'.format( 66 | CURL_GIT_PATH, ver 67 | ) 68 | 69 | os.system(checkout_cmd) 70 | opts = [] 71 | codes = [] 72 | infos = [] 73 | vers = [] 74 | auths = [] 75 | init_pattern = re.compile(r"CINIT\((.*?),\s*(LONG|OBJECTPOINT|FUNCTIONPOINT|STRINGPOINT|OFF_T),\s*(\d+)\)") 76 | error_pattern = re.compile(r"^\s+(CURLE_[A-Z_0-9]+),") 77 | info_pattern = re.compile(r"^\s+(CURLINFO_[A-Z_0-9]+)\s+=") 78 | with open(os.path.join(CURL_GIT_PATH, "include", "curl", "curl.h")) as f: 79 | for line in f: 80 | match = init_pattern.findall(line) 81 | if match: 82 | opts.append("CURLOPT_" + match[0][0]) 83 | if line.startswith("#define CURLOPT_"): 84 | o = line.split() 85 | opts.append(o[1]) 86 | 87 | if line.startswith("#define CURLAUTH_"): 88 | a = line.split() 89 | auths.append(a[1]) 90 | 91 | match = error_pattern.findall(line) 92 | if match: 93 | codes.append(match[0]) 94 | 95 | if line.startswith("#define CURLE_"): 96 | c = line.split() 97 | codes.append(c[1]) 98 | 99 | match = info_pattern.findall(line) 100 | if match: 101 | infos.append(match[0]) 102 | 103 | if line.startswith("#define CURLINFO_"): 104 | i = line.split() 105 | if "0x" not in i[2]: # :( 106 | infos.append(i[1]) 107 | 108 | if line.startswith("#define CURL_VERSION_"): 109 | i = line.split() 110 | vers.append(i[1]) 111 | 112 | return opts, codes, infos, vers, auths 113 | 114 | 115 | def extract_version(tag_str: str) -> dict: 116 | """Converts a curl git tag (curl-8_8_0) into a dict, ex.: {'major': 8, 'minor': 8, 'patch': 0, 'version': 'curl-8_8_0'}""" 117 | fields = re.search(r"curl-([0-9]+)_([0-9]+)_([0-9]+)", tag_str) 118 | if fields is None: 119 | raise ValueError("Invalid tag: {}".format(tag_str)) 120 | version = { 121 | "major": int(fields.group(1)), 122 | "minor": int(fields.group(2)), 123 | "patch": int(fields.group(3)), 124 | "version": tag_str, 125 | } 126 | return version 127 | 128 | 129 | ## valid versions that are compatible are 7_16_XXX or higher 130 | def is_valid_version(version: dict) -> bool: 131 | """Returns false when curl version (branch) is less than 7_16_XXX.""" 132 | return version["major"] >= 8 or (version["major"] == 7 and version["minor"] >= 16) 133 | 134 | 135 | # fetches a list of tags from the curl repo, matching only format "curl-X_Y_Z" 136 | get_tags_raw_cmd = "cd {} && git tag | grep -E '^curl-[0-9]+_[0-9]+_[0-9]+$'".format(CURL_GIT_PATH) 137 | tags_raw = os.popen(get_tags_raw_cmd).read().split("\n")[:-1] 138 | tags = map(extract_version, tags_raw) 139 | tags = filter(is_valid_version, tags) 140 | versions = sorted(tags, key=lambda v: [v["major"], v["minor"], v["patch"]], reverse=True) 141 | last = version_symbol("master") 142 | 143 | template = """ 144 | /* generated by compatgen.py */ 145 | #include 146 | 147 | 148 | """ 149 | 150 | result = [template] 151 | result_tail = ["/* generated ends */\n"] 152 | 153 | 154 | if __name__ == "__main__": 155 | for ver in versions: 156 | major = ver["major"] 157 | minor = ver["minor"] 158 | patch = ver["patch"] 159 | opts, codes, infos, vers, auths = curr = version_symbol(ver["version"]) 160 | 161 | for o in last[0]: 162 | if o not in opts: 163 | result.append("#define {} 0".format(o)) # 0 for nil option 164 | for c in last[1]: 165 | if c not in codes: 166 | result.append("#define {} -1".format(c)) # -1 for error 167 | for i in last[2]: 168 | if i not in infos: 169 | result.append("#define {} 0".format(i)) # 0 for nil 170 | for v in last[3]: 171 | if v not in vers: 172 | result.append("#define {} 0".format(v)) # 0 for nil 173 | for a in last[4]: 174 | if a not in auths: 175 | result.append("#define {} 0".format(a)) # 0 for nil 176 | 177 | result.append( 178 | f"#if LIBCURL_VERSION_MAJOR < {major} || (LIBCURL_VERSION_MAJOR == {major} && LIBCURL_VERSION_MINOR < {minor}) || (LIBCURL_VERSION_MAJOR == {major} && LIBCURL_VERSION_MINOR == {minor} && LIBCURL_VERSION_PATCH < {patch})" 179 | ) 180 | 181 | result_tail.insert(0, "#endif /* {}.{}.{} */".format(major, minor, patch)) 182 | 183 | last = curr 184 | 185 | result.append("#error your version is TOOOOOOOO low") 186 | 187 | result.extend(result_tail) 188 | 189 | with open("./compat.h", "w", encoding="utf-8") as fp: 190 | fp.write("\n".join(result)) 191 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /const_gen.go: -------------------------------------------------------------------------------- 1 | //go:generate /usr/bin/env python ./misc/codegen.py 2 | 3 | package curl 4 | /* 5 | #include 6 | #include "compat.h" 7 | */ 8 | import "C" 9 | 10 | // CURLcode 11 | const ( 12 | E_UNSUPPORTED_PROTOCOL = C.CURLE_UNSUPPORTED_PROTOCOL 13 | E_FAILED_INIT = C.CURLE_FAILED_INIT 14 | E_URL_MALFORMAT = C.CURLE_URL_MALFORMAT 15 | E_URL_MALFORMAT_USER = C.CURLE_URL_MALFORMAT_USER 16 | E_COULDNT_RESOLVE_PROXY = C.CURLE_COULDNT_RESOLVE_PROXY 17 | E_COULDNT_RESOLVE_HOST = C.CURLE_COULDNT_RESOLVE_HOST 18 | E_COULDNT_CONNECT = C.CURLE_COULDNT_CONNECT 19 | E_FTP_WEIRD_SERVER_REPLY = C.CURLE_FTP_WEIRD_SERVER_REPLY 20 | E_FTP_ACCESS_DENIED = C.CURLE_FTP_ACCESS_DENIED 21 | E_FTP_USER_PASSWORD_INCORRECT = C.CURLE_FTP_USER_PASSWORD_INCORRECT 22 | E_FTP_WEIRD_PASS_REPLY = C.CURLE_FTP_WEIRD_PASS_REPLY 23 | E_FTP_WEIRD_USER_REPLY = C.CURLE_FTP_WEIRD_USER_REPLY 24 | E_FTP_WEIRD_PASV_REPLY = C.CURLE_FTP_WEIRD_PASV_REPLY 25 | E_FTP_WEIRD_227_FORMAT = C.CURLE_FTP_WEIRD_227_FORMAT 26 | E_FTP_CANT_GET_HOST = C.CURLE_FTP_CANT_GET_HOST 27 | E_FTP_CANT_RECONNECT = C.CURLE_FTP_CANT_RECONNECT 28 | E_FTP_COULDNT_SET_BINARY = C.CURLE_FTP_COULDNT_SET_BINARY 29 | E_PARTIAL_FILE = C.CURLE_PARTIAL_FILE 30 | E_FTP_COULDNT_RETR_FILE = C.CURLE_FTP_COULDNT_RETR_FILE 31 | E_FTP_WRITE_ERROR = C.CURLE_FTP_WRITE_ERROR 32 | E_FTP_QUOTE_ERROR = C.CURLE_FTP_QUOTE_ERROR 33 | E_HTTP_RETURNED_ERROR = C.CURLE_HTTP_RETURNED_ERROR 34 | E_WRITE_ERROR = C.CURLE_WRITE_ERROR 35 | E_MALFORMAT_USER = C.CURLE_MALFORMAT_USER 36 | E_FTP_COULDNT_STOR_FILE = C.CURLE_FTP_COULDNT_STOR_FILE 37 | E_READ_ERROR = C.CURLE_READ_ERROR 38 | E_OUT_OF_MEMORY = C.CURLE_OUT_OF_MEMORY 39 | E_OPERATION_TIMEOUTED = C.CURLE_OPERATION_TIMEOUTED 40 | E_FTP_COULDNT_SET_ASCII = C.CURLE_FTP_COULDNT_SET_ASCII 41 | E_FTP_PORT_FAILED = C.CURLE_FTP_PORT_FAILED 42 | E_FTP_COULDNT_USE_REST = C.CURLE_FTP_COULDNT_USE_REST 43 | E_FTP_COULDNT_GET_SIZE = C.CURLE_FTP_COULDNT_GET_SIZE 44 | E_HTTP_RANGE_ERROR = C.CURLE_HTTP_RANGE_ERROR 45 | E_HTTP_POST_ERROR = C.CURLE_HTTP_POST_ERROR 46 | E_SSL_CONNECT_ERROR = C.CURLE_SSL_CONNECT_ERROR 47 | E_BAD_DOWNLOAD_RESUME = C.CURLE_BAD_DOWNLOAD_RESUME 48 | E_FILE_COULDNT_READ_FILE = C.CURLE_FILE_COULDNT_READ_FILE 49 | E_LDAP_CANNOT_BIND = C.CURLE_LDAP_CANNOT_BIND 50 | E_LDAP_SEARCH_FAILED = C.CURLE_LDAP_SEARCH_FAILED 51 | E_LIBRARY_NOT_FOUND = C.CURLE_LIBRARY_NOT_FOUND 52 | E_FUNCTION_NOT_FOUND = C.CURLE_FUNCTION_NOT_FOUND 53 | E_ABORTED_BY_CALLBACK = C.CURLE_ABORTED_BY_CALLBACK 54 | E_BAD_FUNCTION_ARGUMENT = C.CURLE_BAD_FUNCTION_ARGUMENT 55 | E_BAD_CALLING_ORDER = C.CURLE_BAD_CALLING_ORDER 56 | E_INTERFACE_FAILED = C.CURLE_INTERFACE_FAILED 57 | E_BAD_PASSWORD_ENTERED = C.CURLE_BAD_PASSWORD_ENTERED 58 | E_UNKNOWN_TELNET_OPTION = C.CURLE_UNKNOWN_TELNET_OPTION 59 | E_OBSOLETE = C.CURLE_OBSOLETE 60 | E_SSL_PEER_CERTIFICATE = C.CURLE_SSL_PEER_CERTIFICATE 61 | E_GOT_NOTHING = C.CURLE_GOT_NOTHING 62 | E_SSL_ENGINE_NOTFOUND = C.CURLE_SSL_ENGINE_NOTFOUND 63 | E_SSL_ENGINE_SETFAILED = C.CURLE_SSL_ENGINE_SETFAILED 64 | E_SEND_ERROR = C.CURLE_SEND_ERROR 65 | E_RECV_ERROR = C.CURLE_RECV_ERROR 66 | E_SHARE_IN_USE = C.CURLE_SHARE_IN_USE 67 | E_SSL_CERTPROBLEM = C.CURLE_SSL_CERTPROBLEM 68 | E_SSL_CIPHER = C.CURLE_SSL_CIPHER 69 | E_SSL_CACERT = C.CURLE_SSL_CACERT 70 | E_BAD_CONTENT_ENCODING = C.CURLE_BAD_CONTENT_ENCODING 71 | E_LDAP_INVALID_URL = C.CURLE_LDAP_INVALID_URL 72 | E_FILESIZE_EXCEEDED = C.CURLE_FILESIZE_EXCEEDED 73 | E_FTP_SSL_FAILED = C.CURLE_FTP_SSL_FAILED 74 | E_SEND_FAIL_REWIND = C.CURLE_SEND_FAIL_REWIND 75 | E_SSL_ENGINE_INITFAILED = C.CURLE_SSL_ENGINE_INITFAILED 76 | E_LOGIN_DENIED = C.CURLE_LOGIN_DENIED 77 | E_TFTP_NOTFOUND = C.CURLE_TFTP_NOTFOUND 78 | E_TFTP_PERM = C.CURLE_TFTP_PERM 79 | E_TFTP_DISKFULL = C.CURLE_TFTP_DISKFULL 80 | E_TFTP_ILLEGAL = C.CURLE_TFTP_ILLEGAL 81 | E_TFTP_UNKNOWNID = C.CURLE_TFTP_UNKNOWNID 82 | E_TFTP_EXISTS = C.CURLE_TFTP_EXISTS 83 | E_TFTP_NOSUCHUSER = C.CURLE_TFTP_NOSUCHUSER 84 | E_CONV_FAILED = C.CURLE_CONV_FAILED 85 | E_CONV_REQD = C.CURLE_CONV_REQD 86 | E_SSL_CACERT_BADFILE = C.CURLE_SSL_CACERT_BADFILE 87 | E_OPERATION_TIMEDOUT = C.CURLE_OPERATION_TIMEDOUT 88 | E_HTTP_NOT_FOUND = C.CURLE_HTTP_NOT_FOUND 89 | E_HTTP_PORT_FAILED = C.CURLE_HTTP_PORT_FAILED 90 | E_ALREADY_COMPLETE = C.CURLE_ALREADY_COMPLETE 91 | E_FTP_PARTIAL_FILE = C.CURLE_FTP_PARTIAL_FILE 92 | E_FTP_BAD_DOWNLOAD_RESUME = C.CURLE_FTP_BAD_DOWNLOAD_RESUME 93 | ) 94 | 95 | // easy.Setopt(flag, ...) 96 | const ( 97 | OPT_FILE = C.CURLOPT_FILE 98 | OPT_URL = C.CURLOPT_URL 99 | OPT_PORT = C.CURLOPT_PORT 100 | OPT_PROXY = C.CURLOPT_PROXY 101 | OPT_USERPWD = C.CURLOPT_USERPWD 102 | OPT_PROXYUSERPWD = C.CURLOPT_PROXYUSERPWD 103 | OPT_RANGE = C.CURLOPT_RANGE 104 | OPT_INFILE = C.CURLOPT_INFILE 105 | OPT_ERRORBUFFER = C.CURLOPT_ERRORBUFFER 106 | OPT_WRITEFUNCTION = C.CURLOPT_WRITEFUNCTION 107 | OPT_READFUNCTION = C.CURLOPT_READFUNCTION 108 | OPT_TIMEOUT = C.CURLOPT_TIMEOUT 109 | OPT_INFILESIZE = C.CURLOPT_INFILESIZE 110 | OPT_POSTFIELDS = C.CURLOPT_POSTFIELDS 111 | OPT_REFERER = C.CURLOPT_REFERER 112 | OPT_FTPPORT = C.CURLOPT_FTPPORT 113 | OPT_USERAGENT = C.CURLOPT_USERAGENT 114 | OPT_LOW_SPEED_TIME = C.CURLOPT_LOW_SPEED_TIME 115 | OPT_RESUME_FROM = C.CURLOPT_RESUME_FROM 116 | OPT_COOKIE = C.CURLOPT_COOKIE 117 | OPT_HTTPHEADER = C.CURLOPT_HTTPHEADER 118 | OPT_HTTPPOST = C.CURLOPT_HTTPPOST 119 | OPT_SSLCERT = C.CURLOPT_SSLCERT 120 | OPT_SSLCERTPASSWD = C.CURLOPT_SSLCERTPASSWD 121 | OPT_SSLKEYPASSWD = C.CURLOPT_SSLKEYPASSWD 122 | OPT_CRLF = C.CURLOPT_CRLF 123 | OPT_QUOTE = C.CURLOPT_QUOTE 124 | OPT_WRITEHEADER = C.CURLOPT_WRITEHEADER 125 | OPT_COOKIEFILE = C.CURLOPT_COOKIEFILE 126 | OPT_SSLVERSION = C.CURLOPT_SSLVERSION 127 | OPT_TIMECONDITION = C.CURLOPT_TIMECONDITION 128 | OPT_TIMEVALUE = C.CURLOPT_TIMEVALUE 129 | OPT_CUSTOMREQUEST = C.CURLOPT_CUSTOMREQUEST 130 | OPT_STDERR = C.CURLOPT_STDERR 131 | OPT_POSTQUOTE = C.CURLOPT_POSTQUOTE 132 | OPT_WRITEINFO = C.CURLOPT_WRITEINFO 133 | OPT_VERBOSE = C.CURLOPT_VERBOSE 134 | OPT_HEADER = C.CURLOPT_HEADER 135 | OPT_NOPROGRESS = C.CURLOPT_NOPROGRESS 136 | OPT_NOBODY = C.CURLOPT_NOBODY 137 | OPT_FAILONERROR = C.CURLOPT_FAILONERROR 138 | OPT_UPLOAD = C.CURLOPT_UPLOAD 139 | OPT_POST = C.CURLOPT_POST 140 | OPT_FTPLISTONLY = C.CURLOPT_FTPLISTONLY 141 | OPT_FTPAPPEND = C.CURLOPT_FTPAPPEND 142 | OPT_NETRC = C.CURLOPT_NETRC 143 | OPT_FOLLOWLOCATION = C.CURLOPT_FOLLOWLOCATION 144 | OPT_TRANSFERTEXT = C.CURLOPT_TRANSFERTEXT 145 | OPT_PUT = C.CURLOPT_PUT 146 | OPT_PROGRESSFUNCTION = C.CURLOPT_PROGRESSFUNCTION 147 | OPT_PROGRESSDATA = C.CURLOPT_PROGRESSDATA 148 | OPT_AUTOREFERER = C.CURLOPT_AUTOREFERER 149 | OPT_PROXYPORT = C.CURLOPT_PROXYPORT 150 | OPT_POSTFIELDSIZE = C.CURLOPT_POSTFIELDSIZE 151 | OPT_HTTPPROXYTUNNEL = C.CURLOPT_HTTPPROXYTUNNEL 152 | OPT_INTERFACE = C.CURLOPT_INTERFACE 153 | OPT_KRB4LEVEL = C.CURLOPT_KRB4LEVEL 154 | OPT_SSL_VERIFYPEER = C.CURLOPT_SSL_VERIFYPEER 155 | OPT_CAINFO = C.CURLOPT_CAINFO 156 | OPT_MAXREDIRS = C.CURLOPT_MAXREDIRS 157 | OPT_FILETIME = C.CURLOPT_FILETIME 158 | OPT_TELNETOPTIONS = C.CURLOPT_TELNETOPTIONS 159 | OPT_MAXCONNECTS = C.CURLOPT_MAXCONNECTS 160 | OPT_CLOSEPOLICY = C.CURLOPT_CLOSEPOLICY 161 | OPT_FRESH_CONNECT = C.CURLOPT_FRESH_CONNECT 162 | OPT_FORBID_REUSE = C.CURLOPT_FORBID_REUSE 163 | OPT_RANDOM_FILE = C.CURLOPT_RANDOM_FILE 164 | OPT_EGDSOCKET = C.CURLOPT_EGDSOCKET 165 | OPT_CONNECTTIMEOUT = C.CURLOPT_CONNECTTIMEOUT 166 | OPT_HEADERFUNCTION = C.CURLOPT_HEADERFUNCTION 167 | OPT_HTTPGET = C.CURLOPT_HTTPGET 168 | OPT_SSL_VERIFYHOST = C.CURLOPT_SSL_VERIFYHOST 169 | OPT_COOKIEJAR = C.CURLOPT_COOKIEJAR 170 | OPT_SSL_CIPHER_LIST = C.CURLOPT_SSL_CIPHER_LIST 171 | OPT_HTTP_VERSION = C.CURLOPT_HTTP_VERSION 172 | OPT_FTP_USE_EPSV = C.CURLOPT_FTP_USE_EPSV 173 | OPT_SSLCERTTYPE = C.CURLOPT_SSLCERTTYPE 174 | OPT_SSLKEY = C.CURLOPT_SSLKEY 175 | OPT_SSLKEYTYPE = C.CURLOPT_SSLKEYTYPE 176 | OPT_SSLENGINE = C.CURLOPT_SSLENGINE 177 | OPT_SSLENGINE_DEFAULT = C.CURLOPT_SSLENGINE_DEFAULT 178 | OPT_DNS_USE_GLOBAL_CACHE = C.CURLOPT_DNS_USE_GLOBAL_CACHE 179 | OPT_DNS_CACHE_TIMEOUT = C.CURLOPT_DNS_CACHE_TIMEOUT 180 | OPT_PREQUOTE = C.CURLOPT_PREQUOTE 181 | OPT_DEBUGFUNCTION = C.CURLOPT_DEBUGFUNCTION 182 | OPT_DEBUGDATA = C.CURLOPT_DEBUGDATA 183 | OPT_COOKIESESSION = C.CURLOPT_COOKIESESSION 184 | OPT_CAPATH = C.CURLOPT_CAPATH 185 | OPT_BUFFERSIZE = C.CURLOPT_BUFFERSIZE 186 | OPT_NOSIGNAL = C.CURLOPT_NOSIGNAL 187 | OPT_SHARE = C.CURLOPT_SHARE 188 | OPT_PROXYTYPE = C.CURLOPT_PROXYTYPE 189 | OPT_ENCODING = C.CURLOPT_ENCODING 190 | OPT_PRIVATE = C.CURLOPT_PRIVATE 191 | OPT_HTTP200ALIASES = C.CURLOPT_HTTP200ALIASES 192 | OPT_UNRESTRICTED_AUTH = C.CURLOPT_UNRESTRICTED_AUTH 193 | OPT_FTP_USE_EPRT = C.CURLOPT_FTP_USE_EPRT 194 | OPT_HTTPAUTH = C.CURLOPT_HTTPAUTH 195 | OPT_SSL_CTX_FUNCTION = C.CURLOPT_SSL_CTX_FUNCTION 196 | OPT_SSL_CTX_DATA = C.CURLOPT_SSL_CTX_DATA 197 | OPT_FTP_CREATE_MISSING_DIRS = C.CURLOPT_FTP_CREATE_MISSING_DIRS 198 | OPT_PROXYAUTH = C.CURLOPT_PROXYAUTH 199 | OPT_IPRESOLVE = C.CURLOPT_IPRESOLVE 200 | OPT_RESOLVE = C.CURLOPT_RESOLVE 201 | OPT_MAXFILESIZE = C.CURLOPT_MAXFILESIZE 202 | OPT_INFILESIZE_LARGE = C.CURLOPT_INFILESIZE_LARGE 203 | OPT_RESUME_FROM_LARGE = C.CURLOPT_RESUME_FROM_LARGE 204 | OPT_MAXFILESIZE_LARGE = C.CURLOPT_MAXFILESIZE_LARGE 205 | OPT_NETRC_FILE = C.CURLOPT_NETRC_FILE 206 | OPT_FTP_SSL = C.CURLOPT_FTP_SSL 207 | OPT_POSTFIELDSIZE_LARGE = C.CURLOPT_POSTFIELDSIZE_LARGE 208 | OPT_TCP_NODELAY = C.CURLOPT_TCP_NODELAY 209 | OPT_FTPSSLAUTH = C.CURLOPT_FTPSSLAUTH 210 | OPT_IOCTLFUNCTION = C.CURLOPT_IOCTLFUNCTION 211 | OPT_IOCTLDATA = C.CURLOPT_IOCTLDATA 212 | OPT_FTP_ACCOUNT = C.CURLOPT_FTP_ACCOUNT 213 | OPT_COOKIELIST = C.CURLOPT_COOKIELIST 214 | OPT_IGNORE_CONTENT_LENGTH = C.CURLOPT_IGNORE_CONTENT_LENGTH 215 | OPT_FTP_SKIP_PASV_IP = C.CURLOPT_FTP_SKIP_PASV_IP 216 | OPT_FTP_FILEMETHOD = C.CURLOPT_FTP_FILEMETHOD 217 | OPT_LOCALPORT = C.CURLOPT_LOCALPORT 218 | OPT_LOCALPORTRANGE = C.CURLOPT_LOCALPORTRANGE 219 | OPT_CONNECT_ONLY = C.CURLOPT_CONNECT_ONLY 220 | OPT_CONV_FROM_NETWORK_FUNCTION = C.CURLOPT_CONV_FROM_NETWORK_FUNCTION 221 | OPT_CONV_TO_NETWORK_FUNCTION = C.CURLOPT_CONV_TO_NETWORK_FUNCTION 222 | OPT_CONV_FROM_UTF8_FUNCTION = C.CURLOPT_CONV_FROM_UTF8_FUNCTION 223 | OPT_MAX_SEND_SPEED_LARGE = C.CURLOPT_MAX_SEND_SPEED_LARGE 224 | OPT_MAX_RECV_SPEED_LARGE = C.CURLOPT_MAX_RECV_SPEED_LARGE 225 | OPT_FTP_ALTERNATIVE_TO_USER = C.CURLOPT_FTP_ALTERNATIVE_TO_USER 226 | OPT_SOCKOPTFUNCTION = C.CURLOPT_SOCKOPTFUNCTION 227 | OPT_SOCKOPTDATA = C.CURLOPT_SOCKOPTDATA 228 | OPT_SSL_SESSIONID_CACHE = C.CURLOPT_SSL_SESSIONID_CACHE 229 | OPT_WRITEDATA = C.CURLOPT_WRITEDATA 230 | OPT_READDATA = C.CURLOPT_READDATA 231 | OPT_HEADERDATA = C.CURLOPT_HEADERDATA 232 | ) 233 | 234 | // easy.Getinfo(flag) 235 | const ( 236 | INFO_TEXT = C.CURLINFO_TEXT 237 | INFO_EFFECTIVE_URL = C.CURLINFO_EFFECTIVE_URL 238 | INFO_RESPONSE_CODE = C.CURLINFO_RESPONSE_CODE 239 | INFO_TOTAL_TIME = C.CURLINFO_TOTAL_TIME 240 | INFO_NAMELOOKUP_TIME = C.CURLINFO_NAMELOOKUP_TIME 241 | INFO_CONNECT_TIME = C.CURLINFO_CONNECT_TIME 242 | INFO_PRETRANSFER_TIME = C.CURLINFO_PRETRANSFER_TIME 243 | INFO_SIZE_UPLOAD = C.CURLINFO_SIZE_UPLOAD 244 | INFO_SIZE_DOWNLOAD = C.CURLINFO_SIZE_DOWNLOAD 245 | INFO_SPEED_DOWNLOAD = C.CURLINFO_SPEED_DOWNLOAD 246 | INFO_SPEED_UPLOAD = C.CURLINFO_SPEED_UPLOAD 247 | INFO_HEADER_SIZE = C.CURLINFO_HEADER_SIZE 248 | INFO_REQUEST_SIZE = C.CURLINFO_REQUEST_SIZE 249 | INFO_SSL_VERIFYRESULT = C.CURLINFO_SSL_VERIFYRESULT 250 | INFO_FILETIME = C.CURLINFO_FILETIME 251 | INFO_CONTENT_LENGTH_DOWNLOAD = C.CURLINFO_CONTENT_LENGTH_DOWNLOAD 252 | INFO_CONTENT_LENGTH_UPLOAD = C.CURLINFO_CONTENT_LENGTH_UPLOAD 253 | INFO_STARTTRANSFER_TIME = C.CURLINFO_STARTTRANSFER_TIME 254 | INFO_CONTENT_TYPE = C.CURLINFO_CONTENT_TYPE 255 | INFO_REDIRECT_TIME = C.CURLINFO_REDIRECT_TIME 256 | INFO_REDIRECT_COUNT = C.CURLINFO_REDIRECT_COUNT 257 | INFO_PRIVATE = C.CURLINFO_PRIVATE 258 | INFO_HTTP_CONNECTCODE = C.CURLINFO_HTTP_CONNECTCODE 259 | INFO_HTTPAUTH_AVAIL = C.CURLINFO_HTTPAUTH_AVAIL 260 | INFO_PROXYAUTH_AVAIL = C.CURLINFO_PROXYAUTH_AVAIL 261 | INFO_OS_ERRNO = C.CURLINFO_OS_ERRNO 262 | INFO_NUM_CONNECTS = C.CURLINFO_NUM_CONNECTS 263 | INFO_SSL_ENGINES = C.CURLINFO_SSL_ENGINES 264 | INFO_COOKIELIST = C.CURLINFO_COOKIELIST 265 | INFO_LASTSOCKET = C.CURLINFO_LASTSOCKET 266 | INFO_FTP_ENTRY_PATH = C.CURLINFO_FTP_ENTRY_PATH 267 | INFO_LASTONE = C.CURLINFO_LASTONE 268 | INFO_HTTP_CODE = C.CURLINFO_HTTP_CODE 269 | ) 270 | 271 | // Auth 272 | const ( 273 | AUTH_NONE = C.CURLAUTH_NONE & (1<<32 - 1) 274 | AUTH_BASIC = C.CURLAUTH_BASIC & (1<<32 - 1) 275 | AUTH_DIGEST = C.CURLAUTH_DIGEST & (1<<32 - 1) 276 | AUTH_GSSNEGOTIATE = C.CURLAUTH_GSSNEGOTIATE & (1<<32 - 1) 277 | AUTH_NTLM = C.CURLAUTH_NTLM & (1<<32 - 1) 278 | AUTH_ANY = C.CURLAUTH_ANY & (1<<32 - 1) 279 | AUTH_ANYSAFE = C.CURLAUTH_ANYSAFE & (1<<32 - 1) 280 | ) 281 | 282 | // generated ends 283 | -------------------------------------------------------------------------------- /easy.go: -------------------------------------------------------------------------------- 1 | package curl 2 | 3 | /* 4 | #include 5 | #include 6 | #include "callback.h" 7 | #include "compat.h" 8 | 9 | static CURLcode curl_easy_setopt_long(CURL *handle, CURLoption option, long parameter) { 10 | return curl_easy_setopt(handle, option, parameter); 11 | } 12 | static CURLcode curl_easy_setopt_string(CURL *handle, CURLoption option, char *parameter) { 13 | return curl_easy_setopt(handle, option, parameter); 14 | } 15 | static CURLcode curl_easy_setopt_slist(CURL *handle, CURLoption option, struct curl_slist *parameter) { 16 | return curl_easy_setopt(handle, option, parameter); 17 | } 18 | static CURLcode curl_easy_setopt_pointer(CURL *handle, CURLoption option, void *parameter) { 19 | return curl_easy_setopt(handle, option, parameter); 20 | } 21 | static CURLcode curl_easy_setopt_off_t(CURL *handle, CURLoption option, off_t parameter) { 22 | return curl_easy_setopt(handle, option, parameter); 23 | } 24 | 25 | static CURLcode curl_easy_getinfo_string(CURL *curl, CURLINFO info, char **p) { 26 | return curl_easy_getinfo(curl, info, p); 27 | } 28 | static CURLcode curl_easy_getinfo_long(CURL *curl, CURLINFO info, long *p) { 29 | return curl_easy_getinfo(curl, info, p); 30 | } 31 | static CURLcode curl_easy_getinfo_double(CURL *curl, CURLINFO info, double *p) { 32 | return curl_easy_getinfo(curl, info, p); 33 | } 34 | static CURLcode curl_easy_getinfo_slist(CURL *curl, CURLINFO info, struct curl_slist **p) { 35 | return curl_easy_getinfo(curl, info, p); 36 | } 37 | 38 | static CURLFORMcode curl_formadd_name_content_length( 39 | struct curl_httppost **httppost, struct curl_httppost **last_post, char *name, char *content, int length) { 40 | return curl_formadd(httppost, last_post, 41 | CURLFORM_COPYNAME, name, 42 | CURLFORM_COPYCONTENTS, content, 43 | CURLFORM_CONTENTSLENGTH, length, CURLFORM_END); 44 | } 45 | static CURLFORMcode curl_formadd_name_content_length_type( 46 | struct curl_httppost **httppost, struct curl_httppost **last_post, char *name, char *content, int length, char *type) { 47 | return curl_formadd(httppost, last_post, 48 | CURLFORM_COPYNAME, name, 49 | CURLFORM_COPYCONTENTS, content, 50 | CURLFORM_CONTENTSLENGTH, length, 51 | CURLFORM_CONTENTTYPE, type, CURLFORM_END); 52 | } 53 | static CURLFORMcode curl_formadd_name_file_type( 54 | struct curl_httppost **httppost, struct curl_httppost **last_post, char *name, char *filename, char *type) { 55 | return curl_formadd(httppost, last_post, 56 | CURLFORM_COPYNAME, name, 57 | CURLFORM_FILE, filename, 58 | CURLFORM_CONTENTTYPE, type, CURLFORM_END); 59 | } 60 | // TODO: support multi file 61 | 62 | */ 63 | import "C" 64 | 65 | import ( 66 | "fmt" 67 | "mime" 68 | "path" 69 | "sync" 70 | "unsafe" 71 | ) 72 | 73 | type CurlInfo C.CURLINFO 74 | type CurlError C.CURLcode 75 | 76 | type CurlString *C.char 77 | 78 | func NewCurlString(s string) CurlString { 79 | return CurlString(unsafe.Pointer(C.CString(s))) 80 | } 81 | 82 | func FreeCurlString(s CurlString) { 83 | C.free(unsafe.Pointer(s)) 84 | } 85 | 86 | func (e CurlError) Error() string { 87 | // ret is const char*, no need to free 88 | ret := C.curl_easy_strerror(C.CURLcode(e)) 89 | return fmt.Sprintf("curl: %s", C.GoString(ret)) 90 | } 91 | 92 | func newCurlError(errno C.CURLcode) error { 93 | if errno == C.CURLE_OK { // if nothing wrong 94 | return nil 95 | } 96 | return CurlError(errno) 97 | } 98 | 99 | // curl_easy interface 100 | type CURL struct { 101 | handle unsafe.Pointer 102 | // callback functions, bool ret means ok or not 103 | headerFunction, writeFunction *func([]byte, interface{}) bool 104 | readFunction *func([]byte, interface{}) int // return num of bytes writed to buf 105 | progressFunction *func(float64, float64, float64, float64, interface{}) bool 106 | fnmatchFunction *func(string, string, interface{}) int 107 | // callback datas 108 | headerData, writeData, readData, progressData, fnmatchData interface{} 109 | // list of C allocs 110 | mallocAllocs []*C.char 111 | } 112 | 113 | // concurrent safe context map 114 | type contextMap struct { 115 | items map[uintptr]*CURL 116 | sync.RWMutex 117 | } 118 | 119 | func (c *contextMap) Set(k uintptr, v *CURL) { 120 | c.Lock() 121 | defer c.Unlock() 122 | 123 | c.items[k] = v 124 | } 125 | 126 | func (c *contextMap) Get(k uintptr) *CURL { 127 | c.RLock() 128 | defer c.RUnlock() 129 | 130 | return c.items[k] 131 | } 132 | 133 | func (c *contextMap) Delete(k uintptr) { 134 | c.Lock() 135 | defer c.Unlock() 136 | 137 | delete(c.items, k) 138 | } 139 | 140 | var context_map = &contextMap{ 141 | items: make(map[uintptr]*CURL), 142 | } 143 | 144 | // curl_easy_init - Start a libcurl easy session 145 | func EasyInit() *CURL { 146 | p := C.curl_easy_init() 147 | c := &CURL{handle: p, mallocAllocs: make([]*C.char, 0)} // other field defaults to nil 148 | context_map.Set(uintptr(p), c) 149 | return c 150 | } 151 | 152 | // curl_easy_duphandle - Clone a libcurl session handle 153 | func (curl *CURL) Duphandle() *CURL { 154 | p := C.curl_easy_duphandle(curl.handle) 155 | c := &CURL{handle: p} 156 | context_map.Set(uintptr(p), c) 157 | return c 158 | } 159 | 160 | // curl_easy_cleanup - End a libcurl easy session 161 | func (curl *CURL) Cleanup() { 162 | p := curl.handle 163 | C.curl_easy_cleanup(p) 164 | curl.MallocFreeAfter(0) 165 | context_map.Delete(uintptr(p)) 166 | } 167 | 168 | // curl_easy_setopt - set options for a curl easy handle 169 | // WARNING: a function pointer is &fun, but function addr is reflect.ValueOf(fun).Pointer() 170 | func (curl *CURL) Setopt(opt int, param interface{}) error { 171 | p := curl.handle 172 | if param == nil { 173 | // NOTE: some option will crash program when got a nil param 174 | return newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), nil)) 175 | } 176 | switch { 177 | // not really set 178 | case opt == OPT_READDATA: // OPT_INFILE 179 | curl.readData = param 180 | return nil 181 | case opt == OPT_PROGRESSDATA: 182 | curl.progressData = param 183 | return nil 184 | case opt == OPT_HEADERDATA: // also known as OPT_WRITEHEADER 185 | curl.headerData = param 186 | return nil 187 | case opt == OPT_WRITEDATA: // OPT_FILE 188 | curl.writeData = param 189 | return nil 190 | 191 | case opt == OPT_READFUNCTION: 192 | fun := param.(func([]byte, interface{}) int) 193 | curl.readFunction = &fun 194 | 195 | ptr := C.return_read_function() 196 | if err := newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), ptr)); err == nil { 197 | return newCurlError(C.curl_easy_setopt_pointer(p, OPT_READDATA, unsafe.Pointer(curl.handle))) 198 | } else { 199 | return err 200 | } 201 | 202 | case opt == OPT_PROGRESSFUNCTION: 203 | fun := param.(func(float64, float64, float64, float64, interface{}) bool) 204 | curl.progressFunction = &fun 205 | 206 | ptr := C.return_progress_function() 207 | if err := newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), ptr)); err == nil { 208 | return newCurlError(C.curl_easy_setopt_pointer(p, OPT_PROGRESSDATA, unsafe.Pointer(curl.handle))) 209 | } else { 210 | return err 211 | } 212 | 213 | case opt == OPT_HEADERFUNCTION: 214 | fun := param.(func([]byte, interface{}) bool) 215 | curl.headerFunction = &fun 216 | 217 | ptr := C.return_header_function() 218 | if err := newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), ptr)); err == nil { 219 | return newCurlError(C.curl_easy_setopt_pointer(p, OPT_HEADERDATA, unsafe.Pointer(curl.handle))) 220 | } else { 221 | return err 222 | } 223 | 224 | case opt == OPT_WRITEFUNCTION: 225 | fun := param.(func([]byte, interface{}) bool) 226 | curl.writeFunction = &fun 227 | 228 | ptr := C.return_write_function() 229 | if err := newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), ptr)); err == nil { 230 | return newCurlError(C.curl_easy_setopt_pointer(p, OPT_WRITEDATA, unsafe.Pointer(curl.handle))) 231 | } else { 232 | return err 233 | } 234 | 235 | // for OPT_HTTPPOST, use struct Form 236 | case opt == OPT_HTTPPOST: 237 | post := param.(*Form) 238 | ptr := post.head 239 | return newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), unsafe.Pointer(ptr))) 240 | 241 | case opt >= C.CURLOPTTYPE_OFF_T: 242 | val := C.off_t(0) 243 | switch t := param.(type) { 244 | case int: 245 | val = C.off_t(t) 246 | case uint64: 247 | val = C.off_t(t) 248 | default: 249 | panic("OFF_T conversion not supported") 250 | } 251 | return newCurlError(C.curl_easy_setopt_off_t(p, C.CURLoption(opt), val)) 252 | 253 | case opt >= C.CURLOPTTYPE_FUNCTIONPOINT: 254 | // function pointer 255 | panic("function pointer not implemented yet!") 256 | 257 | case opt >= C.CURLOPTTYPE_OBJECTPOINT: 258 | switch t := param.(type) { 259 | case string: 260 | ptr := C.CString(t) 261 | curl.mallocAddPtr(ptr) 262 | return newCurlError(C.curl_easy_setopt_string(p, C.CURLoption(opt), ptr)) 263 | case CurlString: 264 | ptr := (*C.char)(t) 265 | return newCurlError(C.curl_easy_setopt_string(p, C.CURLoption(opt), ptr)) 266 | case []string: 267 | if len(t) > 0 { 268 | ptr := C.CString(t[0]) 269 | curl.mallocAddPtr(ptr) 270 | a_slist := C.curl_slist_append(nil, ptr) 271 | for _, s := range t[1:] { 272 | ptr := C.CString(s) 273 | curl.mallocAddPtr(ptr) 274 | a_slist = C.curl_slist_append(a_slist, ptr) 275 | } 276 | return newCurlError(C.curl_easy_setopt_slist(p, C.CURLoption(opt), a_slist)) 277 | } else { 278 | return newCurlError(C.curl_easy_setopt_slist(p, C.CURLoption(opt), nil)) 279 | } 280 | case []CurlString: 281 | if len(t) > 0 { 282 | ptr := (*C.char)(t[0]) 283 | a_slist := C.curl_slist_append(nil, ptr) 284 | for _, s := range t[1:] { 285 | ptr := (*C.char)(s) 286 | a_slist = C.curl_slist_append(a_slist, ptr) 287 | } 288 | return newCurlError(C.curl_easy_setopt_slist(p, C.CURLoption(opt), a_slist)) 289 | } else { 290 | return newCurlError(C.curl_easy_setopt_slist(p, C.CURLoption(opt), nil)) 291 | } 292 | default: 293 | // It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer. 294 | // val := reflect.ValueOf(param) 295 | //fmt.Printf("DEBUG(Setopt): param=%x\n", val.Pointer()) 296 | //println("DEBUG can addr =", val.Pointer(), "opt=", opt) 297 | // pass a pointer to GoInterface 298 | return newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), 299 | unsafe.Pointer(¶m))) 300 | } 301 | case opt >= C.CURLOPTTYPE_LONG: 302 | val := C.long(0) 303 | switch t := param.(type) { 304 | case int: 305 | val = C.long(t) 306 | case bool: 307 | if t { 308 | val = 1 309 | } 310 | case int64: 311 | val = C.long(t) 312 | case int32: 313 | val = C.long(t) 314 | default: 315 | panic("not supported converstion to c long") 316 | } 317 | return newCurlError(C.curl_easy_setopt_long(p, C.CURLoption(opt), val)) 318 | } 319 | panic("opt param error!") 320 | } 321 | 322 | // curl_easy_send - sends raw data over an "easy" connection 323 | func (curl *CURL) Send(buffer []byte) (int, error) { 324 | p := curl.handle 325 | buflen := len(buffer) 326 | n := C.size_t(0) 327 | ret := C.curl_easy_send(p, unsafe.Pointer(&buffer[0]), C.size_t(buflen), &n) 328 | return int(n), newCurlError(ret) 329 | } 330 | 331 | // curl_easy_recv - receives raw data on an "easy" connection 332 | func (curl *CURL) Recv(buffer []byte) (int, error) { 333 | p := curl.handle 334 | buflen := len(buffer) 335 | buf := C.CString(string(buffer)) 336 | n := C.size_t(0) 337 | ret := C.curl_easy_recv(p, unsafe.Pointer(buf), C.size_t(buflen), &n) 338 | return copy(buffer, C.GoStringN(buf, C.int(n))), newCurlError(ret) 339 | } 340 | 341 | // curl_easy_perform - Perform a file transfer 342 | func (curl *CURL) Perform() error { 343 | p := curl.handle 344 | return newCurlError(C.curl_easy_perform(p)) 345 | } 346 | 347 | // curl_easy_pause - pause and unpause a connection 348 | func (curl *CURL) Pause(bitmask int) error { 349 | p := curl.handle 350 | return newCurlError(C.curl_easy_pause(p, C.int(bitmask))) 351 | } 352 | 353 | // curl_easy_reset - reset all options of a libcurl session handle 354 | func (curl *CURL) Reset() { 355 | p := curl.handle 356 | C.curl_easy_reset(p) 357 | } 358 | 359 | // curl_easy_escape - URL encodes the given string 360 | func (curl *CURL) Escape(url string) string { 361 | p := curl.handle 362 | oldUrl := C.CString(url) 363 | defer C.free(unsafe.Pointer(oldUrl)) 364 | newUrl := C.curl_easy_escape(p, oldUrl, 0) 365 | defer C.curl_free(unsafe.Pointer(newUrl)) 366 | return C.GoString(newUrl) 367 | } 368 | 369 | // curl_easy_unescape - URL decodes the given string 370 | func (curl *CURL) Unescape(url string) string { 371 | p := curl.handle 372 | oldUrl := C.CString(url) 373 | outlength := C.int(0) 374 | defer C.free(unsafe.Pointer(oldUrl)) 375 | // If outlength is non-NULL, the function will write the length of the 376 | // returned string in the integer it points to. This allows an 377 | // escaped string containing %00 to still get used properly after unescaping. 378 | newUrl := C.curl_easy_unescape(p, oldUrl, 0, &outlength) 379 | defer C.curl_free(unsafe.Pointer(newUrl)) 380 | return C.GoStringN(newUrl, outlength) 381 | } 382 | 383 | // curl_easy_getinfo - extract information from a curl handle 384 | func (curl *CURL) Getinfo(info CurlInfo) (ret interface{}, err error) { 385 | p := curl.handle 386 | cInfo := C.CURLINFO(info) 387 | switch cInfo & C.CURLINFO_TYPEMASK { 388 | case C.CURLINFO_STRING: 389 | a_string := C.CString("") 390 | defer C.free(unsafe.Pointer(a_string)) 391 | err := newCurlError(C.curl_easy_getinfo_string(p, cInfo, &a_string)) 392 | ret := C.GoString(a_string) 393 | debugf("Getinfo %s", ret) 394 | return ret, err 395 | case C.CURLINFO_LONG: 396 | a_long := C.long(-1) 397 | err := newCurlError(C.curl_easy_getinfo_long(p, cInfo, &a_long)) 398 | ret := int(a_long) 399 | debugf("Getinfo %s", ret) 400 | return ret, err 401 | case C.CURLINFO_DOUBLE: 402 | a_double := C.double(0.0) 403 | err := newCurlError(C.curl_easy_getinfo_double(p, cInfo, &a_double)) 404 | ret := float64(a_double) 405 | debugf("Getinfo %s", ret) 406 | return ret, err 407 | case C.CURLINFO_SLIST: 408 | a_ptr_slist := (*C.struct_curl_slist)(nil) 409 | err := newCurlError(C.curl_easy_getinfo_slist(p, cInfo, &a_ptr_slist)) 410 | ret := []string{} 411 | for a_ptr_slist != nil { 412 | debugf("Getinfo %s %v", C.GoString(a_ptr_slist.data), a_ptr_slist.next) 413 | ret = append(ret, C.GoString(a_ptr_slist.data)) 414 | a_ptr_slist = a_ptr_slist.next 415 | } 416 | return ret, err 417 | default: 418 | panic("error calling Getinfo\n") 419 | } 420 | panic("not implemented yet!") 421 | return nil, nil 422 | } 423 | 424 | func (curl *CURL) GetHandle() unsafe.Pointer { 425 | return curl.handle 426 | } 427 | 428 | func (curl *CURL) MallocGetPos() int { 429 | return len(curl.mallocAllocs) 430 | } 431 | 432 | func (curl *CURL) MallocFreeAfter(from int) { 433 | l := len(curl.mallocAllocs) 434 | for idx := from; idx < l; idx++ { 435 | C.free(unsafe.Pointer(curl.mallocAllocs[idx])) 436 | curl.mallocAllocs[idx] = nil 437 | } 438 | curl.mallocAllocs = curl.mallocAllocs[0:from] 439 | } 440 | 441 | func (curl *CURL) mallocAddPtr(ptr *C.char) { 442 | curl.mallocAllocs = append(curl.mallocAllocs, ptr) 443 | } 444 | 445 | // A multipart/formdata HTTP POST form 446 | type Form struct { 447 | head, last *C.struct_curl_httppost 448 | } 449 | 450 | func NewForm() *Form { 451 | return &Form{} 452 | } 453 | 454 | func (form *Form) Add(name string, content interface{}) error { 455 | head, last := form.head, form.last 456 | namestr := C.CString(name) 457 | defer C.free(unsafe.Pointer(namestr)) 458 | var ( 459 | buffer *C.char 460 | length C.int 461 | ) 462 | switch t := content.(type) { 463 | case string: 464 | buffer = C.CString(t) 465 | length = C.int(len(t)) 466 | case []byte: 467 | buffer = C.CString(string(t)) 468 | length = C.int(len(t)) 469 | default: 470 | panic("not implemented") 471 | } 472 | defer C.free(unsafe.Pointer(buffer)) 473 | C.curl_formadd_name_content_length(&head, &last, namestr, buffer, length) 474 | form.head, form.last = head, last 475 | return nil 476 | } 477 | 478 | func (form *Form) AddWithType(name string, content interface{}, content_type string) error { 479 | head, last := form.head, form.last 480 | namestr := C.CString(name) 481 | typestr := C.CString(content_type) 482 | defer C.free(unsafe.Pointer(namestr)) 483 | defer C.free(unsafe.Pointer(typestr)) 484 | var ( 485 | buffer *C.char 486 | length C.int 487 | ) 488 | switch t := content.(type) { 489 | case string: 490 | buffer = C.CString(t) 491 | length = C.int(len(t)) 492 | case []byte: 493 | buffer = C.CString(string(t)) 494 | length = C.int(len(t)) 495 | default: 496 | panic("not implemented") 497 | } 498 | defer C.free(unsafe.Pointer(buffer)) 499 | C.curl_formadd_name_content_length_type(&head, &last, namestr, buffer, length, typestr) 500 | form.head, form.last = head, last 501 | return nil 502 | } 503 | 504 | func (form *Form) AddFile(name, filename string) error { 505 | head, last := form.head, form.last 506 | namestr := C.CString(name) 507 | pathstr := C.CString(filename) 508 | typestr := C.CString(guessType(filename)) 509 | defer C.free(unsafe.Pointer(namestr)) 510 | defer C.free(unsafe.Pointer(pathstr)) 511 | defer C.free(unsafe.Pointer(typestr)) 512 | C.curl_formadd_name_file_type(&head, &last, namestr, pathstr, typestr) 513 | form.head, form.last = head, last 514 | return nil 515 | } 516 | 517 | func (form *Form) AddFromFile(name, filename string) { 518 | } 519 | 520 | func guessType(filename string) string { 521 | ext := path.Ext(filename) 522 | file_type := mime.TypeByExtension(ext) 523 | if file_type == "" { 524 | return "application/octet-stream" 525 | } 526 | return file_type 527 | } 528 | -------------------------------------------------------------------------------- /compat.h: -------------------------------------------------------------------------------- 1 | 2 | /* generated by compatgen.py */ 3 | #include 4 | 5 | 6 | 7 | #define CURLINFO_HTTPAUTH_USED 0 8 | #define CURLINFO_PROXYAUTH_USED 0 9 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 11) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 11 && LIBCURL_VERSION_PATCH < 1) 10 | #define CURLE_OBSOLETE34 -1 11 | #define CURLE_OBSOLETE41 -1 12 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 11) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 11 && LIBCURL_VERSION_PATCH < 0) 13 | #define CURLINFO_EARLYDATA_SENT_T 0 14 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 10) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 10 && LIBCURL_VERSION_PATCH < 1) 15 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 10) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 10 && LIBCURL_VERSION_PATCH < 0) 16 | #define CURLOPT_OBSOLETE72 0 17 | #define CURLOPT_OBSOLETE40 0 18 | #define CURLINFO_POSTTRANSFER_TIME_T 0 19 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 9) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 9 && LIBCURL_VERSION_PATCH < 1) 20 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 9) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 9 && LIBCURL_VERSION_PATCH < 0) 21 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 8) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 8 && LIBCURL_VERSION_PATCH < 0) 22 | #define CURLE_ECH_REQUIRED -1 23 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 7) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 7 && LIBCURL_VERSION_PATCH < 1) 24 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 7) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 7 && LIBCURL_VERSION_PATCH < 0) 25 | #define CURLINFO_USED_PROXY 0 26 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 6) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 6 && LIBCURL_VERSION_PATCH < 0) 27 | #define CURLE_TOO_LARGE -1 28 | #define CURLINFO_QUEUE_TIME_T 0 29 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 5) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 5 && LIBCURL_VERSION_PATCH < 0) 30 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 4) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 4 && LIBCURL_VERSION_PATCH < 0) 31 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 3) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 3 && LIBCURL_VERSION_PATCH < 0) 32 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 2) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 2 && LIBCURL_VERSION_PATCH < 1) 33 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 2) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 2 && LIBCURL_VERSION_PATCH < 0) 34 | #define CURLOPT_MAIL_RCPT_ALLLOWFAILS 0 35 | #define CURLINFO_XFER_ID 0 36 | #define CURLINFO_CONN_ID 0 37 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 1) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 1 && LIBCURL_VERSION_PATCH < 2) 38 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 1) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 1 && LIBCURL_VERSION_PATCH < 1) 39 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 1) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 1 && LIBCURL_VERSION_PATCH < 0) 40 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 0) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 0 && LIBCURL_VERSION_PATCH < 1) 41 | #if LIBCURL_VERSION_MAJOR < 8 || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR < 0) || (LIBCURL_VERSION_MAJOR == 8 && LIBCURL_VERSION_MINOR == 0 && LIBCURL_VERSION_PATCH < 0) 42 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 88) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 88 && LIBCURL_VERSION_PATCH < 1) 43 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 88) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 88 && LIBCURL_VERSION_PATCH < 0) 44 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 87) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 87 && LIBCURL_VERSION_PATCH < 0) 45 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 86) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 86 && LIBCURL_VERSION_PATCH < 0) 46 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 85) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 85 && LIBCURL_VERSION_PATCH < 0) 47 | #define CURLOPT_FTP_RESPONSE_TIMEOUT 0 48 | #define CURLE_OBSOLETE75 -1 49 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 84) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 84 && LIBCURL_VERSION_PATCH < 0) 50 | #define CURLE_UNRECOVERABLE_POLL -1 51 | #define CURLINFO_CAINFO 0 52 | #define CURLINFO_CAPATH 0 53 | #define CURL_VERSION_THREADSAFE 0 54 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 83) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 83 && LIBCURL_VERSION_PATCH < 1) 55 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 83) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 83 && LIBCURL_VERSION_PATCH < 0) 56 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 82) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 82 && LIBCURL_VERSION_PATCH < 0) 57 | #define CURLE_OBSOLETE62 -1 58 | #define CURLE_OBSOLETE76 -1 59 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 81) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 81 && LIBCURL_VERSION_PATCH < 0) 60 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 80) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 80 && LIBCURL_VERSION_PATCH < 0) 61 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 79) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 79 && LIBCURL_VERSION_PATCH < 1) 62 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 79) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 79 && LIBCURL_VERSION_PATCH < 0) 63 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 78) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 78 && LIBCURL_VERSION_PATCH < 0) 64 | #define CURLE_SETOPT_OPTION_SYNTAX -1 65 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 77) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 77 && LIBCURL_VERSION_PATCH < 0) 66 | #define CURLE_SSL_CLIENTCERT -1 67 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 76) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 76 && LIBCURL_VERSION_PATCH < 1) 68 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 76) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 76 && LIBCURL_VERSION_PATCH < 0) 69 | #define CURLINFO_REFERER 0 70 | #define CURL_VERSION_GSASL 0 71 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 75) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 75 && LIBCURL_VERSION_PATCH < 0) 72 | #define CURLAUTH_AWS_SIGV4 0 73 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 74) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 74 && LIBCURL_VERSION_PATCH < 0) 74 | #define CURL_VERSION_HSTS 0 75 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 73) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 73 && LIBCURL_VERSION_PATCH < 0) 76 | #define CURLOPT_PROGRESSDATA 0 77 | #define CURLE_PROXY -1 78 | #define CURLINFO_PROXY_ERROR 0 79 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 72) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 72 && LIBCURL_VERSION_PATCH < 0) 80 | #define CURLINFO_EFFECTIVE_METHOD 0 81 | #define CURL_VERSION_ZSTD 0 82 | #define CURL_VERSION_UNICODE 0 83 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 71) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 71 && LIBCURL_VERSION_PATCH < 1) 84 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 71) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 71 && LIBCURL_VERSION_PATCH < 0) 85 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 70) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 70 && LIBCURL_VERSION_PATCH < 0) 86 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 69) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 69 && LIBCURL_VERSION_PATCH < 1) 87 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 69) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 69 && LIBCURL_VERSION_PATCH < 0) 88 | #define CURLE_QUIC_CONNECT_ERROR -1 89 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 68) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 68 && LIBCURL_VERSION_PATCH < 0) 90 | #define CURLE_HTTP3 -1 91 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 67) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 67 && LIBCURL_VERSION_PATCH < 0) 92 | #define CURL_VERSION_ESNI 0 93 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 66) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 66 && LIBCURL_VERSION_PATCH < 0) 94 | #define CURLOPT_SASL_AUTHZID 0 95 | #define CURLE_AUTH_ERROR -1 96 | #define CURLINFO_RETRY_AFTER 0 97 | #define CURL_VERSION_HTTP3 0 98 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 65) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 65 && LIBCURL_VERSION_PATCH < 3) 99 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 65) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 65 && LIBCURL_VERSION_PATCH < 2) 100 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 65) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 65 && LIBCURL_VERSION_PATCH < 1) 101 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 65) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 65 && LIBCURL_VERSION_PATCH < 0) 102 | #define CURLOPT_MAXAGE_CONN 0 103 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 64) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 64 && LIBCURL_VERSION_PATCH < 1) 104 | #define CURLOPT_ALTSVC_CTRL 0 105 | #define CURLOPT_ALTSVC 0 106 | #define CURL_VERSION_ALTSVC 0 107 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 64) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 64 && LIBCURL_VERSION_PATCH < 0) 108 | #define CURLOPT_TRAILERFUNCTION 0 109 | #define CURLOPT_TRAILERDATA 0 110 | #define CURLOPT_HTTP09_ALLOWED 0 111 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 63) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 63 && LIBCURL_VERSION_PATCH < 0) 112 | #define CURLOPT_CURLU 0 113 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 62) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 62 && LIBCURL_VERSION_PATCH < 0) 114 | #define CURLOPT_DOH_URL 0 115 | #define CURLOPT_UPLOAD_BUFFERSIZE 0 116 | #define CURLOPT_UPKEEP_INTERVAL_MS 0 117 | #define CURLE_OBSOLETE51 -1 118 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 61) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 61 && LIBCURL_VERSION_PATCH < 1) 119 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 61) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 61 && LIBCURL_VERSION_PATCH < 0) 120 | #define CURLOPT_TLS13_CIPHERS 0 121 | #define CURLOPT_PROXY_TLS13_CIPHERS 0 122 | #define CURLOPT_DISALLOW_USERNAME_IN_URL 0 123 | #define CURLINFO_TOTAL_TIME_T 0 124 | #define CURLINFO_NAMELOOKUP_TIME_T 0 125 | #define CURLINFO_CONNECT_TIME_T 0 126 | #define CURLINFO_PRETRANSFER_TIME_T 0 127 | #define CURLINFO_STARTTRANSFER_TIME_T 0 128 | #define CURLINFO_REDIRECT_TIME_T 0 129 | #define CURLINFO_APPCONNECT_TIME_T 0 130 | #define CURLAUTH_BEARER 0 131 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 60) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 60 && LIBCURL_VERSION_PATCH < 0) 132 | #define CURLOPT_HAPROXYPROTOCOL 0 133 | #define CURLOPT_DNS_SHUFFLE_ADDRESSES 0 134 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 59) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 59 && LIBCURL_VERSION_PATCH < 0) 135 | #define CURLOPT_TIMEVALUE_LARGE 0 136 | #define CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS 0 137 | #define CURLOPT_RESOLVER_START_FUNCTION 0 138 | #define CURLOPT_RESOLVER_START_DATA 0 139 | #define CURLE_RECURSIVE_API_CALL -1 140 | #define CURLINFO_FILETIME_T 0 141 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 58) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 58 && LIBCURL_VERSION_PATCH < 0) 142 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 57) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 57 && LIBCURL_VERSION_PATCH < 0) 143 | #define CURL_VERSION_BROTLI 0 144 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 56) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 56 && LIBCURL_VERSION_PATCH < 1) 145 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 56) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 56 && LIBCURL_VERSION_PATCH < 0) 146 | #define CURLOPT_SSH_COMPRESSION 0 147 | #define CURLOPT_MIMEPOST 0 148 | #define CURL_VERSION_MULTI_SSL 0 149 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 55) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 55 && LIBCURL_VERSION_PATCH < 1) 150 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 55) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 55 && LIBCURL_VERSION_PATCH < 0) 151 | #define CURLOPT_REQUEST_TARGET 0 152 | #define CURLOPT_SOCKS5_AUTH 0 153 | #define CURLINFO_SIZE_UPLOAD_T 0 154 | #define CURLINFO_SIZE_DOWNLOAD_T 0 155 | #define CURLINFO_SPEED_DOWNLOAD_T 0 156 | #define CURLINFO_SPEED_UPLOAD_T 0 157 | #define CURLINFO_CONTENT_LENGTH_DOWNLOAD_T 0 158 | #define CURLINFO_CONTENT_LENGTH_UPLOAD_T 0 159 | #define CURLAUTH_GSSAPI 0 160 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 54) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 54 && LIBCURL_VERSION_PATCH < 1) 161 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 54) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 54 && LIBCURL_VERSION_PATCH < 0) 162 | #define CURLOPT_SUPPRESS_CONNECT_HEADERS 0 163 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 53) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 53 && LIBCURL_VERSION_PATCH < 1) 164 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 53) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 53 && LIBCURL_VERSION_PATCH < 0) 165 | #define CURLOPT_ABSTRACT_UNIX_SOCKET 0 166 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 52) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 52 && LIBCURL_VERSION_PATCH < 1) 167 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 52) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 52 && LIBCURL_VERSION_PATCH < 0) 168 | #define CURLOPT_PROXY_CAINFO 0 169 | #define CURLOPT_PROXY_CAPATH 0 170 | #define CURLOPT_PROXY_SSL_VERIFYPEER 0 171 | #define CURLOPT_PROXY_SSL_VERIFYHOST 0 172 | #define CURLOPT_PROXY_SSLVERSION 0 173 | #define CURLOPT_PROXY_TLSAUTH_USERNAME 0 174 | #define CURLOPT_PROXY_TLSAUTH_PASSWORD 0 175 | #define CURLOPT_PROXY_TLSAUTH_TYPE 0 176 | #define CURLOPT_PROXY_SSLCERT 0 177 | #define CURLOPT_PROXY_SSLCERTTYPE 0 178 | #define CURLOPT_PROXY_SSLKEY 0 179 | #define CURLOPT_PROXY_SSLKEYTYPE 0 180 | #define CURLOPT_PROXY_KEYPASSWD 0 181 | #define CURLOPT_PROXY_SSL_CIPHER_LIST 0 182 | #define CURLOPT_PROXY_CRLFILE 0 183 | #define CURLOPT_PROXY_SSL_OPTIONS 0 184 | #define CURLOPT_PRE_PROXY 0 185 | #define CURLOPT_PROXY_PINNEDPUBLICKEY 0 186 | #define CURLINFO_PROXY_SSL_VERIFYRESULT 0 187 | #define CURLINFO_PROTOCOL 0 188 | #define CURLINFO_SCHEME 0 189 | #define CURL_VERSION_HTTPS_PROXY 0 190 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 51) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 51 && LIBCURL_VERSION_PATCH < 0) 191 | #define CURLOPT_KEEP_SENDING_ON_ERROR 0 192 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 50) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 50 && LIBCURL_VERSION_PATCH < 3) 193 | #define CURLE_WEIRD_SERVER_REPLY -1 194 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 50) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 50 && LIBCURL_VERSION_PATCH < 2) 195 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 50) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 50 && LIBCURL_VERSION_PATCH < 1) 196 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 50) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 50 && LIBCURL_VERSION_PATCH < 0) 197 | #define CURLINFO_HTTP_VERSION 0 198 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 49) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 49 && LIBCURL_VERSION_PATCH < 1) 199 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 49) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 49 && LIBCURL_VERSION_PATCH < 0) 200 | #define CURLOPT_CONNECT_TO 0 201 | #define CURLOPT_TCP_FASTOPEN 0 202 | #define CURLE_TOO_MANY_REDIRECTS -1 203 | #define CURLE_TELNET_OPTION_SYNTAX -1 204 | #define CURLE_HTTP2_STREAM -1 205 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 48) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 48 && LIBCURL_VERSION_PATCH < 0) 206 | #define CURLOPT_TFTP_NO_OPTIONS 0 207 | #define CURLINFO_TLS_SSL_PTR 0 208 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 47) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 47 && LIBCURL_VERSION_PATCH < 1) 209 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 47) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 47 && LIBCURL_VERSION_PATCH < 0) 210 | #define CURL_VERSION_PSL 0 211 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 46) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 46 && LIBCURL_VERSION_PATCH < 0) 212 | #define CURLOPT_STREAM_WEIGHT 0 213 | #define CURLOPT_STREAM_DEPENDS 0 214 | #define CURLOPT_STREAM_DEPENDS_E 0 215 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 45) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 45 && LIBCURL_VERSION_PATCH < 0) 216 | #define CURLOPT_DEFAULT_PROTOCOL 0 217 | #define CURLINFO_ACTIVESOCKET 0 218 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 44) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 44 && LIBCURL_VERSION_PATCH < 0) 219 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 43) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 43 && LIBCURL_VERSION_PATCH < 0) 220 | #define CURLOPT_PROXY_SERVICE_NAME 0 221 | #define CURLOPT_SERVICE_NAME 0 222 | #define CURLOPT_PIPEWAIT 0 223 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 42) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 42 && LIBCURL_VERSION_PATCH < 1) 224 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 42) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 42 && LIBCURL_VERSION_PATCH < 0) 225 | #define CURLOPT_SSL_FALSESTART 0 226 | #define CURLOPT_PATH_AS_IS 0 227 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 41) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 41 && LIBCURL_VERSION_PATCH < 0) 228 | #define CURLOPT_SSL_VERIFYSTATUS 0 229 | #define CURLE_SSL_INVALIDCERTSTATUS -1 230 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 40) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 40 && LIBCURL_VERSION_PATCH < 0) 231 | #define CURLOPT_UNIX_SOCKET_PATH 0 232 | #define CURL_VERSION_KERBEROS5 0 233 | #define CURL_VERSION_UNIX_SOCKETS 0 234 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 39) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 39 && LIBCURL_VERSION_PATCH < 0) 235 | #define CURLOPT_PINNEDPUBLICKEY 0 236 | #define CURLE_SSL_PINNEDPUBKEYNOTMATCH -1 237 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 38) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 38 && LIBCURL_VERSION_PATCH < 0) 238 | #define CURLE_HTTP2 -1 239 | #define CURL_VERSION_GSSAPI 0 240 | #define CURLAUTH_NEGOTIATE 0 241 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 37) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 37 && LIBCURL_VERSION_PATCH < 1) 242 | #define CURLOPT_OBSOLETE40 0 243 | #define CURLOPT_OBSOLETE72 0 244 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 37) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 37 && LIBCURL_VERSION_PATCH < 0) 245 | #define CURLOPT_PROXYHEADER 0 246 | #define CURLOPT_HEADEROPT 0 247 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 36) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 36 && LIBCURL_VERSION_PATCH < 0) 248 | #define CURLOPT_SSL_ENABLE_NPN 0 249 | #define CURLOPT_SSL_ENABLE_ALPN 0 250 | #define CURLOPT_EXPECT_100_TIMEOUT_MS 0 251 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 35) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 35 && LIBCURL_VERSION_PATCH < 0) 252 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 34) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 34 && LIBCURL_VERSION_PATCH < 0) 253 | #define CURLOPT_LOGIN_OPTIONS 0 254 | #define CURLINFO_TLS_SESSION 0 255 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 33) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 33 && LIBCURL_VERSION_PATCH < 0) 256 | #define CURLOPT_XOAUTH2_BEARER 0 257 | #define CURLOPT_DNS_INTERFACE 0 258 | #define CURLOPT_DNS_LOCAL_IP4 0 259 | #define CURLOPT_DNS_LOCAL_IP6 0 260 | #define CURL_VERSION_HTTP2 0 261 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 32) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 32 && LIBCURL_VERSION_PATCH < 0) 262 | #define CURLOPT_XFERINFODATA 0 263 | #define CURLOPT_XFERINFOFUNCTION 0 264 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 31) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 31 && LIBCURL_VERSION_PATCH < 0) 265 | #define CURLOPT_SASL_IR 0 266 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 30) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 30 && LIBCURL_VERSION_PATCH < 0) 267 | #define CURLE_NO_CONNECTION_AVAILABLE -1 268 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 29) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 29 && LIBCURL_VERSION_PATCH < 0) 269 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 28) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 28 && LIBCURL_VERSION_PATCH < 1) 270 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 28) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 28 && LIBCURL_VERSION_PATCH < 0) 271 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 27) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 27 && LIBCURL_VERSION_PATCH < 0) 272 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 26) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 26 && LIBCURL_VERSION_PATCH < 0) 273 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 25) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 25 && LIBCURL_VERSION_PATCH < 0) 274 | #define CURLOPT_TCP_KEEPALIVE 0 275 | #define CURLOPT_TCP_KEEPIDLE 0 276 | #define CURLOPT_TCP_KEEPINTVL 0 277 | #define CURLOPT_SSL_OPTIONS 0 278 | #define CURLOPT_MAIL_AUTH 0 279 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 24) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 24 && LIBCURL_VERSION_PATCH < 0) 280 | #define CURLOPT_DNS_SERVERS 0 281 | #define CURLOPT_ACCEPTTIMEOUT_MS 0 282 | #define CURLE_FTP_ACCEPT_FAILED -1 283 | #define CURLE_FTP_ACCEPT_TIMEOUT -1 284 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 23) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 23 && LIBCURL_VERSION_PATCH < 1) 285 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 23) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 23 && LIBCURL_VERSION_PATCH < 0) 286 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 22) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 22 && LIBCURL_VERSION_PATCH < 0) 287 | #define CURLOPT_GSSAPI_DELEGATION 0 288 | #define CURL_VERSION_NTLM_WB 0 289 | #define CURLAUTH_NTLM_WB 0 290 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 21) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 21 && LIBCURL_VERSION_PATCH < 7) 291 | #define CURLOPT_CLOSESOCKETFUNCTION 0 292 | #define CURLOPT_CLOSESOCKETDATA 0 293 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 21) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 21 && LIBCURL_VERSION_PATCH < 6) 294 | #define CURLOPT_ACCEPT_ENCODING 0 295 | #define CURLOPT_TRANSFER_ENCODING 0 296 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 21) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 21 && LIBCURL_VERSION_PATCH < 5) 297 | #define CURLE_NOT_BUILT_IN -1 298 | #define CURLE_UNKNOWN_OPTION -1 299 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 21) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 21 && LIBCURL_VERSION_PATCH < 4) 300 | #define CURLOPT_TLSAUTH_USERNAME 0 301 | #define CURLOPT_TLSAUTH_PASSWORD 0 302 | #define CURLOPT_TLSAUTH_TYPE 0 303 | #define CURL_VERSION_TLSAUTH_SRP 0 304 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 21) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 21 && LIBCURL_VERSION_PATCH < 3) 305 | #define CURLOPT_RESOLVE 0 306 | #define CURLAUTH_ONLY 0 307 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 21) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 21 && LIBCURL_VERSION_PATCH < 2) 308 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 21) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 21 && LIBCURL_VERSION_PATCH < 1) 309 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 21) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 21 && LIBCURL_VERSION_PATCH < 0) 310 | #define CURLOPT_WILDCARDMATCH 0 311 | #define CURLOPT_CHUNK_BGN_FUNCTION 0 312 | #define CURLOPT_CHUNK_END_FUNCTION 0 313 | #define CURLOPT_FNMATCH_FUNCTION 0 314 | #define CURLOPT_CHUNK_DATA 0 315 | #define CURLOPT_FNMATCH_DATA 0 316 | #define CURLE_FTP_BAD_FILE_LIST -1 317 | #define CURLE_CHUNK_FAILED -1 318 | #define CURLINFO_PRIMARY_PORT 0 319 | #define CURLINFO_LOCAL_IP 0 320 | #define CURLINFO_LOCAL_PORT 0 321 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 20) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 20 && LIBCURL_VERSION_PATCH < 1) 322 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 20) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 20 && LIBCURL_VERSION_PATCH < 0) 323 | #define CURLOPT_SERVER_RESPONSE_TIMEOUT 0 324 | #define CURLOPT_MAIL_FROM 0 325 | #define CURLOPT_MAIL_RCPT 0 326 | #define CURLOPT_FTP_USE_PRET 0 327 | #define CURLOPT_RTSP_REQUEST 0 328 | #define CURLOPT_RTSP_SESSION_ID 0 329 | #define CURLOPT_RTSP_STREAM_URI 0 330 | #define CURLOPT_RTSP_TRANSPORT 0 331 | #define CURLOPT_RTSP_CLIENT_CSEQ 0 332 | #define CURLOPT_RTSP_SERVER_CSEQ 0 333 | #define CURLOPT_INTERLEAVEDATA 0 334 | #define CURLOPT_INTERLEAVEFUNCTION 0 335 | #define CURLOPT_RTSPHEADER 0 336 | #define CURLE_FTP_PRET_FAILED -1 337 | #define CURLE_RTSP_CSEQ_ERROR -1 338 | #define CURLE_RTSP_SESSION_ERROR -1 339 | #define CURLINFO_RTSP_SESSION_ID 0 340 | #define CURLINFO_RTSP_CLIENT_CSEQ 0 341 | #define CURLINFO_RTSP_SERVER_CSEQ 0 342 | #define CURLINFO_RTSP_CSEQ_RECV 0 343 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 19) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH < 7) 344 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 19) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH < 6) 345 | #define CURLOPT_SSH_KNOWNHOSTS 0 346 | #define CURLOPT_SSH_KEYFUNCTION 0 347 | #define CURLOPT_SSH_KEYDATA 0 348 | #define CURL_VERSION_CURLDEBUG 0 349 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 19) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH < 5) 350 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 19) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH < 4) 351 | #define CURLOPT_NOPROXY 0 352 | #define CURLOPT_TFTP_BLKSIZE 0 353 | #define CURLOPT_SOCKS5_GSSAPI_SERVICE 0 354 | #define CURLOPT_SOCKS5_GSSAPI_NEC 0 355 | #define CURLOPT_PROTOCOLS 0 356 | #define CURLOPT_REDIR_PROTOCOLS 0 357 | #define CURLINFO_CONDITION_UNMET 0 358 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 19) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH < 3) 359 | #define CURLAUTH_DIGEST_IE 0 360 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 19) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH < 2) 361 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 19) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH < 1) 362 | #define CURLOPT_POSTREDIR 0 363 | #define CURLOPT_CERTINFO 0 364 | #define CURLOPT_USERNAME 0 365 | #define CURLOPT_PASSWORD 0 366 | #define CURLOPT_PROXYUSERNAME 0 367 | #define CURLOPT_PROXYPASSWORD 0 368 | #define CURLINFO_CERTINFO 0 369 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 19) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH < 0) 370 | #define CURLOPT_CRLFILE 0 371 | #define CURLOPT_ISSUERCERT 0 372 | #define CURLOPT_ADDRESS_SCOPE 0 373 | #define CURLE_SSL_CRL_BADFILE -1 374 | #define CURLE_SSL_ISSUER_ERROR -1 375 | #define CURLINFO_PRIMARY_IP 0 376 | #define CURLINFO_APPCONNECT_TIME 0 377 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 18) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 18 && LIBCURL_VERSION_PATCH < 2) 378 | #define CURLE_AGAIN -1 379 | #define CURLINFO_REDIRECT_URL 0 380 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 18) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 18 && LIBCURL_VERSION_PATCH < 1) 381 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 18) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 18 && LIBCURL_VERSION_PATCH < 0) 382 | #define CURLOPT_PROXY_TRANSFER_MODE 0 383 | #define CURLOPT_SEEKFUNCTION 0 384 | #define CURLOPT_SEEKDATA 0 385 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 17) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 17 && LIBCURL_VERSION_PATCH < 1) 386 | #define CURLOPT_POST301 0 387 | #define CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 0 388 | #define CURLOPT_OPENSOCKETFUNCTION 0 389 | #define CURLOPT_OPENSOCKETDATA 0 390 | #define CURLOPT_COPYPOSTFIELDS 0 391 | #define CURLE_PEER_FAILED_VERIFICATION -1 392 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 17) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 17 && LIBCURL_VERSION_PATCH < 0) 393 | #define CURLOPT_LOW_SPEED_LIMIT 0 394 | #define CURLOPT_KEYPASSWD 0 395 | #define CURLOPT_DIRLISTONLY 0 396 | #define CURLOPT_APPEND 0 397 | #define CURLOPT_FTP_RESPONSE_TIMEOUT 0 398 | #define CURLOPT_USE_SSL 0 399 | #define CURLE_OBSOLETE4 -1 400 | #define CURLE_REMOTE_ACCESS_DENIED -1 401 | #define CURLE_OBSOLETE10 -1 402 | #define CURLE_OBSOLETE12 -1 403 | #define CURLE_OBSOLETE16 -1 404 | #define CURLE_FTP_COULDNT_SET_TYPE -1 405 | #define CURLE_OBSOLETE20 -1 406 | #define CURLE_QUOTE_ERROR -1 407 | #define CURLE_OBSOLETE24 -1 408 | #define CURLE_OBSOLETE29 -1 409 | #define CURLE_OBSOLETE32 -1 410 | #define CURLE_RANGE_ERROR -1 411 | #define CURLE_OBSOLETE40 -1 412 | #define CURLE_OBSOLETE44 -1 413 | #define CURLE_OBSOLETE46 -1 414 | #define CURLE_OBSOLETE50 -1 415 | #define CURLE_OBSOLETE57 -1 416 | #define CURLE_USE_SSL_FAILED -1 417 | #define CURLE_REMOTE_DISK_FULL -1 418 | #define CURLE_REMOTE_FILE_EXISTS -1 419 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 16) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 16 && LIBCURL_VERSION_PATCH < 4) 420 | #define CURLOPT_KRBLEVEL 0 421 | #define CURLOPT_NEW_FILE_PERMS 0 422 | #define CURLOPT_NEW_DIRECTORY_PERMS 0 423 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 16) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 16 && LIBCURL_VERSION_PATCH < 3) 424 | #define CURLE_UPLOAD_FAILED -1 425 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 16) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 16 && LIBCURL_VERSION_PATCH < 2) 426 | #define CURLOPT_TIMEOUT_MS 0 427 | #define CURLOPT_CONNECTTIMEOUT_MS 0 428 | #define CURLOPT_HTTP_TRANSFER_DECODING 0 429 | #define CURLOPT_HTTP_CONTENT_DECODING 0 430 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 16) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 16 && LIBCURL_VERSION_PATCH < 1) 431 | #define CURLOPT_SSH_AUTH_TYPES 0 432 | #define CURLOPT_SSH_PUBLIC_KEYFILE 0 433 | #define CURLOPT_SSH_PRIVATE_KEYFILE 0 434 | #define CURLOPT_FTP_SSL_CCC 0 435 | #define CURLE_REMOTE_FILE_NOT_FOUND -1 436 | #define CURLE_SSH -1 437 | #define CURLE_SSL_SHUTDOWN_FAILED -1 438 | #if LIBCURL_VERSION_MAJOR < 7 || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR < 16) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR == 16 && LIBCURL_VERSION_PATCH < 0) 439 | #error your version is TOOOOOOOO low 440 | #endif /* 7.16.0 */ 441 | #endif /* 7.16.1 */ 442 | #endif /* 7.16.2 */ 443 | #endif /* 7.16.3 */ 444 | #endif /* 7.16.4 */ 445 | #endif /* 7.17.0 */ 446 | #endif /* 7.17.1 */ 447 | #endif /* 7.18.0 */ 448 | #endif /* 7.18.1 */ 449 | #endif /* 7.18.2 */ 450 | #endif /* 7.19.0 */ 451 | #endif /* 7.19.1 */ 452 | #endif /* 7.19.2 */ 453 | #endif /* 7.19.3 */ 454 | #endif /* 7.19.4 */ 455 | #endif /* 7.19.5 */ 456 | #endif /* 7.19.6 */ 457 | #endif /* 7.19.7 */ 458 | #endif /* 7.20.0 */ 459 | #endif /* 7.20.1 */ 460 | #endif /* 7.21.0 */ 461 | #endif /* 7.21.1 */ 462 | #endif /* 7.21.2 */ 463 | #endif /* 7.21.3 */ 464 | #endif /* 7.21.4 */ 465 | #endif /* 7.21.5 */ 466 | #endif /* 7.21.6 */ 467 | #endif /* 7.21.7 */ 468 | #endif /* 7.22.0 */ 469 | #endif /* 7.23.0 */ 470 | #endif /* 7.23.1 */ 471 | #endif /* 7.24.0 */ 472 | #endif /* 7.25.0 */ 473 | #endif /* 7.26.0 */ 474 | #endif /* 7.27.0 */ 475 | #endif /* 7.28.0 */ 476 | #endif /* 7.28.1 */ 477 | #endif /* 7.29.0 */ 478 | #endif /* 7.30.0 */ 479 | #endif /* 7.31.0 */ 480 | #endif /* 7.32.0 */ 481 | #endif /* 7.33.0 */ 482 | #endif /* 7.34.0 */ 483 | #endif /* 7.35.0 */ 484 | #endif /* 7.36.0 */ 485 | #endif /* 7.37.0 */ 486 | #endif /* 7.37.1 */ 487 | #endif /* 7.38.0 */ 488 | #endif /* 7.39.0 */ 489 | #endif /* 7.40.0 */ 490 | #endif /* 7.41.0 */ 491 | #endif /* 7.42.0 */ 492 | #endif /* 7.42.1 */ 493 | #endif /* 7.43.0 */ 494 | #endif /* 7.44.0 */ 495 | #endif /* 7.45.0 */ 496 | #endif /* 7.46.0 */ 497 | #endif /* 7.47.0 */ 498 | #endif /* 7.47.1 */ 499 | #endif /* 7.48.0 */ 500 | #endif /* 7.49.0 */ 501 | #endif /* 7.49.1 */ 502 | #endif /* 7.50.0 */ 503 | #endif /* 7.50.1 */ 504 | #endif /* 7.50.2 */ 505 | #endif /* 7.50.3 */ 506 | #endif /* 7.51.0 */ 507 | #endif /* 7.52.0 */ 508 | #endif /* 7.52.1 */ 509 | #endif /* 7.53.0 */ 510 | #endif /* 7.53.1 */ 511 | #endif /* 7.54.0 */ 512 | #endif /* 7.54.1 */ 513 | #endif /* 7.55.0 */ 514 | #endif /* 7.55.1 */ 515 | #endif /* 7.56.0 */ 516 | #endif /* 7.56.1 */ 517 | #endif /* 7.57.0 */ 518 | #endif /* 7.58.0 */ 519 | #endif /* 7.59.0 */ 520 | #endif /* 7.60.0 */ 521 | #endif /* 7.61.0 */ 522 | #endif /* 7.61.1 */ 523 | #endif /* 7.62.0 */ 524 | #endif /* 7.63.0 */ 525 | #endif /* 7.64.0 */ 526 | #endif /* 7.64.1 */ 527 | #endif /* 7.65.0 */ 528 | #endif /* 7.65.1 */ 529 | #endif /* 7.65.2 */ 530 | #endif /* 7.65.3 */ 531 | #endif /* 7.66.0 */ 532 | #endif /* 7.67.0 */ 533 | #endif /* 7.68.0 */ 534 | #endif /* 7.69.0 */ 535 | #endif /* 7.69.1 */ 536 | #endif /* 7.70.0 */ 537 | #endif /* 7.71.0 */ 538 | #endif /* 7.71.1 */ 539 | #endif /* 7.72.0 */ 540 | #endif /* 7.73.0 */ 541 | #endif /* 7.74.0 */ 542 | #endif /* 7.75.0 */ 543 | #endif /* 7.76.0 */ 544 | #endif /* 7.76.1 */ 545 | #endif /* 7.77.0 */ 546 | #endif /* 7.78.0 */ 547 | #endif /* 7.79.0 */ 548 | #endif /* 7.79.1 */ 549 | #endif /* 7.80.0 */ 550 | #endif /* 7.81.0 */ 551 | #endif /* 7.82.0 */ 552 | #endif /* 7.83.0 */ 553 | #endif /* 7.83.1 */ 554 | #endif /* 7.84.0 */ 555 | #endif /* 7.85.0 */ 556 | #endif /* 7.86.0 */ 557 | #endif /* 7.87.0 */ 558 | #endif /* 7.88.0 */ 559 | #endif /* 7.88.1 */ 560 | #endif /* 8.0.0 */ 561 | #endif /* 8.0.1 */ 562 | #endif /* 8.1.0 */ 563 | #endif /* 8.1.1 */ 564 | #endif /* 8.1.2 */ 565 | #endif /* 8.2.0 */ 566 | #endif /* 8.2.1 */ 567 | #endif /* 8.3.0 */ 568 | #endif /* 8.4.0 */ 569 | #endif /* 8.5.0 */ 570 | #endif /* 8.6.0 */ 571 | #endif /* 8.7.0 */ 572 | #endif /* 8.7.1 */ 573 | #endif /* 8.8.0 */ 574 | #endif /* 8.9.0 */ 575 | #endif /* 8.9.1 */ 576 | #endif /* 8.10.0 */ 577 | #endif /* 8.10.1 */ 578 | #endif /* 8.11.0 */ 579 | #endif /* 8.11.1 */ 580 | /* generated ends */ 581 | --------------------------------------------------------------------------------