├── .github ├── addfiles.png ├── frameworks.png └── workflows │ └── release.yml ├── .gitignore ├── LICENSE ├── README.md ├── build-ios.sh ├── curl.asc ├── inject_module_map.sh ├── patches └── README ├── rootca_signing_key.pem ├── shim.h └── signingkey.pem /.github/addfiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tls-inspector/curl-ios/b5bbc3806e0427b3a02e1daec33f1e5f1cf52b5e/.github/addfiles.png -------------------------------------------------------------------------------- /.github/frameworks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tls-inspector/curl-ios/b5bbc3806e0427b3a02e1daec33f1e5f1cf52b5e/.github/frameworks.png -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: "Build curl framework" 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | schedule: 7 | - cron: "18 18 * * *" 8 | workflow_dispatch: 9 | 10 | permissions: 11 | packages: read 12 | contents: write 13 | 14 | jobs: 15 | query: 16 | name: "Check for updates" 17 | runs-on: macos-14 18 | outputs: 19 | curl_version: ${{ steps.query.outputs.curl_version }} 20 | openssl_version: ${{ steps.query.outputs.openssl_version }} 21 | needs_update: ${{ steps.query.outputs.needs_update }} 22 | steps: 23 | - name: "Get latest release" 24 | id: query 25 | env: 26 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 27 | run: | 28 | echo "Getting latest curl release..." 29 | LATEST_OFFICIAL_CURL_RELEASE=$(curl -sS https://curl.se/info | grep 'Version:' | cut -d ' ' -f2) 30 | LATEST_CURL_IOS_RELEASE=$(gh api /repos/tls-inspector/curl-ios/releases/latest --jq '.name') 31 | if [ -z "$LATEST_OFFICIAL_CURL_RELEASE" ]; then 32 | echo "::error ::Unable to determine latest curl version, aborting run" 33 | exit 1 34 | fi 35 | if [ -z "$LATEST_CURL_IOS_RELEASE" ]; then 36 | echo "::error ::Unable to determine last published framework version, aborting run" 37 | exit 1 38 | fi 39 | 40 | echo "Getting latest openssl release..." 41 | LATEST_OPENSSL_IOS_RELEASE=$(gh api /repos/tls-inspector/openssl-ios/releases/latest --jq '.name') 42 | if [ -z "$LATEST_OPENSSL_IOS_RELEASE" ]; then 43 | echo "::error ::Unable to determine last published framework version, aborting run" 44 | exit 1 45 | fi 46 | 47 | echo "curl_version=${LATEST_OFFICIAL_CURL_RELEASE}" >> $GITHUB_OUTPUT 48 | echo "openssl_version=${LATEST_OPENSSL_IOS_RELEASE}" >> $GITHUB_OUTPUT 49 | 50 | echo "::notice ::Latest curl release: ${LATEST_OFFICIAL_CURL_RELEASE}, last published framework: ${LATEST_CURL_IOS_RELEASE}" 51 | 52 | if [[ "${LATEST_CURL_IOS_RELEASE}" != "${LATEST_OFFICIAL_CURL_RELEASE}" ]]; then 53 | echo "Update available!" 54 | echo "needs_update=yes" >> $GITHUB_OUTPUT 55 | else 56 | echo "No updates available" 57 | echo "needs_update=no" >> $GITHUB_OUTPUT 58 | fi 59 | cat $GITHUB_OUTPUT 60 | update: 61 | name: "Compile" 62 | needs: query 63 | if: needs.query.outputs.needs_update == 'yes' 64 | runs-on: macos-14 65 | outputs: 66 | framework_checksum: ${{ steps.prepare.outputs.framework_checksum }} 67 | steps: 68 | - name: Checkout Source 69 | id: checkout 70 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #pin v4.2.2 71 | - name: Compile Framework 72 | id: compile 73 | env: 74 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 75 | run: | 76 | gpg --import ./curl.asc 77 | echo 'trusted-key 0x78E11C6B279D5C91' >> ~/.gnupg/gpg.conf 78 | echo 'trusted-key 0xF9FEAFF9D34A1BDB' >> ~/.gnupg/gpg.conf 79 | echo 'trusted-key 0x5CC908FDB71E12C2' >> ~/.gnupg/gpg.conf 80 | ./build-ios.sh -c ${{ needs.query.outputs.curl_version }} -o ${{ needs.query.outputs.openssl_version }} -v -g 81 | zip -r curl.xcframework.zip curl.xcframework/ 82 | ./inject_module_map.sh iphoneos 83 | ./inject_module_map.sh iphonesimulator 84 | zip -r curl_swift.xcframework.zip curl.xcframework/ 85 | - name: Capture Build Errors 86 | uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 #pin v4.6.2 87 | if: failure() 88 | with: 89 | name: build_output 90 | path: build/*_build.log 91 | - name: Prepare Release 92 | id: prepare_release 93 | run: | 94 | echo "-----BEGIN EC PRIVATE KEY-----" >> private_key.pem 95 | echo '${{ secrets.SIGNING_KEY }}' >> private_key.pem 96 | echo "-----END EC PRIVATE KEY-----" >> private_key.pem 97 | openssl dgst -sign private_key.pem -sha256 -out curl.xcframework.zip.sig curl.xcframework.zip 98 | openssl dgst -sign private_key.pem -sha256 -out curl_swift.xcframework.zip.sig curl_swift.xcframework.zip 99 | rm -f private_key.pem 100 | - name: Make Release 101 | id: make_release 102 | env: 103 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 104 | run: | 105 | gh release create -n "${{ needs.query.outputs.curl_version }}" -t "${{ needs.query.outputs.curl_version }}" ${{ needs.query.outputs.curl_version }} curl.xcframework.zip curl.xcframework.zip.sig curl_swift.xcframework.zip curl_swift.xcframework.zip.sig 106 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | build/ 3 | *.xcframework/ 4 | *.tar.gz 5 | *.tar.gz.asc 6 | *.tar.xz 7 | *.tar.xz.sig 8 | *.zip 9 | *.zip.sig 10 | *.pem 11 | !rootca_signing_key.pem 12 | !openssl_signing_key.pem 13 | !signingkey.pem 14 | *.pem.sig -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ian Spence 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # curl-ios 2 | 3 | Pre-compiled libcurl framework for iOS and iPadOS applications! Automatically updated within 4 | 24-hours of a new release of curl. 5 | 6 | This copy of curl is built to use [OpenSSL](https://github.com/tls-inspector/openssl-ios), which 7 | uses the root certificates from [rootca](https://github.com/tls-inspector/rootca). 8 | 9 | ## Using the pre-compiled framework 10 | 11 | 1. Download and extract the xcframework.zip from the latest release. 12 | 13 | If you are planning on using Curl in Swift, use `curl_swift.xcframework.zip`, otherwise use `curl.xcframework.zip`. 14 | 15 | 1. _(Optional but recommended)_ download the [signing key](signingkey.pem) and the .sig file for your downloaded zip from the release and verify the signature using OpenSSL 16 | ```bash 17 | openssl dgst -sha256 -verify signingkey.pem -signature curl.xcframework.zip.sig curl.xcframework.zip 18 | ``` 19 | 20 | 1. Select your target in Xcode and click the "+" under Frameworks, Libraries, and Embedded Content 21 | ![Screenshot of the Frameworks, Libraries, and Embedded Content section in Xcode with the plus button circled](.github/frameworks.png) 22 | 1. Click "Add Other" then "Add Files..." 23 | ![Screenshot of a dropdown menu with the add files option highlighted](.github/addfiles.png) 24 | 1. Select the extracted `curl.xcframework` directory. 25 | 26 | Note that Xcode will reference the directory _in-place_, so make sure you've moved it somewhere suitable (outside your downloads directory!). 27 | 28 | 1. Use curl in your code! 29 | 30 | **Swift**: 31 | ```swift 32 | import Curl 33 | import Foundation 34 | 35 | let curlVersion: String = LIBCURL_VERSION 36 | ``` 37 | 38 | **Objective-C**: 39 | ```objc 40 | #import 41 | #import "YourAwesomeClass.h" 42 | 43 | @implementation YourAwesomeClass 44 | 45 | + (NSString *) curlVersion { 46 | return @LIBCURL_VERSION; 47 | } 48 | 49 | @end 50 | ``` 51 | 52 | ## Compile it yourself 53 | 54 | Use the included build script to compile a specific version or customize the configuration options. 55 | 56 | ``` 57 | ./build-ios.sh [-c ] [-o ] [-r ] [-n ] [-vsg] [-- build args] 58 | 59 | Options are: 60 | 61 | -c 62 | Specify the version of curl to compile. If not specified, will query the curl github repo and use 63 | the latest release. If not specified then the 'jq' utility must be installed. 64 | 65 | -o 66 | Specify the version of the openssl-ios package to download and use. If not specified, will query 67 | the tls-inspector/openssl-ios repo and use the latest release. If not specified then the 'jq' 68 | utility must be installed. 69 | 70 | -o 71 | Specify the version of the root ca bundle to download and use. If not specified, will query 72 | the tls-inspector/rootca repo and use the latest release. If not specified then the 'jq' 73 | utility must be installed. 74 | 75 | -n 76 | Specify the name of the root ca bundle to download and use. Defaults to 'apple'. Valid options 77 | are 'apple', 'google', 'microsoft', 'mozilla', and 'tlsinspector'. 78 | 79 | -v 80 | Verify signatures of downloaded artifacts 81 | 82 | -s 83 | Include a Swift module map and shim files. Do not use this if you plan to use this framework in 84 | an Objective-C project. 85 | 86 | -g 87 | Use the 'gh' command line tool instead of curl for GitHub API queries. This is useful for when 88 | running this script in a Github action. 89 | 90 | -- build args 91 | Any arguments after -- are passed directly to the ./configure step of compiling curl. Regardless 92 | of this value these parameters are always provided: 93 | --disable-shared --enable-static --with-openssl --without-libpsl 94 | ``` 95 | 96 | ## Using Curl in Swift 97 | 98 | This package provides support for using Curl in swift. When compiling this package you must pass `-s`. 99 | This will create a .xcframework file that includes a modulemap so you can simply use `import Curl` in any Swift file. 100 | 101 | ### Swift Shim 102 | 103 | This library includes a shim header to work-around some incompatibilities with curl and Swift's C interoperability. Curl 104 | uses C macro functions that accept variables of any type and Swift does not support this. 105 | 106 | When using `curl_easy_setopt` in Swift, you will need to use one of the provided shim functions specific to the 107 | datatype, such as `curl_easy_setopt_string`. 108 | 109 | ## Export Compliance 110 | 111 | This script includes OpenSSL and other cryptographic code. 112 | 113 | Please remember that export/import and/or use of strong cryptography software, providing 114 | cryptography hooks, or even just communicating technical details about cryptography 115 | software is illegal in some parts of the world. By using this script, or importing the 116 | resulting compiled framework in your country, re-distribute it from there or even just 117 | email technical suggestions or even source patches to the authors or other people you are 118 | strongly advised to pay close attention to any laws or regulations which apply to you. 119 | The authors of this script, Curl, and OpenSSL are not liable for any violations you make here. 120 | So be careful, it is your responsibility. 121 | -------------------------------------------------------------------------------- /build-ios.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | ################ 5 | # PROCESS ARGS # 6 | ################ 7 | 8 | VERIFY=0 9 | CURL_VERSION=0 10 | OPENSSL_VERSION=0 11 | ROOTCA_VERSION=0 12 | ROOTCA_BUNDLE_NAME="apple" 13 | SWIFT=0 14 | USE_GH_CLI=0 15 | 16 | while getopts :c:o:r:n:vsg OPTION; do 17 | case $OPTION in 18 | c) CURL_VERSION=$OPTARG;; 19 | o) OPENSSL_VERSION=$OPTARG;; 20 | r) ROOTCA_VERSION=$OPTARG;; 21 | n) ROOTCA_BUNDLE_NAME=$OPTARG;; 22 | v) VERIFY=1;; 23 | s) SWIFT=1;; 24 | g) USE_GH_CLI=1;; 25 | ?) echo "Error: Invalid option was specified -$OPTARG";exit 1;; 26 | esac 27 | done 28 | if [ "$OPTIND" -ge 2 ]; then 29 | shift "$((OPTIND - 2))" 30 | shift 1 31 | else 32 | shift "$((OPTIND - 1))" 33 | fi 34 | 35 | if ! command -v jq 2>&1 >/dev/null; then 36 | echo "The 'jq' utility must be installed, otherwise you must specify the curl and openssl versions to use." 37 | exit 1 38 | fi 39 | 40 | BUILD_ARGS="$*" 41 | USERAGENT="github.com/tls-inspector/curl-ios" 42 | 43 | function github_api() { 44 | API_PATH=$1 45 | 46 | if [[ $USE_GH_CLI == 1 ]]; then 47 | gh api $API_PATH 48 | else 49 | curl -Ss -A "${USERAGENT}" "https://api.github.com/$API_PATH" 50 | fi 51 | } 52 | 53 | if [[ $CURL_VERSION == 0 ]]; then 54 | CURL_VERSION=$(github_api repos/curl/curl/releases/latest | jq -r .name) 55 | fi 56 | echo "Using Curl ${CURL_VERSION}" 57 | 58 | if [[ $OPENSSL_VERSION == 0 ]]; then 59 | OPENSSL_VERSION=$(github_api repos/tls-inspector/openssl-ios/releases/latest | jq -r .name) 60 | fi 61 | echo "Using OpenSSL ${OPENSSL_VERSION}" 62 | 63 | if [[ $ROOTCA_VERSION == 0 ]]; then 64 | ROOTCA_VERSION=$(github_api repos/tls-inspector/rootca/releases/latest | jq -r .tag_name) 65 | fi 66 | echo "Using root CA certificates ${ROOTCA_VERSION}" 67 | 68 | ############################### 69 | # DOWNLOAD & VERIFY ARTIFACTS # 70 | ############################### 71 | 72 | # Download curl 73 | ARCHIVE="curl-${CURL_VERSION}.tar.gz" 74 | if [ ! -f "${ARCHIVE}" ]; then 75 | echo "Downloading curl ${CURL_VERSION}" 76 | curl -A "${USERAGENT}" "https://curl.se/download/curl-${CURL_VERSION}.tar.gz" > "${ARCHIVE}" 77 | fi 78 | 79 | # Verify curl 80 | if [[ $VERIFY == 1 ]]; then 81 | echo "Verifying signature for curl-${CURL_VERSION}.tar.gz" 82 | if [ ! -f "${ARCHIVE}.asc" ]; then 83 | curl -A "${USERAGENT}" "https://curl.se/download/curl-${CURL_VERSION}.tar.gz.asc" > "${ARCHIVE}.asc" 84 | fi 85 | gpg --verify "${ARCHIVE}.asc" "${ARCHIVE}" >/dev/null 86 | echo "Verified signature for ${ARCHIVE} successfully!" 87 | fi 88 | 89 | # Download openssl 90 | OPENSSL_ARCHIVE="openssl-${OPENSSL_VERSION}.tar.xz" 91 | if [ ! -f "${OPENSSL_ARCHIVE}" ]; then 92 | echo "Downloading openssl ${OPENSSL_VERSION}" 93 | curl -A "${UA}" -L "https://github.com/tls-inspector/openssl-ios/releases/download/${OPENSSL_VERSION}/openssl.tar.xz" > "${OPENSSL_ARCHIVE}" 94 | fi 95 | 96 | # Verify openssl 97 | if [[ $VERIFY == 1 ]]; then 98 | echo "Verifying signature for ${OPENSSL_ARCHIVE}" 99 | if [ ! -f "${OPENSSL_ARCHIVE}.sig" ]; then 100 | curl -A "${UA}" -L "https://github.com/tls-inspector/openssl-ios/releases/download/${OPENSSL_VERSION}/openssl.tar.xz.sig" > "${OPENSSL_ARCHIVE}.sig" 101 | fi 102 | openssl dgst -sha256 -verify signingkey.pem -signature ${OPENSSL_ARCHIVE}.sig ${OPENSSL_ARCHIVE} 103 | fi 104 | 105 | # Download rootca certs 106 | ROOTCA_ARCHIVE="rootca-${ROOTCA_BUNDLE_NAME}-${ROOTCA_VERSION}.pem" 107 | if [ ! -f "${ROOTCA_ARCHIVE}" ]; then 108 | curl -A "${UA}" -L "https://github.com/tls-inspector/rootca/releases/download/${ROOTCA_VERSION}/${ROOTCA_BUNDLE_NAME}_ca_bundle.pem" > "${ROOTCA_ARCHIVE}" 109 | fi 110 | 111 | # Verify rootca certs 112 | if [[ $VERIFY == 1 ]]; then 113 | echo "Verifying signature for ${ROOTCA_ARCHIVE}" 114 | if [ ! -f "${ROOTCA_ARCHIVE}.sig" ]; then 115 | curl -A "${UA}" -L "https://github.com/tls-inspector/rootca/releases/download/${ROOTCA_VERSION}/${ROOTCA_BUNDLE_NAME}_ca_bundle.pem.sig" > "${ROOTCA_ARCHIVE}.sig" 116 | fi 117 | openssl dgst -sha256 -verify rootca_signing_key.pem -signature ${ROOTCA_ARCHIVE}.sig ${ROOTCA_ARCHIVE} 118 | fi 119 | 120 | ########### 121 | # COMPILE # 122 | ########### 123 | 124 | BUILDDIR=build 125 | 126 | function build() { 127 | ARCH=$1 128 | HOST=$2 129 | SDK=$3 130 | echo "Building libcurl for ${ARCH}-${SDK}..." 131 | SDKDIR=$(xcrun --sdk ${SDK} --show-sdk-path) 132 | LOG="../${ARCH}-${SDK}_build.log" 133 | 134 | WORKDIR=curl_${ARCH}-${SDK} 135 | mkdir "${WORKDIR}" 136 | tar -xzf "../${ARCHIVE}" -C "${WORKDIR}" --strip-components 1 137 | cd "${WORKDIR}" 138 | 139 | for FILE in $(find ../../patches -name '*.patch' 2>/dev/null); do 140 | patch -p1 < ${FILE} 141 | done 142 | 143 | OPENSSL_ARTIFACTS=$(readlink -f ../openssl/openssl_${ARCH}-${SDK}/artifacts) 144 | CA_EMBED=$(readlink -f ../../${ROOTCA_ARCHIVE}) 145 | # Need to patch the pkgconfig in openssl 146 | perl -pi -e "s,/Users/runner/work/openssl-ios/openssl-ios/build/openssl_${ARCH}-${SDK}/artifacts,${OPENSSL_ARTIFACTS},g" ${OPENSSL_ARTIFACTS}/lib/pkgconfig/*.pc 147 | 148 | export CC=$(xcrun -find -sdk ${SDK} gcc) 149 | export CFLAGS="-arch ${ARCH} -pipe -Os -gdwarf-2 -isysroot ${SDKDIR} -m${SDK}-version-min=18.0" 150 | export LDFLAGS="-arch ${ARCH} -isysroot ${SDKDIR}" 151 | 152 | CONFIGURE_ARGS="${BUILD_ARGS} --disable-shared --enable-static --without-libpsl --with-ca-embed=${CA_EMBED} --with-openssl=${OPENSSL_ARTIFACTS}" 153 | 154 | echo "build variables: CC=\"${CC}\" CFLAGS=\"${CFLAGS}\" CPPFLAGS=\"${CPPFLAGS}\" LDFLAGS=\"${LDFLAGS}\"" >> "${LOG}" 155 | echo "configure parameters: --host=\"${HOST}-apple-darwin\" ${CONFIGURE_ARGS} --prefix $(pwd)/artifacts" >> "${LOG}" 156 | 157 | ./configure \ 158 | --host="${HOST}-apple-darwin" \ 159 | $CONFIGURE_ARGS \ 160 | --prefix $(pwd)/artifacts >> "${LOG}" 2>&1 161 | 162 | make -j`sysctl -n hw.logicalcpu_max` >> "${LOG}" 2>&1 163 | make install >> "${LOG}" 2>&1 164 | cd ../ 165 | } 166 | 167 | rm -rf ${BUILDDIR} 168 | mkdir ${BUILDDIR} 169 | cp ${OPENSSL_ARCHIVE} ${BUILDDIR} 170 | cd ${BUILDDIR} 171 | tar -xf ${OPENSSL_ARCHIVE} 172 | mv build openssl 173 | 174 | build arm64 arm iphoneos 175 | build arm64 arm iphonesimulator 176 | build x86_64 x86_64 iphonesimulator 177 | 178 | cd ../ 179 | 180 | ########### 181 | # PACKAGE # 182 | ########### 183 | 184 | lipo \ 185 | -arch arm64 ${BUILDDIR}/curl_arm64-iphonesimulator/artifacts/lib/libcurl.a \ 186 | -arch x86_64 ${BUILDDIR}/curl_x86_64-iphonesimulator/artifacts/lib/libcurl.a \ 187 | -create -output ${BUILDDIR}/libcurl.a 188 | 189 | rm -rf ${BUILDDIR}/iphoneos/curl.framework ${BUILDDIR}/iphonesimulator/curl.framework 190 | mkdir -p ${BUILDDIR}/iphoneos/curl.framework/Headers ${BUILDDIR}/iphonesimulator/curl.framework/Headers 191 | libtool -no_warning_for_no_symbols -static -o ${BUILDDIR}/iphoneos/curl.framework/curl ${BUILDDIR}/curl_arm64-iphoneos/artifacts/lib/libcurl.a 192 | cp -r ${BUILDDIR}/curl_arm64-iphoneos/artifacts/include/curl/*.h ${BUILDDIR}/iphoneos/curl.framework/Headers 193 | libtool -no_warning_for_no_symbols -static -o ${BUILDDIR}/iphonesimulator/curl.framework/curl ${BUILDDIR}/libcurl.a 194 | cp -r ${BUILDDIR}/curl_arm64-iphonesimulator/artifacts/include/curl/*.h ${BUILDDIR}/iphonesimulator/curl.framework/Headers 195 | 196 | rm -rf curl.xcframework 197 | xcodebuild -create-xcframework \ 198 | -framework ${BUILDDIR}/iphoneos/curl.framework \ 199 | -framework ${BUILDDIR}/iphonesimulator/curl.framework \ 200 | -output curl.xcframework 201 | plutil -insert CFBundleVersion -string ${CURL_VERSION} curl.xcframework/Info.plist 202 | 203 | if [[ $SWIFT == 1 ]]; then 204 | ./inject_module_map.sh iphoneos 205 | ./inject_module_map.sh iphonesimulator 206 | fi 207 | 208 | rm -rf curl.xcframework 209 | xcodebuild -create-xcframework \ 210 | -framework ${BUILDDIR}/iphoneos/curl.framework \ 211 | -framework ${BUILDDIR}/iphonesimulator/curl.framework \ 212 | -output curl.xcframework 213 | plutil -insert CFBundleVersion -string ${CURL_VERSION} curl.xcframework/Info.plist 214 | -------------------------------------------------------------------------------- /curl.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Version: GnuPG v2 3 | 4 | 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 75 | j/qx4ytjt5uxt6Jm6IXV9cry8i6x 76 | =Phs/ 77 | -----END PGP PUBLIC KEY BLOCK----- 78 | -------------------------------------------------------------------------------- /inject_module_map.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | if [ -z "$1" ]; then 5 | echo "Usage: $0 " 6 | exit 1 7 | fi 8 | 9 | PLATFORM=${1} 10 | mkdir -p build/${PLATFORM}/curl.framework/Modules 11 | echo "framework module Curl {" > build/${PLATFORM}/curl.framework/Modules/module.modulemap 12 | echo " header \"shim.h\"" >> build/${PLATFORM}/curl.framework/Modules/module.modulemap 13 | for HEADER in $(ls build/${PLATFORM}/curl.framework/Headers); do 14 | echo " header \"${HEADER}\"" >> build/${PLATFORM}/curl.framework/Modules/module.modulemap 15 | done 16 | echo " export *" >> build/${PLATFORM}/curl.framework/Modules/module.modulemap 17 | echo "}" >> build/${PLATFORM}/curl.framework/Modules/module.modulemap 18 | cp shim.h build/${PLATFORM}/curl.framework/Headers 19 | -------------------------------------------------------------------------------- /patches/README: -------------------------------------------------------------------------------- 1 | Any .patch file placed here will be applied to the curl source before compiling. 2 | Patches are applied in an alphabetical order, so it's recommended to use a 3 | numerical prefix like 10-fix.patch 4 | -------------------------------------------------------------------------------- /rootca_signing_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExiFIwNh/FbegHR6DEqSZz0QcDQPI 3 | oeMuS45AzI8Mbrs9yA9FYkgFcowDtPSO5adwZTTeCfKBamuYuIYSBlshiA== 4 | -----END PUBLIC KEY----- -------------------------------------------------------------------------------- /shim.h: -------------------------------------------------------------------------------- 1 | #ifndef CURL_SHIM 2 | #define CURL_SHIM 3 | 4 | /* 5 | * This shim enables Swift applications to interact with some of curl's function macros which aren't 6 | * compatible with Swift. 7 | */ 8 | 9 | #import 10 | #include 11 | 12 | /// Invoke curl_easy_setopt with a string parameter 13 | static inline CURLcode curl_easy_setopt_string(CURL *handle, CURLoption option, const char *parameter) 14 | { 15 | return curl_easy_setopt(handle, option, parameter); 16 | } 17 | 18 | /// Invoke curl_easy_setopt with an int parameter 19 | static inline CURLcode curl_easy_setopt_int(CURL *handle, CURLoption option, int parameter) 20 | { 21 | return curl_easy_setopt(handle, option, parameter); 22 | } 23 | 24 | /// Invoke curl_easy_setopt with a byte array parameter 25 | static inline CURLcode curl_easy_setopt_binary(CURL *handle, CURLoption option, const uint8_t *parameter) 26 | { 27 | return curl_easy_setopt(handle, option, parameter); 28 | } 29 | 30 | /// Invoke curl_easy_setopt with a callback function parameter 31 | static inline CURLcode curl_easy_setopt_write_function(CURL *handle, CURLoption option, curl_write_callback parameter) 32 | { 33 | return curl_easy_setopt(handle, option, parameter); 34 | } 35 | 36 | /// Invoke curl_easy_setopt with a debug function parameter 37 | static inline CURLcode curl_easy_setopt_debug_function(CURL *handle, CURLoption option, curl_debug_callback parameter) 38 | { 39 | return curl_easy_setopt(handle, option, parameter); 40 | } 41 | 42 | /// Invoke curl_easy_setopt with a pointer parameter 43 | static inline CURLcode curl_easy_setopt_pointer(CURL *handle, CURLoption option, void *parameter) 44 | { 45 | return curl_easy_setopt(handle, option, parameter); 46 | } 47 | 48 | /// Invoke curl_easy_setopt with a slist parameter 49 | static inline CURLcode curl_easy_setopt_slist(CURL *handle, CURLoption option, struct curl_slist *parameter) 50 | { 51 | return curl_easy_setopt(handle, option, parameter); 52 | } 53 | 54 | /// Invoke curl_easy_setopt with a blob parameter 55 | static inline CURLcode curl_easy_setopt_blob(CURL *handle, CURLoption option, struct curl_blob *parameter) 56 | { 57 | return curl_easy_setopt(handle, option, parameter); 58 | } 59 | 60 | /// Invoke curl_easy_getinfo for getting a string value 61 | static inline CURLcode curl_easy_getinfo_string(CURL *handle, CURLINFO info, const char **parameter) 62 | { 63 | return curl_easy_getinfo(handle, info, parameter); 64 | } 65 | 66 | /// Invoke curl_easy_getinfo for getting an int value 67 | static inline CURLcode curl_easy_getinfo_int(CURL *handle, CURLINFO info, int *parameter) 68 | { 69 | return curl_easy_getinfo(handle, info, parameter); 70 | } 71 | 72 | /// Invoke curl_easy_getinfo for getting a byte array value 73 | static inline CURLcode curl_easy_getinfo_binary(CURL *handle, CURLINFO info, const uint8_t **parameter) 74 | { 75 | return curl_easy_getinfo(handle, info, parameter); 76 | } 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /signingkey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbJGKehPTyb+n1D9ejHvcupuVOvYY 3 | hkbps3hVsc/w+YDGMompmY5W+VpL5t+ORE079jKlxoB0LSuS6of9LuY6fQ== 4 | -----END PUBLIC KEY----- 5 | --------------------------------------------------------------------------------