├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── build.zig ├── gyro.zzz ├── libcurl.zig └── src └── main.zig /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: 3 | push: 4 | branches: [ main ] 5 | pull_request: 6 | branches: [ main ] 7 | schedule: 8 | - cron: "0 7 * * *" 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | target: [ 16 | riscv64-linux-gnu, 17 | riscv64-linux-musl, 18 | aarch64-linux-gnu, 19 | aarch64-linux-musl, 20 | aarch64-macos, 21 | i386-linux-gnu, 22 | i386-linux-musl, 23 | i386-windows, 24 | x86_64-linux-gnu, 25 | x86_64-linux-musl, 26 | x86_64-macos, 27 | x86_64-windows-gnu, 28 | ] 29 | mode: [ 30 | debug, 31 | release-safe, 32 | release-fast, 33 | release-small, 34 | ] 35 | steps: 36 | - name: Checkout 37 | uses: actions/checkout@v2 38 | with: 39 | submodules: recursive 40 | fetch-depth: 0 41 | 42 | - name: Setup Zig 43 | uses: goto-bus-stop/setup-zig@v1.3.0 44 | with: 45 | version: master 46 | 47 | - name: Setup Gyro 48 | uses: mattnite/setup-gyro@v1 49 | with: 50 | access-token: ${{ secrets.GITHUB_TOKEN }} 51 | 52 | - name: Build Debug 53 | if: ${{ matrix.mode == 'debug' }} 54 | run: gyro build -Dtarget=${{ matrix.target }} 55 | 56 | - name: Build Release 57 | if: ${{ matrix.mode != 'debug' }} 58 | run: gyro build -D${{ matrix.mode }} -Dtarget=${{ matrix.target }} 59 | 60 | test: 61 | runs-on: ${{ matrix.os }} 62 | strategy: 63 | matrix: 64 | os: [ 65 | ubuntu-latest, 66 | windows-latest, 67 | macos-latest, 68 | ] 69 | mode: [ 70 | debug, 71 | release-safe, 72 | release-fast, 73 | release-small, 74 | ] 75 | steps: 76 | - name: Checkout 77 | uses: actions/checkout@v2 78 | with: 79 | submodules: recursive 80 | fetch-depth: 0 81 | 82 | - name: Setup Zig 83 | uses: goto-bus-stop/setup-zig@v1.3.0 84 | with: 85 | version: master 86 | 87 | - name: Setup Gyro 88 | uses: mattnite/setup-gyro@v1 89 | with: 90 | access-token: ${{ secrets.GITHUB_TOKEN }} 91 | 92 | - name: Build and Test Debug 93 | if: ${{ matrix.mode == 'debug' }} 94 | run: gyro build test 95 | 96 | - name: Build and Test Release 97 | if: ${{ matrix.mode != 'debug' }} 98 | run: gyro build test -D${{ matrix.mode }} 99 | 100 | crosscompile-from-windows: 101 | runs-on: windows-latest 102 | strategy: 103 | matrix: 104 | target: [ 105 | riscv64-linux-gnu, 106 | riscv64-linux-musl, 107 | aarch64-linux-gnu, 108 | aarch64-linux-musl, 109 | aarch64-macos, 110 | i386-linux-gnu, 111 | i386-linux-musl, 112 | x86_64-linux-gnu, 113 | x86_64-linux-musl, 114 | x86_64-macos, 115 | ] 116 | steps: 117 | - name: Checkout 118 | uses: actions/checkout@v2 119 | with: 120 | submodules: recursive 121 | fetch-depth: 0 122 | 123 | - name: Setup Zig 124 | uses: goto-bus-stop/setup-zig@v1.3.0 125 | with: 126 | version: master 127 | 128 | - name: Setup Gyro 129 | uses: mattnite/setup-gyro@v1 130 | with: 131 | access-token: ${{ secrets.GITHUB_TOKEN }} 132 | 133 | - name: Build 134 | run: gyro build 135 | 136 | crosscompile-from-macos: 137 | runs-on: macos-latest 138 | strategy: 139 | matrix: 140 | target: [ 141 | riscv64-linux-gnu, 142 | riscv64-linux-musl, 143 | aarch64-linux-gnu, 144 | aarch64-linux-musl, 145 | i386-linux-gnu, 146 | i386-linux-musl, 147 | i386-windows, 148 | x86_64-linux-gnu, 149 | x86_64-linux-musl, 150 | x86_64-windows-gnu, 151 | ] 152 | steps: 153 | - name: Checkout 154 | uses: actions/checkout@v2 155 | with: 156 | submodules: recursive 157 | fetch-depth: 0 158 | 159 | - name: Setup Zig 160 | uses: goto-bus-stop/setup-zig@v1.3.0 161 | with: 162 | version: master 163 | 164 | - name: Setup Gyro 165 | uses: mattnite/setup-gyro@v1 166 | with: 167 | access-token: ${{ secrets.GITHUB_TOKEN }} 168 | 169 | - name: Build 170 | run: gyro build 171 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | zig-cache 2 | zig-out 3 | deps.zig 4 | gyro.lock 5 | .gyro 6 | build_runner.zig 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "c"] 2 | path = curl 3 | url = https://github.com/curl/curl.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2021 Matthew Knight 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libcurl build package 2 | 3 | [![ci](https://github.com/mattnite/zig-libcurl/actions/workflows/ci.yml/badge.svg)](https://github.com/mattnite/zig-libcurl/actions/workflows/ci.yml) 4 | 5 | ## Like this project? 6 | 7 | If you like this project or other works of mine, please consider [donating to or sponsoring me](https://github.com/sponsors/mattnite) on Github [:heart:](https://github.com/sponsors/mattnite) 8 | 9 | ## How to use 10 | 11 | This repo contains code for your `build.zig` that can statically compile libcurl, as well as some idiomatic Zig bindings for libcurl that you can use in your application. In either case below you will be able to include libcurls header with: 12 | 13 | ```zig 14 | const c = @cImport({ 15 | @cInclude("curl/curl.h"); 16 | }); 17 | ``` 18 | 19 | ### Link and add bindings to your application 20 | 21 | In order to statically link libcurl into your application and access the bindings with a configurable import string: 22 | 23 | ```zig 24 | const libcurl = @import("path/to/libcurl.zig"); 25 | 26 | pub fn build(b: *std.build.Builder) void { 27 | // ... 28 | 29 | const lib = libcurl.create(b, target, optimize); 30 | 31 | const exe = b.addExecutable(.{ 32 | .name = "my-program", 33 | .root_source_file = .{ .path = "src/main.zig" }, 34 | .target = target, 35 | .optimize = optimize, 36 | }); 37 | const exe = b.addExecutable("my-program", "src/main.zig"); 38 | lib.link(exe, .{ .import_name = "curl" }); 39 | } 40 | ``` 41 | 42 | Now code that is part of the `my-program` executable can import the libcurl bindings with `@import("curl")`. 43 | 44 | ### Only link to your application 45 | 46 | In order to just link to the application, all you need to do is omit the `.import_name = "curl"` argument to libcurl's link options: 47 | 48 | ```zig 49 | lib.link(exe, .{}); 50 | ``` 51 | -------------------------------------------------------------------------------- /build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const build_pkgs = @import("deps.zig").build_pkgs; 4 | 5 | const libcurl = @import("libcurl.zig"); 6 | const mbedtls = build_pkgs.mbedtls; 7 | const libssh2 = build_pkgs.libssh2; 8 | const zlib = build_pkgs.zlib; 9 | 10 | pub fn build(b: *std.build.Builder) !void { 11 | const target = b.standardTargetOptions(.{}); 12 | const optimize = b.standardOptimizeOption(.{}); 13 | 14 | const z = zlib.create(b, target, optimize); 15 | const tls = mbedtls.create(b, target, optimize); 16 | const ssh2 = libssh2.create(b, target, optimize); 17 | tls.link(ssh2.step); 18 | 19 | const curl = try libcurl.create(b, target, optimize); 20 | ssh2.link(curl.step); 21 | tls.link(curl.step); 22 | z.link(curl.step, .{}); 23 | curl.step.install(); 24 | 25 | const tests = b.addTest(.{ 26 | .root_source_file = .{ .path = "src/main.zig" }, 27 | .target = target, 28 | .optimize = optimize, 29 | }); 30 | curl.link(tests, .{}); 31 | z.link(tests, .{}); 32 | tls.link(tests); 33 | ssh2.link(tests); 34 | 35 | const test_step = b.step("test", "Run tests"); 36 | test_step.dependOn(&tests.step); 37 | } 38 | -------------------------------------------------------------------------------- /gyro.zzz: -------------------------------------------------------------------------------- 1 | build_deps: 2 | zlib: 3 | git: 4 | url: "https://github.com/mattnite/zig-zlib.git" 5 | ref: main 6 | root: zlib.zig 7 | mbedtls: 8 | git: 9 | url: "https://github.com/mattnite/zig-mbedtls.git" 10 | ref: main 11 | root: mbedtls.zig 12 | libssh2: 13 | git: 14 | url: "https://github.com/mattnite/zig-libssh2.git" 15 | ref: main 16 | root: libssh2.zig 17 | -------------------------------------------------------------------------------- /libcurl.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | fn root() []const u8 { 4 | return std.fs.path.dirname(@src().file) orelse "."; 5 | } 6 | 7 | const root_path = root() ++ "/"; 8 | 9 | pub const include_dir = root_path ++ "curl/include"; 10 | const package_path = root_path ++ "src/main.zig"; 11 | const lib_dir = root_path ++ "curl/lib"; 12 | 13 | pub const Define = struct { 14 | key: []const u8, 15 | value: ?[]const u8, 16 | }; 17 | 18 | pub const Options = struct { 19 | import_name: ?[]const u8 = null, 20 | }; 21 | 22 | pub const Library = struct { 23 | exported_defines: []Define, 24 | step: *std.build.LibExeObjStep, 25 | 26 | pub fn link(self: Library, other: *std.build.LibExeObjStep, opts: Options) void { 27 | for (self.exported_defines) |def| 28 | other.defineCMacro(def.key, def.value); 29 | 30 | other.addIncludePath(include_dir); 31 | other.linkLibrary(self.step); 32 | 33 | if (opts.import_name) |import_name| 34 | other.addAnonymousModule( 35 | import_name, 36 | .{ .source_file = .{ .path = package_path } }, 37 | ); 38 | } 39 | }; 40 | 41 | pub fn create( 42 | b: *std.build.Builder, 43 | target: std.zig.CrossTarget, 44 | optimize: std.builtin.OptimizeMode, 45 | ) !Library { 46 | const ret = b.addStaticLibrary(.{ 47 | .name = "curl", 48 | .target = target, 49 | .optimize = optimize, 50 | }); 51 | ret.addCSourceFiles(srcs, &.{}); 52 | ret.addIncludePath(include_dir); 53 | ret.addIncludePath(lib_dir); 54 | ret.linkLibC(); 55 | 56 | var exported_defines = std.ArrayList(Define).init(b.allocator); 57 | defer exported_defines.deinit(); 58 | 59 | ret.defineCMacro("BUILDING_LIBCURL", null); 60 | 61 | // when not building a shared library 62 | ret.defineCMacro("CURL_STATICLIB", "1"); 63 | try exported_defines.append(.{ .key = "CURL_STATICLIB", .value = "1" }); 64 | 65 | // disables LDAP 66 | ret.defineCMacro("CURL_DISABLE_LDAP", "1"); 67 | 68 | // disables LDAPS 69 | ret.defineCMacro("CURL_DISABLE_LDAPS", "1"); 70 | 71 | // if mbedTLS is enabled 72 | ret.defineCMacro("USE_MBEDTLS", "1"); 73 | 74 | // disables alt-svc 75 | // #undef CURL_DISABLE_ALTSVC 76 | 77 | // disables cookies support 78 | // #undef CURL_DISABLE_COOKIES 79 | 80 | // disables cryptographic authentication 81 | // #undef CURL_DISABLE_CRYPTO_AUTH 82 | 83 | // disables DICT 84 | ret.defineCMacro("CURL_DISABLE_DICT", "1"); 85 | 86 | // disables DNS-over-HTTPS 87 | // #undef CURL_DISABLE_DOH 88 | 89 | // disables FILE 90 | ret.defineCMacro("CURL_DISABLE_FILE", "1"); 91 | 92 | // disables FTP 93 | ret.defineCMacro("CURL_DISABLE_FTP", "1"); 94 | 95 | // disables GOPHER 96 | ret.defineCMacro("CURL_DISABLE_GOPHER", "1"); 97 | 98 | // disables HSTS support 99 | // #undef CURL_DISABLE_HSTS 100 | 101 | // disables HTTP 102 | // #undef CURL_DISABLE_HTTP 103 | 104 | // disables IMAP 105 | ret.defineCMacro("CURL_DISABLE_IMAP", "1"); 106 | 107 | // disables --libcurl option from the curl tool 108 | // #undef CURL_DISABLE_LIBCURL_OPTION 109 | 110 | // disables MIME support 111 | // #undef CURL_DISABLE_MIME 112 | 113 | // disables MQTT 114 | ret.defineCMacro("CURL_DISABLE_MQTT", "1"); 115 | 116 | // disables netrc parser 117 | // #undef CURL_DISABLE_NETRC 118 | 119 | // disables NTLM support 120 | // #undef CURL_DISABLE_NTLM 121 | 122 | // disables date parsing 123 | // #undef CURL_DISABLE_PARSEDATE 124 | 125 | // disables POP3 126 | ret.defineCMacro("CURL_DISABLE_POP3", "1"); 127 | 128 | // disables built-in progress meter 129 | // #undef CURL_DISABLE_PROGRESS_METER 130 | 131 | // disables proxies 132 | // #undef CURL_DISABLE_PROXY 133 | 134 | // disables RTSP 135 | ret.defineCMacro("CURL_DISABLE_RTSP", "1"); 136 | 137 | // disables SMB 138 | ret.defineCMacro("CURL_DISABLE_SMB", "1"); 139 | 140 | // disables SMTP 141 | ret.defineCMacro("CURL_DISABLE_SMTP", "1"); 142 | 143 | // disables use of socketpair for curl_multi_poll 144 | // #undef CURL_DISABLE_SOCKETPAIR 145 | 146 | // disables TELNET 147 | ret.defineCMacro("CURL_DISABLE_TELNET", "1"); 148 | 149 | // disables TFTP 150 | ret.defineCMacro("CURL_DISABLE_TFTP", "1"); 151 | 152 | // disables verbose strings 153 | // #undef CURL_DISABLE_VERBOSE_STRINGS 154 | 155 | // Define to 1 if you have the `ssh2' library (-lssh2). 156 | ret.defineCMacro("HAVE_LIBSSH2", "1"); 157 | 158 | // Define to 1 if you have the header file. 159 | ret.defineCMacro("HAVE_LIBSSH2_H", "1"); 160 | 161 | // if zlib is available 162 | ret.defineCMacro("HAVE_LIBZ", "1"); 163 | 164 | // if you have the zlib.h header file 165 | ret.defineCMacro("HAVE_ZLIB_H", "1"); 166 | 167 | if (target.isWindows()) { 168 | // Define if you want to enable WIN32 threaded DNS lookup 169 | //ret.defineCMacro("USE_THREADS_WIN32", "1"); 170 | 171 | return Library{ .step = ret, .exported_defines = try exported_defines.toOwnedSlice() }; 172 | } 173 | 174 | //ret.defineCMacro("libcurl_EXPORTS", null); 175 | 176 | //ret.defineCMacro("STDC_HEADERS", null); 177 | 178 | // when building libcurl itself 179 | // #undef BUILDING_LIBCURL 180 | 181 | // Location of default ca bundle 182 | // ret.defineCMacro("CURL_CA_BUNDLE", "\"/etc/ssl/certs/ca-certificates.crt\""); 183 | 184 | // define "1" to use built-in ca store of TLS backend 185 | // #undef CURL_CA_FALLBACK 186 | 187 | // Location of default ca path 188 | // ret.defineCMacro("CURL_CA_PATH", "\"/etc/ssl/certs\""); 189 | 190 | // to make a symbol visible 191 | ret.defineCMacro("CURL_EXTERN_SYMBOL", "__attribute__ ((__visibility__ (\"default\"))"); 192 | // Ensure using CURL_EXTERN_SYMBOL is possible 193 | //#ifndef CURL_EXTERN_SYMBOL 194 | //ret.defineCMacro("CURL_EXTERN_SYMBOL 195 | //#endif 196 | 197 | // Allow SMB to work on Windows 198 | // #undef USE_WIN32_CRYPTO 199 | 200 | // Use Windows LDAP implementation 201 | // #undef USE_WIN32_LDAP 202 | 203 | // your Entropy Gathering Daemon socket pathname 204 | // #undef EGD_SOCKET 205 | 206 | // Define if you want to enable IPv6 support 207 | if (!target.isDarwin()) 208 | ret.defineCMacro("ENABLE_IPV6", "1"); 209 | 210 | // Define to 1 if you have the alarm function. 211 | ret.defineCMacro("HAVE_ALARM", "1"); 212 | 213 | // Define to 1 if you have the header file. 214 | ret.defineCMacro("HAVE_ALLOCA_H", "1"); 215 | 216 | // Define to 1 if you have the header file. 217 | ret.defineCMacro("HAVE_ARPA_INET_H", "1"); 218 | 219 | // Define to 1 if you have the header file. 220 | ret.defineCMacro("HAVE_ARPA_TFTP_H", "1"); 221 | 222 | // Define to 1 if you have the header file. 223 | ret.defineCMacro("HAVE_ASSERT_H", "1"); 224 | 225 | // Define to 1 if you have the `basename' function. 226 | ret.defineCMacro("HAVE_BASENAME", "1"); 227 | 228 | // Define to 1 if bool is an available type. 229 | ret.defineCMacro("HAVE_BOOL_T", "1"); 230 | 231 | // Define to 1 if you have the __builtin_available function. 232 | ret.defineCMacro("HAVE_BUILTIN_AVAILABLE", "1"); 233 | 234 | // Define to 1 if you have the clock_gettime function and monotonic timer. 235 | ret.defineCMacro("HAVE_CLOCK_GETTIME_MONOTONIC", "1"); 236 | 237 | // Define to 1 if you have the `closesocket' function. 238 | // #undef HAVE_CLOSESOCKET 239 | 240 | // Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. 241 | // #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 242 | 243 | // Define to 1 if you have the header file. 244 | ret.defineCMacro("HAVE_DLFCN_H", "1"); 245 | 246 | // Define to 1 if you have the header file. 247 | ret.defineCMacro("HAVE_ERRNO_H", "1"); 248 | 249 | // Define to 1 if you have the fcntl function. 250 | ret.defineCMacro("HAVE_FCNTL", "1"); 251 | 252 | // Define to 1 if you have the header file. 253 | ret.defineCMacro("HAVE_FCNTL_H", "1"); 254 | 255 | // Define to 1 if you have a working fcntl O_NONBLOCK function. 256 | ret.defineCMacro("HAVE_FCNTL_O_NONBLOCK", "1"); 257 | 258 | // Define to 1 if you have the freeaddrinfo function. 259 | ret.defineCMacro("HAVE_FREEADDRINFO", "1"); 260 | 261 | // Define to 1 if you have the ftruncate function. 262 | ret.defineCMacro("HAVE_FTRUNCATE", "1"); 263 | 264 | // Define to 1 if you have a working getaddrinfo function. 265 | ret.defineCMacro("HAVE_GETADDRINFO", "1"); 266 | 267 | // Define to 1 if you have the `geteuid' function. 268 | ret.defineCMacro("HAVE_GETEUID", "1"); 269 | 270 | // Define to 1 if you have the `getppid' function. 271 | ret.defineCMacro("HAVE_GETPPID", "1"); 272 | 273 | // Define to 1 if you have the gethostbyname function. 274 | ret.defineCMacro("HAVE_GETHOSTBYNAME", "1"); 275 | 276 | // Define to 1 if you have the gethostbyname_r function. 277 | if (!target.isDarwin()) 278 | ret.defineCMacro("HAVE_GETHOSTBYNAME_R", "1"); 279 | 280 | // gethostbyname_r() takes 3 args 281 | // #undef HAVE_GETHOSTBYNAME_R_3 282 | 283 | // gethostbyname_r() takes 5 args 284 | // #undef HAVE_GETHOSTBYNAME_R_5 285 | 286 | // gethostbyname_r() takes 6 args 287 | ret.defineCMacro("HAVE_GETHOSTBYNAME_R_6", "1"); 288 | 289 | // Define to 1 if you have the gethostname function. 290 | ret.defineCMacro("HAVE_GETHOSTNAME", "1"); 291 | 292 | // Define to 1 if you have a working getifaddrs function. 293 | // #undef HAVE_GETIFADDRS 294 | 295 | // Define to 1 if you have the `getpass_r' function. 296 | // #undef HAVE_GETPASS_R 297 | 298 | // Define to 1 if you have the `getppid' function. 299 | ret.defineCMacro("HAVE_GETPPID", "1"); 300 | 301 | // Define to 1 if you have the `getprotobyname' function. 302 | ret.defineCMacro("HAVE_GETPROTOBYNAME", "1"); 303 | 304 | // Define to 1 if you have the `getpeername' function. 305 | ret.defineCMacro("HAVE_GETPEERNAME", "1"); 306 | 307 | // Define to 1 if you have the `getsockname' function. 308 | ret.defineCMacro("HAVE_GETSOCKNAME", "1"); 309 | 310 | // Define to 1 if you have the `if_nametoindex' function. 311 | ret.defineCMacro("HAVE_IF_NAMETOINDEX", "1"); 312 | 313 | // Define to 1 if you have the `getpwuid' function. 314 | ret.defineCMacro("HAVE_GETPWUID", "1"); 315 | 316 | // Define to 1 if you have the `getpwuid_r' function. 317 | ret.defineCMacro("HAVE_GETPWUID_R", "1"); 318 | 319 | // Define to 1 if you have the `getrlimit' function. 320 | ret.defineCMacro("HAVE_GETRLIMIT", "1"); 321 | 322 | // Define to 1 if you have the `gettimeofday' function. 323 | ret.defineCMacro("HAVE_GETTIMEOFDAY", "1"); 324 | 325 | // Define to 1 if you have a working glibc-style strerror_r function. 326 | // #undef HAVE_GLIBC_STRERROR_R 327 | 328 | // Define to 1 if you have a working gmtime_r function. 329 | ret.defineCMacro("HAVE_GMTIME_R", "1"); 330 | 331 | // if you have the gssapi libraries 332 | // #undef HAVE_GSSAPI 333 | 334 | // Define to 1 if you have the header file. 335 | // #undef HAVE_GSSAPI_GSSAPI_GENERIC_H 336 | 337 | // Define to 1 if you have the header file. 338 | // #undef HAVE_GSSAPI_GSSAPI_H 339 | 340 | // Define to 1 if you have the header file. 341 | // #undef HAVE_GSSAPI_GSSAPI_KRB5_H 342 | 343 | // if you have the GNU gssapi libraries 344 | // #undef HAVE_GSSGNU 345 | 346 | // if you have the Heimdal gssapi libraries 347 | // #undef HAVE_GSSHEIMDAL 348 | 349 | // if you have the MIT gssapi libraries 350 | // #undef HAVE_GSSMIT 351 | 352 | // Define to 1 if you have the `idna_strerror' function. 353 | // #undef HAVE_IDNA_STRERROR 354 | 355 | // Define to 1 if you have the `idn_free' function. 356 | // #undef HAVE_IDN_FREE 357 | 358 | // Define to 1 if you have the header file. 359 | // #undef HAVE_IDN_FREE_H 360 | 361 | // Define to 1 if you have the header file. 362 | ret.defineCMacro("HAVE_IFADDRS_H", "1"); 363 | 364 | // Define to 1 if you have the `inet_addr' function. 365 | ret.defineCMacro("HAVE_INET_ADDR", "1"); 366 | 367 | // Define to 1 if you have a IPv6 capable working inet_ntop function. 368 | // #undef HAVE_INET_NTOP 369 | 370 | // Define to 1 if you have a IPv6 capable working inet_pton function. 371 | ret.defineCMacro("HAVE_INET_PTON", "1"); 372 | 373 | // Define to 1 if symbol `sa_family_t' exists 374 | ret.defineCMacro("HAVE_SA_FAMILY_T", "1"); 375 | 376 | // Define to 1 if symbol `ADDRESS_FAMILY' exists 377 | // #undef HAVE_ADDRESS_FAMILY 378 | 379 | // Define to 1 if you have the header file. 380 | ret.defineCMacro("HAVE_INTTYPES_H", "1"); 381 | 382 | // Define to 1 if you have the ioctl function. 383 | ret.defineCMacro("HAVE_IOCTL", "1"); 384 | 385 | // Define to 1 if you have the ioctlsocket function. 386 | // #undef HAVE_IOCTLSOCKET 387 | 388 | // Define to 1 if you have the IoctlSocket camel case function. 389 | // #undef HAVE_IOCTLSOCKET_CAMEL 390 | 391 | // Define to 1 if you have a working IoctlSocket camel case FIONBIO function. 392 | 393 | // #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO 394 | 395 | // Define to 1 if you have a working ioctlsocket FIONBIO function. 396 | // #undef HAVE_IOCTLSOCKET_FIONBIO 397 | 398 | // Define to 1 if you have a working ioctl FIONBIO function. 399 | ret.defineCMacro("HAVE_IOCTL_FIONBIO", "1"); 400 | 401 | // Define to 1 if you have a working ioctl SIOCGIFADDR function. 402 | ret.defineCMacro("HAVE_IOCTL_SIOCGIFADDR", "1"); 403 | 404 | // Define to 1 if you have the header file. 405 | // #undef HAVE_IO_H 406 | 407 | // if you have the Kerberos4 libraries (including -ldes) 408 | // #undef HAVE_KRB4 409 | 410 | // Define to 1 if you have the `krb_get_our_ip_for_realm' function. 411 | // #undef HAVE_KRB_GET_OUR_IP_FOR_REALM 412 | 413 | // Define to 1 if you have the header file. 414 | // #undef HAVE_KRB_H 415 | 416 | // Define to 1 if you have the lber.h header file. 417 | // #undef HAVE_LBER_H 418 | 419 | // Define to 1 if you have the ldapssl.h header file. 420 | // #undef HAVE_LDAPSSL_H 421 | 422 | // Define to 1 if you have the ldap.h header file. 423 | // #undef HAVE_LDAP_H 424 | 425 | // Use LDAPS implementation 426 | // #undef HAVE_LDAP_SSL 427 | 428 | // Define to 1 if you have the ldap_ssl.h header file. 429 | // #undef HAVE_LDAP_SSL_H 430 | 431 | // Define to 1 if you have the `ldap_url_parse' function. 432 | ret.defineCMacro("HAVE_LDAP_URL_PARSE", "1"); 433 | 434 | // Define to 1 if you have the header file. 435 | ret.defineCMacro("HAVE_LIBGEN_H", "1"); 436 | 437 | // Define to 1 if you have the `idn2' library (-lidn2). 438 | // #undef HAVE_LIBIDN2 439 | 440 | // Define to 1 if you have the idn2.h header file. 441 | ret.defineCMacro("HAVE_IDN2_H", "1"); 442 | 443 | // Define to 1 if you have the `resolv' library (-lresolv). 444 | // #undef HAVE_LIBRESOLV 445 | 446 | // Define to 1 if you have the `resolve' library (-lresolve). 447 | // #undef HAVE_LIBRESOLVE 448 | 449 | // Define to 1 if you have the `socket' library (-lsocket). 450 | // #undef HAVE_LIBSOCKET 451 | 452 | // if brotli is available 453 | // #undef HAVE_BROTLI 454 | 455 | // if zstd is available 456 | // #undef HAVE_ZSTD 457 | 458 | // if your compiler supports LL 459 | ret.defineCMacro("HAVE_LL", "1"); 460 | 461 | // Define to 1 if you have the header file. 462 | ret.defineCMacro("HAVE_LOCALE_H", "1"); 463 | 464 | // Define to 1 if you have a working localtime_r function. 465 | ret.defineCMacro("HAVE_LOCALTIME_R", "1"); 466 | 467 | // Define to 1 if the compiler supports the 'long long' data type. 468 | ret.defineCMacro("HAVE_LONGLONG", "1"); 469 | 470 | // Define to 1 if you have the malloc.h header file. 471 | ret.defineCMacro("HAVE_MALLOC_H", "1"); 472 | 473 | // Define to 1 if you have the header file. 474 | ret.defineCMacro("HAVE_MEMORY_H", "1"); 475 | 476 | // Define to 1 if you have the MSG_NOSIGNAL flag. 477 | if (!target.isDarwin()) 478 | ret.defineCMacro("HAVE_MSG_NOSIGNAL", "1"); 479 | 480 | // Define to 1 if you have the header file. 481 | ret.defineCMacro("HAVE_NETDB_H", "1"); 482 | 483 | // Define to 1 if you have the header file. 484 | ret.defineCMacro("HAVE_NETINET_IN_H", "1"); 485 | 486 | // Define to 1 if you have the header file. 487 | ret.defineCMacro("HAVE_NETINET_TCP_H", "1"); 488 | 489 | // Define to 1 if you have the header file. 490 | if (target.isLinux()) 491 | ret.defineCMacro("HAVE_LINUX_TCP_H", "1"); 492 | 493 | // Define to 1 if you have the header file. 494 | ret.defineCMacro("HAVE_NET_IF_H", "1"); 495 | 496 | // Define to 1 if NI_WITHSCOPEID exists and works. 497 | // #undef HAVE_NI_WITHSCOPEID 498 | 499 | // if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE 500 | // #undef HAVE_OLD_GSSMIT 501 | 502 | // Define to 1 if you have the header file. 503 | // #undef HAVE_PEM_H 504 | 505 | // Define to 1 if you have the `pipe' function. 506 | ret.defineCMacro("HAVE_PIPE", "1"); 507 | 508 | // Define to 1 if you have a working poll function. 509 | ret.defineCMacro("HAVE_POLL", "1"); 510 | 511 | // If you have a fine poll 512 | ret.defineCMacro("HAVE_POLL_FINE", "1"); 513 | 514 | // Define to 1 if you have the header file. 515 | ret.defineCMacro("HAVE_POLL_H", "1"); 516 | 517 | // Define to 1 if you have a working POSIX-style strerror_r function. 518 | ret.defineCMacro("HAVE_POSIX_STRERROR_R", "1"); 519 | 520 | // Define to 1 if you have the header file 521 | ret.defineCMacro("HAVE_PTHREAD_H", "1"); 522 | 523 | // Define to 1 if you have the header file. 524 | ret.defineCMacro("HAVE_PWD_H", "1"); 525 | 526 | // Define to 1 if you have the `RAND_egd' function. 527 | // #undef HAVE_RAND_EGD 528 | 529 | // Define to 1 if you have the `RAND_screen' function. 530 | // #undef HAVE_RAND_SCREEN 531 | 532 | // Define to 1 if you have the `RAND_status' function. 533 | // #undef HAVE_RAND_STATUS 534 | 535 | // Define to 1 if you have the recv function. 536 | ret.defineCMacro("HAVE_RECV", "1"); 537 | 538 | // Define to 1 if you have the recvfrom function. 539 | // #undef HAVE_RECVFROM 540 | 541 | // Define to 1 if you have the select function. 542 | ret.defineCMacro("HAVE_SELECT", "1"); 543 | 544 | // Define to 1 if you have the send function. 545 | ret.defineCMacro("HAVE_SEND", "1"); 546 | 547 | // Define to 1 if you have the 'fsetxattr' function. 548 | ret.defineCMacro("HAVE_FSETXATTR", "1"); 549 | 550 | // fsetxattr() takes 5 args 551 | ret.defineCMacro("HAVE_FSETXATTR_5", "1"); 552 | 553 | // fsetxattr() takes 6 args 554 | // #undef HAVE_FSETXATTR_6 555 | 556 | // Define to 1 if you have the header file. 557 | ret.defineCMacro("HAVE_SETJMP_H", "1"); 558 | 559 | // Define to 1 if you have the `setlocale' function. 560 | ret.defineCMacro("HAVE_SETLOCALE", "1"); 561 | 562 | // Define to 1 if you have the `setmode' function. 563 | // #undef HAVE_SETMODE 564 | 565 | // Define to 1 if you have the `setrlimit' function. 566 | ret.defineCMacro("HAVE_SETRLIMIT", "1"); 567 | 568 | // Define to 1 if you have the setsockopt function. 569 | ret.defineCMacro("HAVE_SETSOCKOPT", "1"); 570 | 571 | // Define to 1 if you have a working setsockopt SO_NONBLOCK function. 572 | // #undef HAVE_SETSOCKOPT_SO_NONBLOCK 573 | 574 | // Define to 1 if you have the sigaction function. 575 | ret.defineCMacro("HAVE_SIGACTION", "1"); 576 | 577 | // Define to 1 if you have the siginterrupt function. 578 | ret.defineCMacro("HAVE_SIGINTERRUPT", "1"); 579 | 580 | // Define to 1 if you have the signal function. 581 | ret.defineCMacro("HAVE_SIGNAL", "1"); 582 | 583 | // Define to 1 if you have the header file. 584 | ret.defineCMacro("HAVE_SIGNAL_H", "1"); 585 | 586 | // Define to 1 if you have the sigsetjmp function or macro. 587 | ret.defineCMacro("HAVE_SIGSETJMP", "1"); 588 | 589 | // Define to 1 if struct sockaddr_in6 has the sin6_scope_id member 590 | ret.defineCMacro("HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID", "1"); 591 | 592 | // Define to 1 if you have the `socket' function. 593 | ret.defineCMacro("HAVE_SOCKET", "1"); 594 | 595 | // Define to 1 if you have the header file. 596 | ret.defineCMacro("HAVE_STDBOOL_H", "1"); 597 | 598 | // Define to 1 if you have the header file. 599 | ret.defineCMacro("HAVE_STDINT_H", "1"); 600 | 601 | // Define to 1 if you have the header file. 602 | ret.defineCMacro("HAVE_STDIO_H", "1"); 603 | 604 | // Define to 1 if you have the header file. 605 | ret.defineCMacro("HAVE_STDLIB_H", "1"); 606 | 607 | // Define to 1 if you have the strcasecmp function. 608 | ret.defineCMacro("HAVE_STRCASECMP", "1"); 609 | 610 | // Define to 1 if you have the strcasestr function. 611 | // #undef HAVE_STRCASESTR 612 | 613 | // Define to 1 if you have the strcmpi function. 614 | // #undef HAVE_STRCMPI 615 | 616 | // Define to 1 if you have the strdup function. 617 | ret.defineCMacro("HAVE_STRDUP", "1"); 618 | 619 | // Define to 1 if you have the strerror_r function. 620 | ret.defineCMacro("HAVE_STRERROR_R", "1"); 621 | 622 | // Define to 1 if you have the stricmp function. 623 | // #undef HAVE_STRICMP 624 | 625 | // Define to 1 if you have the header file. 626 | ret.defineCMacro("HAVE_STRINGS_H", "1"); 627 | 628 | // Define to 1 if you have the header file. 629 | ret.defineCMacro("HAVE_STRING_H", "1"); 630 | 631 | // Define to 1 if you have the strncmpi function. 632 | // #undef HAVE_STRNCMPI 633 | 634 | // Define to 1 if you have the strnicmp function. 635 | // #undef HAVE_STRNICMP 636 | 637 | // Define to 1 if you have the header file. 638 | // #undef HAVE_STROPTS_H 639 | 640 | // Define to 1 if you have the strstr function. 641 | ret.defineCMacro("HAVE_STRSTR", "1"); 642 | 643 | // Define to 1 if you have the strtok_r function. 644 | ret.defineCMacro("HAVE_STRTOK_R", "1"); 645 | 646 | // Define to 1 if you have the strtoll function. 647 | ret.defineCMacro("HAVE_STRTOLL", "1"); 648 | 649 | // if struct sockaddr_storage is defined 650 | ret.defineCMacro("HAVE_STRUCT_SOCKADDR_STORAGE", "1"); 651 | 652 | // Define to 1 if you have the timeval struct. 653 | ret.defineCMacro("HAVE_STRUCT_TIMEVAL", "1"); 654 | 655 | // Define to 1 if you have the header file. 656 | // #undef HAVE_SYS_FILIO_H 657 | 658 | // Define to 1 if you have the header file. 659 | ret.defineCMacro("HAVE_SYS_IOCTL_H", "1"); 660 | 661 | // Define to 1 if you have the header file. 662 | ret.defineCMacro("HAVE_SYS_PARAM_H", "1"); 663 | 664 | // Define to 1 if you have the header file. 665 | ret.defineCMacro("HAVE_SYS_POLL_H", "1"); 666 | 667 | // Define to 1 if you have the header file. 668 | ret.defineCMacro("HAVE_SYS_RESOURCE_H", "1"); 669 | 670 | // Define to 1 if you have the header file. 671 | ret.defineCMacro("HAVE_SYS_SELECT_H", "1"); 672 | 673 | // Define to 1 if you have the header file. 674 | ret.defineCMacro("HAVE_SYS_SOCKET_H", "1"); 675 | 676 | // Define to 1 if you have the header file. 677 | // #undef HAVE_SYS_SOCKIO_H 678 | 679 | // Define to 1 if you have the header file. 680 | ret.defineCMacro("HAVE_SYS_STAT_H", "1"); 681 | 682 | // Define to 1 if you have the header file. 683 | ret.defineCMacro("HAVE_SYS_TIME_H", "1"); 684 | 685 | // Define to 1 if you have the header file. 686 | ret.defineCMacro("HAVE_SYS_TYPES_H", "1"); 687 | 688 | // Define to 1 if you have the header file. 689 | ret.defineCMacro("HAVE_SYS_UIO_H", "1"); 690 | 691 | // Define to 1 if you have the header file. 692 | ret.defineCMacro("HAVE_SYS_UN_H", "1"); 693 | 694 | // Define to 1 if you have the header file. 695 | // #undef HAVE_SYS_UTIME_H 696 | 697 | // Define to 1 if you have the header file. 698 | ret.defineCMacro("HAVE_TERMIOS_H", "1"); 699 | 700 | // Define to 1 if you have the header file. 701 | ret.defineCMacro("HAVE_TERMIO_H", "1"); 702 | 703 | // Define to 1 if you have the header file. 704 | ret.defineCMacro("HAVE_TIME_H", "1"); 705 | 706 | // Define to 1 if you have the header file. 707 | // #undef HAVE_TLD_H 708 | 709 | // Define to 1 if you have the `tld_strerror' function. 710 | // #undef HAVE_TLD_STRERROR 711 | 712 | // Define to 1 if you have the `uname' function. 713 | ret.defineCMacro("HAVE_UNAME", "1"); 714 | 715 | // Define to 1 if you have the header file. 716 | ret.defineCMacro("HAVE_UNISTD_H", "1"); 717 | 718 | // Define to 1 if you have the `utime' function. 719 | ret.defineCMacro("HAVE_UTIME", "1"); 720 | 721 | // Define to 1 if you have the `utimes' function. 722 | ret.defineCMacro("HAVE_UTIMES", "1"); 723 | 724 | // Define to 1 if you have the header file. 725 | ret.defineCMacro("HAVE_UTIME_H", "1"); 726 | 727 | // Define to 1 if compiler supports C99 variadic macro style. 728 | ret.defineCMacro("HAVE_VARIADIC_MACROS_C99", "1"); 729 | 730 | // Define to 1 if compiler supports old gcc variadic macro style. 731 | ret.defineCMacro("HAVE_VARIADIC_MACROS_GCC", "1"); 732 | 733 | // Define to 1 if you have the winber.h header file. 734 | // #undef HAVE_WINBER_H 735 | 736 | // Define to 1 if you have the windows.h header file. 737 | // #undef HAVE_WINDOWS_H 738 | 739 | // Define to 1 if you have the winldap.h header file. 740 | // #undef HAVE_WINLDAP_H 741 | 742 | // Define to 1 if you have the winsock2.h header file. 743 | // #undef HAVE_WINSOCK2_H 744 | 745 | // Define this symbol if your OS supports changing the contents of argv 746 | // #undef HAVE_WRITABLE_ARGV 747 | 748 | // Define to 1 if you have the writev function. 749 | // #undef HAVE_WRITEV 750 | 751 | // Define to 1 if you have the ws2tcpip.h header file. 752 | // #undef HAVE_WS2TCPIP_H 753 | 754 | // Define to 1 if you have the header file. 755 | // #undef HAVE_X509_H 756 | 757 | // Define if you have the header file. 758 | // #undef HAVE_PROCESS_H 759 | 760 | // Define to the sub-directory in which libtool stores uninstalled libraries. 761 | 762 | // #undef LT_OBJDIR 763 | 764 | // If you lack a fine basename() prototype 765 | // #undef NEED_BASENAME_PROTO 766 | 767 | // Define to 1 if you need the lber.h header file even with ldap.h 768 | // #undef NEED_LBER_H 769 | 770 | // Define to 1 if you need the malloc.h header file even with stdlib.h 771 | // #undef NEED_MALLOC_H 772 | 773 | // Define to 1 if _REENTRANT preprocessor symbol must be defined. 774 | // #undef NEED_REENTRANT 775 | 776 | // cpu-machine-OS 777 | ret.defineCMacro("OS", "\"Linux\""); 778 | 779 | // Name of package 780 | // #undef PACKAGE 781 | 782 | // Define to the address where bug reports for this package should be sent. 783 | // #undef PACKAGE_BUGREPORT 784 | 785 | // Define to the full name of this package. 786 | // #undef PACKAGE_NAME 787 | 788 | // Define to the full name and version of this package. 789 | // #undef PACKAGE_STRING 790 | 791 | // Define to the one symbol short name of this package. 792 | // #undef PACKAGE_TARNAME 793 | 794 | // Define to the version of this package. 795 | // #undef PACKAGE_VERSION 796 | 797 | // a suitable file to read random data from 798 | ret.defineCMacro("RANDOM_FILE", "\"/dev/urandom\""); 799 | 800 | // Define to the type of arg 1 for recvfrom. 801 | // #undef RECVFROM_TYPE_ARG1 802 | 803 | // Define to the type pointed by arg 2 for recvfrom. 804 | // #undef RECVFROM_TYPE_ARG2 805 | 806 | // Define to 1 if the type pointed by arg 2 for recvfrom is void. 807 | // #undef RECVFROM_TYPE_ARG2_IS_VOID 808 | 809 | // Define to the type of arg 3 for recvfrom. 810 | // #undef RECVFROM_TYPE_ARG3 811 | 812 | // Define to the type of arg 4 for recvfrom. 813 | // #undef RECVFROM_TYPE_ARG4 814 | 815 | // Define to the type pointed by arg 5 for recvfrom. 816 | // #undef RECVFROM_TYPE_ARG5 817 | 818 | // Define to 1 if the type pointed by arg 5 for recvfrom is void. 819 | // #undef RECVFROM_TYPE_ARG5_IS_VOID 820 | 821 | // Define to the type pointed by arg 6 for recvfrom. 822 | // #undef RECVFROM_TYPE_ARG6 823 | 824 | // Define to 1 if the type pointed by arg 6 for recvfrom is void. 825 | // #undef RECVFROM_TYPE_ARG6_IS_VOID 826 | 827 | // Define to the function return type for recvfrom. 828 | // #undef RECVFROM_TYPE_RETV 829 | 830 | // Define to the type of arg 1 for recv. 831 | ret.defineCMacro("RECV_TYPE_ARG1", "int"); 832 | 833 | // Define to the type of arg 2 for recv. 834 | ret.defineCMacro("RECV_TYPE_ARG2", "void *"); 835 | 836 | // Define to the type of arg 3 for recv. 837 | ret.defineCMacro("RECV_TYPE_ARG3", "size_t"); 838 | 839 | // Define to the type of arg 4 for recv. 840 | ret.defineCMacro("RECV_TYPE_ARG4", "int"); 841 | 842 | // Define to the function return type for recv. 843 | ret.defineCMacro("RECV_TYPE_RETV", "ssize_t"); 844 | 845 | // Define to the type qualifier of arg 5 for select. 846 | // #undef SELECT_QUAL_ARG5 847 | 848 | // Define to the type of arg 1 for select. 849 | // #undef SELECT_TYPE_ARG1 850 | 851 | // Define to the type of args 2, 3 and 4 for select. 852 | // #undef SELECT_TYPE_ARG234 853 | 854 | // Define to the type of arg 5 for select. 855 | // #undef SELECT_TYPE_ARG5 856 | 857 | // Define to the function return type for select. 858 | // #undef SELECT_TYPE_RETV 859 | 860 | // Define to the type qualifier of arg 2 for send. 861 | ret.defineCMacro("SEND_QUAL_ARG2", "const"); 862 | 863 | // Define to the type of arg 1 for send. 864 | ret.defineCMacro("SEND_TYPE_ARG1", "int"); 865 | 866 | // Define to the type of arg 2 for send. 867 | ret.defineCMacro("SEND_TYPE_ARG2", "void *"); 868 | 869 | // Define to the type of arg 3 for send. 870 | ret.defineCMacro("SEND_TYPE_ARG3", "size_t"); 871 | 872 | // Define to the type of arg 4 for send. 873 | ret.defineCMacro("SEND_TYPE_ARG4", "int"); 874 | 875 | // Define to the function return type for send. 876 | ret.defineCMacro("SEND_TYPE_RETV", "ssize_t"); 877 | 878 | // Note: SIZEOF_* variables are fetched with CMake through check_type_size(). 879 | // As per CMake documentation on CheckTypeSize, C preprocessor code is 880 | // generated by CMake into SIZEOF_*_CODE. This is what we use in the 881 | // following statements. 882 | // 883 | // Reference: https://cmake.org/cmake/help/latest/module/CheckTypeSize.html 884 | 885 | // The size of `int', as computed by sizeof. 886 | ret.defineCMacro("SIZEOF_INT", "4"); 887 | 888 | // The size of `short', as computed by sizeof. 889 | ret.defineCMacro("SIZEOF_SHORT", "2"); 890 | 891 | // The size of `long', as computed by sizeof. 892 | ret.defineCMacro("SIZEOF_LONG", "8"); 893 | 894 | // The size of `off_t', as computed by sizeof. 895 | ret.defineCMacro("SIZEOF_OFF_T", "8"); 896 | 897 | // The size of `curl_off_t', as computed by sizeof. 898 | ret.defineCMacro("SIZEOF_CURL_OFF_T", "8"); 899 | 900 | // The size of `size_t', as computed by sizeof. 901 | ret.defineCMacro("SIZEOF_SIZE_T", "8"); 902 | 903 | // The size of `time_t', as computed by sizeof. 904 | ret.defineCMacro("SIZEOF_TIME_T", "8"); 905 | 906 | // Define to 1 if you have the ANSI C header files. 907 | ret.defineCMacro("STDC_HEADERS", "1"); 908 | 909 | // Define to the type of arg 3 for strerror_r. 910 | // #undef STRERROR_R_TYPE_ARG3 911 | 912 | // Define to 1 if you can safely include both and . 913 | ret.defineCMacro("TIME_WITH_SYS_TIME", "1"); 914 | 915 | // Define if you want to enable c-ares support 916 | // #undef USE_ARES 917 | 918 | // Define if you want to enable POSIX threaded DNS lookup 919 | ret.defineCMacro("USE_THREADS_POSIX", "1"); 920 | 921 | // if libSSH2 is in use 922 | ret.defineCMacro("USE_LIBSSH2", "1"); 923 | 924 | // If you want to build curl with the built-in manual 925 | // #undef USE_MANUAL 926 | 927 | // if NSS is enabled 928 | // #undef USE_NSS 929 | 930 | // if you have the PK11_CreateManagedGenericObject function 931 | // #undef HAVE_PK11_CREATEMANAGEDGENERICOBJECT 932 | 933 | // if you want to use OpenLDAP code instead of legacy ldap implementation 934 | // #undef USE_OPENLDAP 935 | 936 | // to enable NGHTTP2 937 | // #undef USE_NGHTTP2 938 | 939 | // to enable NGTCP2 940 | // #undef USE_NGTCP2 941 | 942 | // to enable NGHTTP3 943 | // #undef USE_NGHTTP3 944 | 945 | // to enable quiche 946 | // #undef USE_QUICHE 947 | 948 | // Define to 1 if you have the quiche_conn_set_qlog_fd function. 949 | // #undef HAVE_QUICHE_CONN_SET_QLOG_FD 950 | 951 | // if Unix domain sockets are enabled 952 | ret.defineCMacro("USE_UNIX_SOCKETS", null); 953 | 954 | // Define to 1 if you are building a Windows target with large file support. 955 | // #undef USE_WIN32_LARGE_FILES 956 | 957 | // to enable SSPI support 958 | // #undef USE_WINDOWS_SSPI 959 | 960 | // to enable Windows SSL 961 | // #undef USE_SCHANNEL 962 | 963 | // enable multiple SSL backends 964 | // #undef CURL_WITH_MULTI_SSL 965 | 966 | // Define to 1 if using yaSSL in OpenSSL compatibility mode. 967 | // #undef USE_YASSLEMUL 968 | 969 | // Version number of package 970 | // #undef VERSION 971 | 972 | // Define to 1 if OS is AIX. 973 | //#ifndef _ALL_SOURCE 974 | //# undef _ALL_SOURCE 975 | //#endif 976 | 977 | // Number of bits in a file offset, on hosts where this is settable. 978 | ret.defineCMacro("_FILE_OFFSET_BITS", "64"); 979 | 980 | // Define for large files, on AIX-style hosts. 981 | // #undef _LARGE_FILES 982 | 983 | // define this if you need it to compile thread-safe code 984 | // #undef _THREAD_SAFE 985 | 986 | // Define to empty if `const' does not conform to ANSI C. 987 | // #undef const 988 | 989 | // Type to use in place of in_addr_t when system does not provide it. 990 | // #undef in_addr_t 991 | 992 | // Define to `__inline__' or `__inline' if that's what the C compiler 993 | // calls it, or to nothing if 'inline' is not supported under any name. 994 | //#ifndef __cplusplus 995 | //#undef inline 996 | //#endif 997 | 998 | // Define to `unsigned int' if does not define. 999 | // #undef size_t 1000 | 1001 | // the signed version of size_t 1002 | // #undef ssize_t 1003 | 1004 | // Define to 1 if you have the mach_absolute_time function. 1005 | // #undef HAVE_MACH_ABSOLUTE_TIME 1006 | 1007 | // to enable Windows IDN 1008 | // #undef USE_WIN32_IDN 1009 | 1010 | // to make the compiler know the prototypes of Windows IDN APIs 1011 | // #undef WANT_IDN_PROTOTYPES 1012 | 1013 | return Library{ .step = ret, .exported_defines = try exported_defines.toOwnedSlice() }; 1014 | } 1015 | 1016 | const srcs = &.{ 1017 | root_path ++ "curl/lib/hostcheck.c", 1018 | root_path ++ "curl/lib/curl_gethostname.c", 1019 | root_path ++ "curl/lib/strerror.c", 1020 | root_path ++ "curl/lib/strdup.c", 1021 | root_path ++ "curl/lib/asyn-ares.c", 1022 | root_path ++ "curl/lib/pop3.c", 1023 | root_path ++ "curl/lib/bufref.c", 1024 | root_path ++ "curl/lib/rename.c", 1025 | root_path ++ "curl/lib/nwlib.c", 1026 | root_path ++ "curl/lib/file.c", 1027 | root_path ++ "curl/lib/curl_gssapi.c", 1028 | root_path ++ "curl/lib/ldap.c", 1029 | root_path ++ "curl/lib/socketpair.c", 1030 | root_path ++ "curl/lib/system_win32.c", 1031 | root_path ++ "curl/lib/http_aws_sigv4.c", 1032 | root_path ++ "curl/lib/content_encoding.c", 1033 | root_path ++ "curl/lib/vquic/ngtcp2.c", 1034 | root_path ++ "curl/lib/vquic/quiche.c", 1035 | root_path ++ "curl/lib/vquic/vquic.c", 1036 | root_path ++ "curl/lib/ftp.c", 1037 | root_path ++ "curl/lib/curl_ntlm_wb.c", 1038 | root_path ++ "curl/lib/curl_ntlm_core.c", 1039 | root_path ++ "curl/lib/hostip.c", 1040 | root_path ++ "curl/lib/urlapi.c", 1041 | root_path ++ "curl/lib/curl_get_line.c", 1042 | root_path ++ "curl/lib/vtls/mesalink.c", 1043 | root_path ++ "curl/lib/vtls/mbedtls_threadlock.c", 1044 | root_path ++ "curl/lib/vtls/nss.c", 1045 | root_path ++ "curl/lib/vtls/gskit.c", 1046 | root_path ++ "curl/lib/vtls/wolfssl.c", 1047 | root_path ++ "curl/lib/vtls/keylog.c", 1048 | root_path ++ "curl/lib/vtls/rustls.c", 1049 | root_path ++ "curl/lib/vtls/vtls.c", 1050 | root_path ++ "curl/lib/vtls/gtls.c", 1051 | root_path ++ "curl/lib/vtls/schannel.c", 1052 | root_path ++ "curl/lib/vtls/schannel_verify.c", 1053 | root_path ++ "curl/lib/vtls/sectransp.c", 1054 | root_path ++ "curl/lib/vtls/openssl.c", 1055 | root_path ++ "curl/lib/vtls/mbedtls.c", 1056 | root_path ++ "curl/lib/vtls/bearssl.c", 1057 | root_path ++ "curl/lib/parsedate.c", 1058 | root_path ++ "curl/lib/sendf.c", 1059 | root_path ++ "curl/lib/altsvc.c", 1060 | root_path ++ "curl/lib/krb5.c", 1061 | root_path ++ "curl/lib/curl_rtmp.c", 1062 | root_path ++ "curl/lib/curl_ctype.c", 1063 | root_path ++ "curl/lib/inet_pton.c", 1064 | root_path ++ "curl/lib/pingpong.c", 1065 | root_path ++ "curl/lib/mime.c", 1066 | root_path ++ "curl/lib/vauth/krb5_gssapi.c", 1067 | root_path ++ "curl/lib/vauth/krb5_sspi.c", 1068 | root_path ++ "curl/lib/vauth/spnego_sspi.c", 1069 | root_path ++ "curl/lib/vauth/digest.c", 1070 | root_path ++ "curl/lib/vauth/ntlm_sspi.c", 1071 | root_path ++ "curl/lib/vauth/vauth.c", 1072 | root_path ++ "curl/lib/vauth/gsasl.c", 1073 | root_path ++ "curl/lib/vauth/cram.c", 1074 | root_path ++ "curl/lib/vauth/oauth2.c", 1075 | root_path ++ "curl/lib/vauth/digest_sspi.c", 1076 | root_path ++ "curl/lib/vauth/cleartext.c", 1077 | root_path ++ "curl/lib/vauth/spnego_gssapi.c", 1078 | root_path ++ "curl/lib/vauth/ntlm.c", 1079 | root_path ++ "curl/lib/version_win32.c", 1080 | root_path ++ "curl/lib/multi.c", 1081 | root_path ++ "curl/lib/http_ntlm.c", 1082 | root_path ++ "curl/lib/curl_sspi.c", 1083 | root_path ++ "curl/lib/md5.c", 1084 | root_path ++ "curl/lib/dict.c", 1085 | root_path ++ "curl/lib/http.c", 1086 | root_path ++ "curl/lib/curl_des.c", 1087 | root_path ++ "curl/lib/memdebug.c", 1088 | root_path ++ "curl/lib/non-ascii.c", 1089 | root_path ++ "curl/lib/transfer.c", 1090 | root_path ++ "curl/lib/inet_ntop.c", 1091 | root_path ++ "curl/lib/slist.c", 1092 | root_path ++ "curl/lib/http_negotiate.c", 1093 | root_path ++ "curl/lib/http_digest.c", 1094 | root_path ++ "curl/lib/vssh/wolfssh.c", 1095 | root_path ++ "curl/lib/vssh/libssh.c", 1096 | root_path ++ "curl/lib/vssh/libssh2.c", 1097 | root_path ++ "curl/lib/hsts.c", 1098 | root_path ++ "curl/lib/escape.c", 1099 | root_path ++ "curl/lib/hostsyn.c", 1100 | root_path ++ "curl/lib/speedcheck.c", 1101 | root_path ++ "curl/lib/asyn-thread.c", 1102 | root_path ++ "curl/lib/curl_addrinfo.c", 1103 | root_path ++ "curl/lib/nwos.c", 1104 | root_path ++ "curl/lib/tftp.c", 1105 | root_path ++ "curl/lib/version.c", 1106 | root_path ++ "curl/lib/rand.c", 1107 | root_path ++ "curl/lib/psl.c", 1108 | root_path ++ "curl/lib/imap.c", 1109 | root_path ++ "curl/lib/mqtt.c", 1110 | root_path ++ "curl/lib/share.c", 1111 | root_path ++ "curl/lib/doh.c", 1112 | root_path ++ "curl/lib/curl_range.c", 1113 | root_path ++ "curl/lib/openldap.c", 1114 | root_path ++ "curl/lib/getinfo.c", 1115 | root_path ++ "curl/lib/select.c", 1116 | root_path ++ "curl/lib/base64.c", 1117 | root_path ++ "curl/lib/curl_sasl.c", 1118 | root_path ++ "curl/lib/curl_endian.c", 1119 | root_path ++ "curl/lib/connect.c", 1120 | root_path ++ "curl/lib/fileinfo.c", 1121 | root_path ++ "curl/lib/telnet.c", 1122 | root_path ++ "curl/lib/x509asn1.c", 1123 | root_path ++ "curl/lib/conncache.c", 1124 | root_path ++ "curl/lib/strcase.c", 1125 | root_path ++ "curl/lib/if2ip.c", 1126 | root_path ++ "curl/lib/gopher.c", 1127 | root_path ++ "curl/lib/ftplistparser.c", 1128 | root_path ++ "curl/lib/setopt.c", 1129 | root_path ++ "curl/lib/idn_win32.c", 1130 | root_path ++ "curl/lib/strtoofft.c", 1131 | root_path ++ "curl/lib/hmac.c", 1132 | root_path ++ "curl/lib/getenv.c", 1133 | root_path ++ "curl/lib/smb.c", 1134 | root_path ++ "curl/lib/dotdot.c", 1135 | root_path ++ "curl/lib/curl_threads.c", 1136 | root_path ++ "curl/lib/md4.c", 1137 | root_path ++ "curl/lib/easygetopt.c", 1138 | root_path ++ "curl/lib/curl_fnmatch.c", 1139 | root_path ++ "curl/lib/sha256.c", 1140 | root_path ++ "curl/lib/cookie.c", 1141 | root_path ++ "curl/lib/amigaos.c", 1142 | root_path ++ "curl/lib/progress.c", 1143 | root_path ++ "curl/lib/nonblock.c", 1144 | root_path ++ "curl/lib/llist.c", 1145 | root_path ++ "curl/lib/hostip6.c", 1146 | root_path ++ "curl/lib/dynbuf.c", 1147 | root_path ++ "curl/lib/warnless.c", 1148 | root_path ++ "curl/lib/hostasyn.c", 1149 | root_path ++ "curl/lib/http_chunks.c", 1150 | root_path ++ "curl/lib/wildcard.c", 1151 | root_path ++ "curl/lib/strtok.c", 1152 | root_path ++ "curl/lib/curl_memrchr.c", 1153 | root_path ++ "curl/lib/rtsp.c", 1154 | root_path ++ "curl/lib/http2.c", 1155 | root_path ++ "curl/lib/socks.c", 1156 | root_path ++ "curl/lib/curl_path.c", 1157 | root_path ++ "curl/lib/curl_multibyte.c", 1158 | root_path ++ "curl/lib/http_proxy.c", 1159 | root_path ++ "curl/lib/formdata.c", 1160 | root_path ++ "curl/lib/netrc.c", 1161 | root_path ++ "curl/lib/socks_sspi.c", 1162 | root_path ++ "curl/lib/mprintf.c", 1163 | root_path ++ "curl/lib/easyoptions.c", 1164 | root_path ++ "curl/lib/easy.c", 1165 | root_path ++ "curl/lib/c-hyper.c", 1166 | root_path ++ "curl/lib/hostip4.c", 1167 | root_path ++ "curl/lib/timeval.c", 1168 | root_path ++ "curl/lib/smtp.c", 1169 | root_path ++ "curl/lib/splay.c", 1170 | root_path ++ "curl/lib/socks_gssapi.c", 1171 | root_path ++ "curl/lib/url.c", 1172 | root_path ++ "curl/lib/hash.c", 1173 | }; 1174 | -------------------------------------------------------------------------------- /src/main.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const testing = std.testing; 3 | 4 | pub const c = @cImport({ 5 | @cInclude("curl/curl.h"); 6 | }); 7 | 8 | pub fn globalInit() Error!void { 9 | return tryCurl(c.curl_global_init(c.CURL_GLOBAL_ALL)); 10 | } 11 | 12 | pub fn globalCleanup() void { 13 | c.curl_global_cleanup(); 14 | } 15 | 16 | pub const XferInfoFn = c.curl_xferinfo_callback; 17 | pub const WriteFn = c.curl_write_callback; 18 | pub const ReadFn = c.curl_read_callback; 19 | pub const Offset = c.curl_off_t; 20 | 21 | /// if you set this as a write function, you must set write data to a fifo of the same type 22 | pub fn writeToFifo(comptime FifoType: type) WriteFn { 23 | return struct { 24 | fn writeFn(ptr: ?[*]u8, size: usize, nmemb: usize, data: ?*anyopaque) callconv(.C) usize { 25 | _ = size; 26 | var slice = (ptr orelse return 0)[0..nmemb]; 27 | const fifo: *FifoType = 28 | @ptrCast(@alignCast(data orelse return 0)); 29 | 30 | fifo.writer().writeAll(slice) catch return 0; 31 | return nmemb; 32 | } 33 | }.writeFn; 34 | } 35 | 36 | /// if you set this as a read function, you must set read data to an FBS of the same type 37 | pub fn readFromFbs(comptime FbsType: type) ReadFn { 38 | const BufferType = switch (FbsType) { 39 | std.io.FixedBufferStream([]u8) => []u8, 40 | std.io.FixedBufferStream([]const u8) => []const u8, 41 | else => @compileError("std.io.FixedBufferStream can only have []u8 or []const u8 buffer type"), 42 | }; 43 | return struct { 44 | fn readFn(buffer: ?[*]u8, size: usize, nitems: usize, data: ?*anyopaque) callconv(.C) usize { 45 | const to = (buffer orelse return c.CURL_READFUNC_ABORT)[0 .. size * nitems]; 46 | var fbs: *std.io.FixedBufferStream(BufferType) = 47 | @ptrCast(@alignCast(data orelse return c.CURL_READFUNC_ABORT)); 48 | 49 | return fbs.read(to) catch |err| blk: { 50 | std.log.err("get fbs read error: {s}", .{@errorName(err)}); 51 | break :blk c.CURL_READFUNC_ABORT; 52 | }; 53 | } 54 | }.readFn; 55 | } 56 | 57 | pub const Easy = opaque { 58 | pub fn init() Error!*Easy { 59 | return @as(?*Easy, @ptrCast(c.curl_easy_init())) orelse error.FailedInit; 60 | } 61 | 62 | pub const deinit = cleanup; 63 | pub fn cleanup(self: *Easy) void { 64 | c.curl_easy_cleanup(self); 65 | } 66 | 67 | pub fn setUrl(self: *Easy, url: [:0]const u8) Error!void { 68 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_URL, url.ptr)); 69 | } 70 | 71 | pub fn setFollowLocation(self: *Easy, val: bool) Error!void { 72 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_FOLLOWLOCATION, @as(c_ulong, if (val) 1 else 0))); 73 | } 74 | 75 | pub fn setVerbose(self: *Easy, val: bool) Error!void { 76 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_VERBOSE, @as(c_ulong, if (val) 1 else 0))); 77 | } 78 | 79 | pub fn setSslVerifyPeer(self: *Easy, val: bool) Error!void { 80 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_SSL_VERIFYPEER, @as(c_ulong, if (val) 1 else 0))); 81 | } 82 | 83 | pub fn setAcceptEncodingGzip(self: *Easy) Error!void { 84 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_ACCEPT_ENCODING, "gzip")); 85 | } 86 | 87 | pub fn setReadFn(self: *Easy, read: ReadFn) Error!void { 88 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_READFUNCTION, read)); 89 | } 90 | 91 | pub fn setReadData(self: *Easy, data: *anyopaque) Error!void { 92 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_READDATA, data)); 93 | } 94 | 95 | pub fn setWriteFn(self: *Easy, write: WriteFn) Error!void { 96 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_WRITEFUNCTION, write)); 97 | } 98 | 99 | pub fn setWriteData(self: *Easy, data: *anyopaque) Error!void { 100 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_WRITEDATA, data)); 101 | } 102 | 103 | pub fn setNoProgress(self: *Easy, val: bool) Error!void { 104 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_NOPROGRESS, @as(c_ulong, if (val) 1 else 0))); 105 | } 106 | 107 | pub fn setXferInfoFn(self: *Easy, xfer: XferInfoFn) Error!void { 108 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_XFERINFOFUNCTION, xfer)); 109 | } 110 | 111 | pub fn setXferInfoData(self: *Easy, data: *anyopaque) Error!void { 112 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_XFERINFODATA, data)); 113 | } 114 | 115 | pub fn setErrorBuffer(self: *Easy, data: *[c.CURL_ERROR_SIZE]u8) Error!void { 116 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_XFERINFODATA, data)); 117 | } 118 | 119 | pub fn setHeaders(self: *Easy, headers: HeaderList) Error!void { 120 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_HTTPHEADER, headers.inner)); 121 | } 122 | 123 | pub fn setPost(self: *Easy) Error!void { 124 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_POST, @as(c_ulong, 1))); 125 | } 126 | 127 | pub fn setPostFields(self: *Easy, data: *anyopaque) Error!void { 128 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_POSTFIELDS, @intFromPtr(data))); 129 | } 130 | 131 | pub fn setPostFieldSize(self: *Easy, size: usize) Error!void { 132 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_POSTFIELDSIZE, @as(c_ulong, @intCast(size)))); 133 | } 134 | 135 | pub fn setTimeout(self: *Easy, duration_seconds: c_ulong) Error!void { 136 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_TIMEOUT, duration_seconds)); 137 | } 138 | 139 | pub fn setTimeoutMs(self: *Easy, duration_ms: c_ulong) Error!void { 140 | return tryCurl(c.curl_easy_setopt(self, c.CURLOPT_TIMEOUT_MS, duration_ms)); 141 | } 142 | 143 | pub fn setopt(self: *Easy, option: c.CURLoption, arg: c_ulong) Error!void { 144 | return tryCurl(c.curl_easy_setopt(self, option, arg)); 145 | } 146 | 147 | pub fn perform(self: *Easy) Error!void { 148 | return tryCurl(c.curl_easy_perform(self)); 149 | } 150 | 151 | pub fn getResponseCode(self: *Easy) Error!isize { 152 | var code: isize = 0; 153 | try tryCurl(c.curl_easy_getinfo(self, c.CURLINFO_RESPONSE_CODE, &code)); 154 | return code; 155 | } 156 | }; 157 | 158 | fn emptyWrite(ptr: ?[*]u8, size: usize, nmemb: usize, data: ?*anyopaque) callconv(.C) usize { 159 | _ = ptr; 160 | _ = data; 161 | _ = size; 162 | 163 | return nmemb; 164 | } 165 | 166 | test "https get" { 167 | const Fifo = std.fifo.LinearFifo(u8, .{ .Dynamic = {} }); 168 | 169 | try globalInit(); 170 | defer globalCleanup(); 171 | 172 | var fifo = Fifo.init(std.testing.allocator); 173 | defer fifo.deinit(); 174 | 175 | var easy = try Easy.init(); 176 | defer easy.cleanup(); 177 | 178 | try easy.setUrl("https://httpbin.org/get"); 179 | try easy.setSslVerifyPeer(false); 180 | try easy.setWriteFn(writeToFifo(Fifo)); 181 | try easy.setWriteData(&fifo); 182 | try easy.setVerbose(true); 183 | try easy.perform(); 184 | const code = try easy.getResponseCode(); 185 | 186 | try std.testing.expectEqual(@as(isize, 200), code); 187 | } 188 | 189 | test "https get gzip encoded" { 190 | const Fifo = std.fifo.LinearFifo(u8, .{ .Dynamic = {} }); 191 | 192 | try globalInit(); 193 | defer globalCleanup(); 194 | 195 | var fifo = Fifo.init(std.testing.allocator); 196 | defer fifo.deinit(); 197 | 198 | var easy = try Easy.init(); 199 | defer easy.cleanup(); 200 | 201 | try easy.setUrl("http://httpbin.org/gzip"); 202 | try easy.setSslVerifyPeer(false); 203 | try easy.setAcceptEncodingGzip(); 204 | try easy.setWriteFn(writeToFifo(Fifo)); 205 | try easy.setWriteData(&fifo); 206 | try easy.setVerbose(true); 207 | try easy.perform(); 208 | const code = try easy.getResponseCode(); 209 | 210 | try std.testing.expectEqual(@as(isize, 200), code); 211 | } 212 | 213 | test "https post" { 214 | try globalInit(); 215 | defer globalCleanup(); 216 | 217 | var easy = try Easy.init(); 218 | defer easy.cleanup(); 219 | 220 | const payload = "this is a payload"; 221 | var fbs = std.io.fixedBufferStream(payload); 222 | fbs.pos = payload.len; 223 | 224 | try easy.setUrl("https://httpbin.org/post"); 225 | try easy.setPost(); 226 | try easy.setSslVerifyPeer(false); 227 | try easy.setWriteFn(emptyWrite); 228 | try easy.setReadFn(readFromFbs(@TypeOf(fbs))); 229 | try easy.setReadData(&fbs); 230 | try easy.setVerbose(true); 231 | try easy.perform(); 232 | const code = try easy.getResponseCode(); 233 | 234 | try std.testing.expectEqual(@as(isize, 200), code); 235 | } 236 | 237 | pub const Url = opaque { 238 | pub fn init() UrlError!*Url { 239 | return @as(?*Url, @ptrCast(c.curl_url())) orelse error.FailedInit; 240 | } 241 | 242 | pub fn cleanup(self: *Url) void { 243 | c.curl_url_cleanup(@as(*c.CURLU, @ptrCast(self))); 244 | } 245 | 246 | pub fn set(self: *Url, url: [:0]const u8) UrlError!void { 247 | return tryCurlUrl(c.curl_url_set(@as(*c.CURLU, @ptrCast(self)), c.CURLUPART_URL, url.ptr, 0)); 248 | } 249 | 250 | pub fn getHost(self: *Url) UrlError![*:0]u8 { 251 | var host: ?[*:0]u8 = undefined; 252 | try tryCurlUrl(c.curl_url_get(@as(*c.CURLU, @ptrCast(self)), c.CURLUPART_HOST, &host, 0)); 253 | return host.?; 254 | } 255 | 256 | pub fn getPath(self: *Url) UrlError![*:0]u8 { 257 | var path: ?[*:0]u8 = undefined; 258 | try tryCurlUrl(c.curl_url_get(@as(*c.CURLU, @ptrCast(self)), c.CURLUPART_PATH, &path, 0)); 259 | return path.?; 260 | } 261 | 262 | pub fn getScheme(self: *Url) UrlError![*:0]u8 { 263 | var scheme: ?[*:0]u8 = undefined; 264 | try tryCurlUrl(c.curl_url_get(@as(*c.CURLU, @ptrCast(self)), c.CURLUPART_SCHEME, &scheme, 0)); 265 | return scheme.?; 266 | } 267 | 268 | pub fn getPort(self: *Url) UrlError![*:0]u8 { 269 | var port: ?[*:0]u8 = undefined; 270 | try tryCurlUrl(c.curl_url_get(@as(*c.CURLU, @ptrCast(self)), c.CURLUPART_PORT, &port, 0)); 271 | return port.?; 272 | } 273 | 274 | pub fn getQuery(self: *Url) UrlError![*:0]u8 { 275 | var query: ?[*:0]u8 = undefined; 276 | try tryCurlUrl(c.curl_url_get(@as(*c.CURLU, @ptrCast(self)), c.CURLUPART_QUERY, &query, 0)); 277 | return query.?; 278 | } 279 | 280 | fn tryCurlUrl(code: c.CURLUcode) UrlError!void { 281 | if (code != c.CURLUE_OK) 282 | return errorFromCurlUrl(code); 283 | } 284 | }; 285 | 286 | test "parse url" { 287 | const url = try Url.init(); 288 | defer url.cleanup(); 289 | 290 | try url.set("https://arst.com:80/blarg/foo.git?what=yes&please=no"); 291 | 292 | const scheme = try url.getScheme(); 293 | try std.testing.expectEqualStrings("https", std.mem.span(scheme)); 294 | 295 | const host = try url.getHost(); 296 | try std.testing.expectEqualStrings("arst.com", std.mem.span(host)); 297 | 298 | const port = try url.getPort(); 299 | try std.testing.expectEqualStrings("80", std.mem.span(port)); 300 | 301 | const path = try url.getPath(); 302 | try std.testing.expectEqualStrings("/blarg/foo.git", std.mem.span(path)); 303 | 304 | const query = try url.getQuery(); 305 | try std.testing.expectEqualStrings("what=yes&please=no", std.mem.span(query)); 306 | } 307 | 308 | pub const HeaderList = struct { 309 | inner: ?*c.curl_slist, 310 | 311 | pub fn init() HeaderList { 312 | return HeaderList{ 313 | .inner = null, 314 | }; 315 | } 316 | 317 | pub const deinit = freeAll; 318 | pub fn freeAll(self: @This()) void { 319 | c.curl_slist_free_all(self.inner); 320 | } 321 | 322 | pub fn append(self: *HeaderList, entry: [:0]const u8) !void { 323 | if (c.curl_slist_append(self.inner, entry.ptr)) |list| { 324 | self.inner = list; 325 | } else return error.CurlHeadersAppend; 326 | } 327 | }; 328 | 329 | test "headers" { 330 | try globalInit(); 331 | defer globalCleanup(); 332 | 333 | var headers = HeaderList.init(); 334 | defer headers.freeAll(); 335 | 336 | // removes a header curl would put in for us 337 | try headers.append("Accept:"); 338 | 339 | // a custom header 340 | try headers.append("MyCustomHeader: bruh"); 341 | 342 | // a header with no value, note the semicolon 343 | try headers.append("ThisHasNoValue;"); 344 | 345 | var easy = try Easy.init(); 346 | defer easy.cleanup(); 347 | 348 | try easy.setUrl("https://httpbin.org/get"); 349 | try easy.setSslVerifyPeer(false); 350 | try easy.setWriteFn(emptyWrite); 351 | try easy.setVerbose(true); 352 | try easy.setHeaders(headers); 353 | try easy.perform(); 354 | const code = try easy.getResponseCode(); 355 | 356 | try std.testing.expectEqual(@as(isize, 200), code); 357 | } 358 | 359 | pub const UrlError = error{ 360 | FailedInit, 361 | BadHandle, 362 | BadPartpointer, 363 | MalformedInput, 364 | BadPortNumber, 365 | UnsupportedScheme, 366 | UrlDecode, 367 | OutOfMemory, 368 | UserNotAllowed, 369 | UnknownPart, 370 | NoScheme, 371 | NoUser, 372 | NoPassword, 373 | NoOptions, 374 | NoHost, 375 | NoPort, 376 | NoQuery, 377 | NoFragment, 378 | UnknownErrorCode, 379 | }; 380 | 381 | pub const Error = error{ 382 | UnsupportedProtocol, 383 | FailedInit, 384 | UrlMalformat, 385 | NotBuiltIn, 386 | CouldntResolveProxy, 387 | CouldntResolveHost, 388 | CounldntConnect, 389 | WeirdServerReply, 390 | RemoteAccessDenied, 391 | FtpAcceptFailed, 392 | FtpWeirdPassReply, 393 | FtpAcceptTimeout, 394 | FtpWeirdPasvReply, 395 | FtpWeird227Format, 396 | FtpCantGetHost, 397 | Http2, 398 | FtpCouldntSetType, 399 | PartialFile, 400 | FtpCouldntRetrFile, 401 | Obsolete20, 402 | QuoteError, 403 | HttpReturnedError, 404 | WriteError, 405 | Obsolete24, 406 | UploadFailed, 407 | ReadError, 408 | OutOfMemory, 409 | OperationTimeout, 410 | Obsolete29, 411 | FtpPortFailed, 412 | FtpCouldntUseRest, 413 | Obsolete32, 414 | RangeError, 415 | HttpPostError, 416 | SslConnectError, 417 | BadDownloadResume, 418 | FileCouldntReadFile, 419 | LdapCannotBind, 420 | LdapSearchFailed, 421 | Obsolete40, 422 | FunctionNotFound, 423 | AbortByCallback, 424 | BadFunctionArgument, 425 | Obsolete44, 426 | InterfaceFailed, 427 | Obsolete46, 428 | TooManyRedirects, 429 | UnknownOption, 430 | SetoptOptionSyntax, 431 | Obsolete50, 432 | Obsolete51, 433 | GotNothing, 434 | SslEngineNotfound, 435 | SslEngineSetfailed, 436 | SendError, 437 | RecvError, 438 | Obsolete57, 439 | SslCertproblem, 440 | SslCipher, 441 | PeerFailedVerification, 442 | BadContentEncoding, 443 | LdapInvalidUrl, 444 | FilesizeExceeded, 445 | UseSslFailed, 446 | SendFailRewind, 447 | SslEngineInitfailed, 448 | LoginDenied, 449 | TftpNotfound, 450 | TftpPerm, 451 | RemoteDiskFull, 452 | TftpIllegal, 453 | Tftp_Unknownid, 454 | RemoteFileExists, 455 | TftpNosuchuser, 456 | ConvFailed, 457 | ConvReqd, 458 | SslCacertBadfile, 459 | RemoteFileNotFound, 460 | Ssh, 461 | SslShutdownFailed, 462 | Again, 463 | SslCrlBadfile, 464 | SslIssuerError, 465 | FtpPretFailed, 466 | RtspCseqError, 467 | RtspSessionError, 468 | FtpBadFileList, 469 | ChunkFailed, 470 | NoConnectionAvailable, 471 | SslPinnedpubkeynotmatch, 472 | SslInvalidcertstatus, 473 | Http2Stream, 474 | RecursiveApiCall, 475 | AuthError, 476 | Http3, 477 | QuicConnectError, 478 | Proxy, 479 | SslClientCert, 480 | UnknownErrorCode, 481 | }; 482 | 483 | fn tryCurl(code: c.CURLcode) Error!void { 484 | if (code != c.CURLE_OK) 485 | return errorFromCurl(code); 486 | } 487 | 488 | fn errorFromCurl(code: c.CURLcode) Error { 489 | return switch (code) { 490 | c.CURLE_UNSUPPORTED_PROTOCOL => error.UnsupportedProtocol, 491 | c.CURLE_FAILED_INIT => error.FailedInit, 492 | c.CURLE_URL_MALFORMAT => error.UrlMalformat, 493 | c.CURLE_NOT_BUILT_IN => error.NotBuiltIn, 494 | c.CURLE_COULDNT_RESOLVE_PROXY => error.CouldntResolveProxy, 495 | c.CURLE_COULDNT_RESOLVE_HOST => error.CouldntResolveHost, 496 | c.CURLE_COULDNT_CONNECT => error.CounldntConnect, 497 | c.CURLE_WEIRD_SERVER_REPLY => error.WeirdServerReply, 498 | c.CURLE_REMOTE_ACCESS_DENIED => error.RemoteAccessDenied, 499 | c.CURLE_FTP_ACCEPT_FAILED => error.FtpAcceptFailed, 500 | c.CURLE_FTP_WEIRD_PASS_REPLY => error.FtpWeirdPassReply, 501 | c.CURLE_FTP_ACCEPT_TIMEOUT => error.FtpAcceptTimeout, 502 | c.CURLE_FTP_WEIRD_PASV_REPLY => error.FtpWeirdPasvReply, 503 | c.CURLE_FTP_WEIRD_227_FORMAT => error.FtpWeird227Format, 504 | c.CURLE_FTP_CANT_GET_HOST => error.FtpCantGetHost, 505 | c.CURLE_HTTP2 => error.Http2, 506 | c.CURLE_FTP_COULDNT_SET_TYPE => error.FtpCouldntSetType, 507 | c.CURLE_PARTIAL_FILE => error.PartialFile, 508 | c.CURLE_FTP_COULDNT_RETR_FILE => error.FtpCouldntRetrFile, 509 | c.CURLE_OBSOLETE20 => error.Obsolete20, 510 | c.CURLE_QUOTE_ERROR => error.QuoteError, 511 | c.CURLE_HTTP_RETURNED_ERROR => error.HttpReturnedError, 512 | c.CURLE_WRITE_ERROR => error.WriteError, 513 | c.CURLE_OBSOLETE24 => error.Obsolete24, 514 | c.CURLE_UPLOAD_FAILED => error.UploadFailed, 515 | c.CURLE_READ_ERROR => error.ReadError, 516 | c.CURLE_OUT_OF_MEMORY => error.OutOfMemory, 517 | c.CURLE_OPERATION_TIMEDOUT => error.OperationTimeout, 518 | c.CURLE_OBSOLETE29 => error.Obsolete29, 519 | c.CURLE_FTP_PORT_FAILED => error.FtpPortFailed, 520 | c.CURLE_FTP_COULDNT_USE_REST => error.FtpCouldntUseRest, 521 | c.CURLE_OBSOLETE32 => error.Obsolete32, 522 | c.CURLE_RANGE_ERROR => error.RangeError, 523 | c.CURLE_HTTP_POST_ERROR => error.HttpPostError, 524 | c.CURLE_SSL_CONNECT_ERROR => error.SslConnectError, 525 | c.CURLE_BAD_DOWNLOAD_RESUME => error.BadDownloadResume, 526 | c.CURLE_FILE_COULDNT_READ_FILE => error.FileCouldntReadFile, 527 | c.CURLE_LDAP_CANNOT_BIND => error.LdapCannotBind, 528 | c.CURLE_LDAP_SEARCH_FAILED => error.LdapSearchFailed, 529 | c.CURLE_OBSOLETE40 => error.Obsolete40, 530 | c.CURLE_FUNCTION_NOT_FOUND => error.FunctionNotFound, 531 | c.CURLE_ABORTED_BY_CALLBACK => error.AbortByCallback, 532 | c.CURLE_BAD_FUNCTION_ARGUMENT => error.BadFunctionArgument, 533 | c.CURLE_OBSOLETE44 => error.Obsolete44, 534 | c.CURLE_INTERFACE_FAILED => error.InterfaceFailed, 535 | c.CURLE_OBSOLETE46 => error.Obsolete46, 536 | c.CURLE_TOO_MANY_REDIRECTS => error.TooManyRedirects, 537 | c.CURLE_UNKNOWN_OPTION => error.UnknownOption, 538 | c.CURLE_SETOPT_OPTION_SYNTAX => error.SetoptOptionSyntax, 539 | c.CURLE_OBSOLETE50 => error.Obsolete50, 540 | c.CURLE_OBSOLETE51 => error.Obsolete51, 541 | c.CURLE_GOT_NOTHING => error.GotNothing, 542 | c.CURLE_SSL_ENGINE_NOTFOUND => error.SslEngineNotfound, 543 | c.CURLE_SSL_ENGINE_SETFAILED => error.SslEngineSetfailed, 544 | c.CURLE_SEND_ERROR => error.SendError, 545 | c.CURLE_RECV_ERROR => error.RecvError, 546 | c.CURLE_OBSOLETE57 => error.Obsolete57, 547 | c.CURLE_SSL_CERTPROBLEM => error.SslCertproblem, 548 | c.CURLE_SSL_CIPHER => error.SslCipher, 549 | c.CURLE_PEER_FAILED_VERIFICATION => error.PeerFailedVerification, 550 | c.CURLE_BAD_CONTENT_ENCODING => error.BadContentEncoding, 551 | c.CURLE_LDAP_INVALID_URL => error.LdapInvalidUrl, 552 | c.CURLE_FILESIZE_EXCEEDED => error.FilesizeExceeded, 553 | c.CURLE_USE_SSL_FAILED => error.UseSslFailed, 554 | c.CURLE_SEND_FAIL_REWIND => error.SendFailRewind, 555 | c.CURLE_SSL_ENGINE_INITFAILED => error.SslEngineInitfailed, 556 | c.CURLE_LOGIN_DENIED => error.LoginDenied, 557 | c.CURLE_TFTP_NOTFOUND => error.TftpNotfound, 558 | c.CURLE_TFTP_PERM => error.TftpPerm, 559 | c.CURLE_REMOTE_DISK_FULL => error.RemoteDiskFull, 560 | c.CURLE_TFTP_ILLEGAL => error.TftpIllegal, 561 | c.CURLE_TFTP_UNKNOWNID => error.Tftp_Unknownid, 562 | c.CURLE_REMOTE_FILE_EXISTS => error.RemoteFileExists, 563 | c.CURLE_TFTP_NOSUCHUSER => error.TftpNosuchuser, 564 | c.CURLE_CONV_FAILED => error.ConvFailed, 565 | c.CURLE_CONV_REQD => error.ConvReqd, 566 | c.CURLE_SSL_CACERT_BADFILE => error.SslCacertBadfile, 567 | c.CURLE_REMOTE_FILE_NOT_FOUND => error.RemoteFileNotFound, 568 | c.CURLE_SSH => error.Ssh, 569 | c.CURLE_SSL_SHUTDOWN_FAILED => error.SslShutdownFailed, 570 | c.CURLE_AGAIN => error.Again, 571 | c.CURLE_SSL_CRL_BADFILE => error.SslCrlBadfile, 572 | c.CURLE_SSL_ISSUER_ERROR => error.SslIssuerError, 573 | c.CURLE_FTP_PRET_FAILED => error.FtpPretFailed, 574 | c.CURLE_RTSP_CSEQ_ERROR => error.RtspCseqError, 575 | c.CURLE_RTSP_SESSION_ERROR => error.RtspSessionError, 576 | c.CURLE_FTP_BAD_FILE_LIST => error.FtpBadFileList, 577 | c.CURLE_CHUNK_FAILED => error.ChunkFailed, 578 | c.CURLE_NO_CONNECTION_AVAILABLE => error.NoConnectionAvailable, 579 | c.CURLE_SSL_PINNEDPUBKEYNOTMATCH => error.SslPinnedpubkeynotmatch, 580 | c.CURLE_SSL_INVALIDCERTSTATUS => error.SslInvalidcertstatus, 581 | c.CURLE_HTTP2_STREAM => error.Http2Stream, 582 | c.CURLE_RECURSIVE_API_CALL => error.RecursiveApiCall, 583 | c.CURLE_AUTH_ERROR => error.AuthError, 584 | c.CURLE_HTTP3 => error.Http3, 585 | c.CURLE_QUIC_CONNECT_ERROR => error.QuicConnectError, 586 | c.CURLE_PROXY => error.Proxy, 587 | c.CURLE_SSL_CLIENTCERT => error.SslClientCert, 588 | 589 | else => blk: { 590 | std.debug.assert(false); 591 | break :blk error.UnknownErrorCode; 592 | }, 593 | }; 594 | } 595 | 596 | fn errorFromCurlUrl(code: c.CURLUcode) UrlError { 597 | return switch (code) { 598 | c.CURLUE_BAD_HANDLE => error.BadHandle, 599 | c.CURLUE_BAD_PARTPOINTER => error.BadPartpointer, 600 | c.CURLUE_MALFORMED_INPUT => error.MalformedInput, 601 | c.CURLUE_BAD_PORT_NUMBER => error.BadPortNumber, 602 | c.CURLUE_UNSUPPORTED_SCHEME => error.UnsupportedScheme, 603 | c.CURLUE_URLDECODE => error.UrlDecode, 604 | c.CURLUE_OUT_OF_MEMORY => error.OutOfMemory, 605 | c.CURLUE_USER_NOT_ALLOWED => error.UserNotAllowed, 606 | c.CURLUE_UNKNOWN_PART => error.UnknownPart, 607 | c.CURLUE_NO_SCHEME => error.NoScheme, 608 | c.CURLUE_NO_USER => error.NoUser, 609 | c.CURLUE_NO_PASSWORD => error.NoPassword, 610 | c.CURLUE_NO_OPTIONS => error.NoOptions, 611 | c.CURLUE_NO_HOST => error.NoHost, 612 | c.CURLUE_NO_PORT => error.NoPort, 613 | c.CURLUE_NO_QUERY => error.NoQuery, 614 | c.CURLUE_NO_FRAGMENT => error.NoFragment, 615 | else => blk: { 616 | std.debug.assert(false); 617 | break :blk error.UnknownErrorCode; 618 | }, 619 | }; 620 | } 621 | --------------------------------------------------------------------------------