├── .appveyor.yml ├── .ci ├── appveyor.psm1 └── php-appveyor.psm1 ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── CREDITS ├── LICENSE ├── Makefile.frag ├── README.md ├── autoconf ├── pecl.m4 └── php-executable.m4 ├── base58.c ├── build-packagexml.php ├── config.m4 ├── config.w32 ├── lib ├── AUTHORS ├── COPYING ├── libbase58.c └── libbase58.h ├── package.xml ├── php_base58.h └── tests ├── base58_decode.phpt └── base58_encode.phpt /.appveyor.yml: -------------------------------------------------------------------------------- 1 | # See https://github.com/sergeyklay/php-appveyor 2 | 3 | branches: 4 | only: 5 | - master 6 | - appveyor 7 | - w32 8 | - /v\d*\.\d*\.\d*/ 9 | 10 | environment: 11 | EXTNAME: base58 12 | 13 | matrix: 14 | - PHP_VERSION: 7.2 15 | BUILD_TYPE: Win32 16 | VC_VERSION: vc15 17 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 18 | 19 | - PHP_VERSION: 7.2 20 | BUILD_TYPE: nts-Win32 21 | VC_VERSION: vc15 22 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 23 | 24 | - PHP_VERSION: 7.3 25 | BUILD_TYPE: Win32 26 | VC_VERSION: vc15 27 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 28 | 29 | - PHP_VERSION: 7.3 30 | BUILD_TYPE: nts-Win32 31 | VC_VERSION: vc15 32 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 33 | 34 | - PHP_VERSION: 7.4 35 | BUILD_TYPE: Win32 36 | VC_VERSION: vc15 37 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 38 | 39 | - PHP_VERSION: 7.4 40 | BUILD_TYPE: nts-Win32 41 | VC_VERSION: vc15 42 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 43 | 44 | - PHP_VERSION: 8.0 45 | BUILD_TYPE: Win32 46 | VC_VERSION: vs16 47 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 48 | 49 | - PHP_VERSION: 8.0 50 | BUILD_TYPE: nts-Win32 51 | VC_VERSION: vs16 52 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 53 | 54 | PHP_SDK_VERSION: 2.2.0 55 | TEST_PHP_EXECUTABLE: C:\php\php.exe 56 | NO_INTERACTION: 1 57 | REPORT_EXIT_STATUS: 1 58 | 59 | matrix: 60 | fast_finish: true 61 | 62 | cache: 63 | - 'C:\Downloads -> .appveyor.yml' 64 | 65 | platform: 66 | - x86 67 | - x64 68 | 69 | init: 70 | - ps: $DebugPreference = 'SilentlyContinue' # Continue 71 | - ps: >- 72 | if ($env:APPVEYOR_REPO_TAG -eq "true") { 73 | Update-AppveyorBuild -Version "$($Env:APPVEYOR_REPO_TAG_NAME.TrimStart("v"))" 74 | } else { 75 | Update-AppveyorBuild -Version "${Env:APPVEYOR_REPO_BRANCH}-$($Env:APPVEYOR_REPO_COMMIT.Substring(0, 7))" 76 | } 77 | 78 | install: 79 | - ps: Import-Module .\.ci\php-appveyor.psm1 80 | 81 | - ps: InstallPhpSdk $Env:PHP_SDK_VERSION $Env:VC_VERSION $Env:PLATFORM 82 | - ps: InstallPhp $Env:PHP_VERSION $Env:BUILD_TYPE $Env:VC_VERSION $Env:PLATFORM 83 | - ps: InstallPhpDevPack $Env:PHP_VERSION $Env:BUILD_TYPE $Env:VC_VERSION $Env:PLATFORM 84 | 85 | build_script: 86 | - ps: Import-Module .\.ci\appveyor.psm1 87 | - ps: InitializeBuildVars 88 | - cmd: '"%VSDEVCMD%" -arch=%PLATFORM%' 89 | - cmd: '"%VCVARSALL%" %ARCH%' 90 | - cmd: C:\php-sdk\bin\phpsdk_setvars 91 | - cmd: C:\php-devpack\phpize 92 | - cmd: configure.bat --with-prefix=C:\php --with-php-build=C:\php-devpack --disable-all %ENABLE_EXT% 93 | - cmd: nmake 2> compile-errors.log 1> compile.log 94 | - ps: InitializeReleaseVars 95 | 96 | test_script: 97 | - cmd: nmake test 98 | 99 | after_build: 100 | - ps: Set-Location "${Env:APPVEYOR_BUILD_FOLDER}" 101 | - ps: >- 102 | PrepareReleasePackage ` 103 | -PhpVersion $Env:PHP_VERSION ` 104 | -BuildType $Env:BUILD_TYPE ` 105 | -Platform $Env:PLATFORM ` 106 | -ConverMdToHtml $true ` 107 | -ReleaseFiles "${Env:RELEASE_FOLDER}\php_${Env:EXTNAME}.dll",` 108 | "${Env:APPVEYOR_BUILD_FOLDER}\CREDITS",` 109 | "${Env:APPVEYOR_BUILD_FOLDER}\LICENSE" 110 | 111 | on_failure : 112 | - ps: >- 113 | If (Test-Path -Path "${Env:APPVEYOR_BUILD_FOLDER}\compile-errors.log") { 114 | Get-Content -Path "${Env:APPVEYOR_BUILD_FOLDER}\compile-errors.log" 115 | } 116 | 117 | If (Test-Path -Path "${Env:APPVEYOR_BUILD_FOLDER}\compile.log") { 118 | Get-Content -Path "${Env:APPVEYOR_BUILD_FOLDER}\compile.log" 119 | } 120 | 121 | Get-ChildItem "${Env:APPVEYOR_BUILD_FOLDER}\tests" -Recurse -Filter *.diff | Foreach-Object { 122 | [Environment]::NewLine 123 | Write-Output $_.FullName 124 | Get-Content -Path $_.FullName 125 | } 126 | 127 | artifacts: 128 | - path: '.\$(RELEASE_ZIPBALL).zip' 129 | name: '$(EXTNAME)' 130 | type: zip 131 | 132 | deploy: 133 | release: v$(appveyor_build_version) 134 | description: 'v$(appveyor_build_version)' 135 | provider: GitHub 136 | auth_token: 137 | secure: IV3NKl1invi15i+slqXGMqn6j6yk4JZYIP6+5fDjbWTJhKze4cCXPKD3+jm5B/Zm 138 | artifact: '$(RELEASE_ZIPBALL).zip' 139 | draft: false 140 | prerelease: true 141 | force_update: true 142 | on: 143 | branch: master 144 | APPVEYOR_REPO_TAG: true 145 | -------------------------------------------------------------------------------- /.ci/appveyor.psm1: -------------------------------------------------------------------------------- 1 | Function InitializeBuildVars { 2 | switch ($Env:VC_VERSION) { 3 | 'vc14' { 4 | If (-not (Test-Path $Env:VS120COMNTOOLS)) { 5 | Throw'The VS120COMNTOOLS environment variable is not set. Check your VS installation' 6 | } 7 | 8 | $Env:VSDEVCMD = ($Env:VS120COMNTOOLS -replace '\\$', '') + '\VsDevCmd.bat' 9 | Break 10 | } 11 | 'vc15' { 12 | If (-not (Test-Path $Env:VS140COMNTOOLS)) { 13 | Throw'The VS140COMNTOOLS environment variable is not set. Check your VS installation' 14 | } 15 | 16 | $Env:VSDEVCMD = ($Env:VS140COMNTOOLS -replace '\\$', '') + '\VsDevCmd.bat' 17 | Break 18 | } 19 | default { 20 | $Env:VSDEVCMD = Get-ChildItem -Path "${Env:ProgramFiles(x86)}" -Filter "VsDevCmd.bat" -Recurse -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName } 21 | 22 | If ("$Env:VSDEVCMD" -eq "") { 23 | Throw 'Unable to find VsDevCmd. Check your VS installation' 24 | } 25 | } 26 | } 27 | 28 | If ($Env:PLATFORM -eq 'x64') { 29 | $Env:ARCH = 'x86_amd64' 30 | } Else { 31 | $Env:ARCH = 'x86' 32 | } 33 | 34 | $Env:ENABLE_EXT = "--enable-{0}" -f ("${Env:EXTNAME}" -replace "_","-") 35 | 36 | $SearchInFolder = (Get-Item $Env:VSDEVCMD).Directory.Parent.Parent.FullName 37 | $Env:VCVARSALL = Get-ChildItem -Path "$SearchInFolder" -Filter "vcvarsall.bat" -Recurse -ErrorAction SilentlyContinue | ForEach-Object { $_.FullName } 38 | } 39 | 40 | Function InitializeReleaseVars { 41 | If ($Env:PLATFORM -eq 'x86') { 42 | If ($Env:BUILD_TYPE -Match "nts-Win32") { 43 | $Env:RELEASE_SUBFOLDER = "Release" 44 | } Else { 45 | $Env:RELEASE_SUBFOLDER = "Release_TS" 46 | } 47 | } Else { 48 | If ($Env:BUILD_TYPE -Match "nts-Win32") { 49 | $Env:RELEASE_SUBFOLDER = "${Env:PLATFORM}\Release" 50 | } Else { 51 | $Env:RELEASE_SUBFOLDER = "${Env:PLATFORM}\Release_TS" 52 | } 53 | } 54 | 55 | $Env:RELEASE_FOLDER = "${Env:APPVEYOR_BUILD_FOLDER}\${Env:RELEASE_SUBFOLDER}" 56 | $Env:RELEASE_ZIPBALL = "${Env:EXTNAME}_${Env:PLATFORM}_${Env:VC_VERSION}_php${Env:PHP_VERSION}_${Env:APPVEYOR_BUILD_VERSION}" 57 | } 58 | -------------------------------------------------------------------------------- /.ci/php-appveyor.psm1: -------------------------------------------------------------------------------- 1 | # This file is part of the php-appveyor.psm1 project. 2 | # 3 | # (c) Serghei Iakovlev 4 | # 5 | # For the full copyright and license information, please view 6 | # the LICENSE file that was distributed with this source code. 7 | 8 | # $ErrorActionPreference = "Stop" 9 | 10 | function InstallPhpSdk { 11 | param ( 12 | [Parameter(Mandatory=$true)] [System.String] $Version, 13 | [Parameter(Mandatory=$true)] [System.String] $VC, 14 | [Parameter(Mandatory=$true)] [System.String] $Platform, 15 | [Parameter(Mandatory=$false)] [System.String] $InstallPath = "C:\php-sdk" 16 | ) 17 | 18 | Write-Debug "Install PHP SDK binary tools: ${Version}" 19 | SetupPrerequisites 20 | 21 | $FileName = "php-sdk-${Version}" 22 | $RemoteUrl = "https://github.com/Microsoft/php-sdk-binary-tools/archive/${FileName}.zip" 23 | $Archive = "C:\Downloads\${FileName}.zip" 24 | 25 | if (-not (Test-Path "${InstallPath}\bin\php\php.exe")) { 26 | if (-not (Test-Path $Archive)) { 27 | DownloadFile -RemoteUrl $RemoteUrl -Destination $Archive 28 | } 29 | 30 | $UnzipPath = "${Env:Temp}\php-sdk-binary-tools-${FileName}" 31 | if (-not (Test-Path "${UnzipPath}")) { 32 | Expand-Item7zip -Archive $Archive -Destination $Env:Temp 33 | } 34 | 35 | Move-Item -Path $UnzipPath -Destination $InstallPath 36 | } 37 | 38 | EnsureRequiredDirectoriesPresent ` 39 | -Directories bin,lib,include ` 40 | -Prefix "${InstallPath}\phpdev\${VC}\${Platform}" 41 | } 42 | 43 | function InstallPhp { 44 | param ( 45 | [Parameter(Mandatory=$true)] [System.String] $Version, 46 | [Parameter(Mandatory=$true)] [System.String] $BuildType, 47 | [Parameter(Mandatory=$true)] [System.String] $VC, 48 | [Parameter(Mandatory=$true)] [System.String] $Platform, 49 | [Parameter(Mandatory=$false)] [System.String] $InstallPath = "C:\php" 50 | ) 51 | 52 | SetupPrerequisites 53 | $FullVersion = SetupPhpVersionString -Pattern $Version 54 | 55 | Write-Debug "Install PHP v${FullVersion}" 56 | 57 | $ReleasesPart = "releases" 58 | if ([System.Convert]::ToDecimal($Version) -lt 7.1) { 59 | $ReleasesPart = "releases/archives" 60 | } 61 | 62 | $RemoteUrl = "http://windows.php.net/downloads/{0}/php-{1}-{2}-{3}-{4}.zip" -f 63 | $ReleasesPart, $FullVersion, $BuildType, $VC, $Platform 64 | 65 | $Archive = "C:\Downloads\php-${FullVersion}-${BuildType}-${VC}-${Platform}.zip" 66 | 67 | if (-not (Test-Path "${InstallPath}\php.exe")) { 68 | if (-not (Test-Path $Archive)) { 69 | DownloadFile $RemoteUrl $Archive 70 | } 71 | 72 | Expand-Item7zip $Archive $InstallPath 73 | } 74 | 75 | if (-not (Test-Path "${InstallPath}\php.ini")) { 76 | Copy-Item "${InstallPath}\php.ini-development" "${InstallPath}\php.ini" 77 | } 78 | } 79 | 80 | function InstallPhpDevPack { 81 | param ( 82 | [Parameter(Mandatory=$true)] [System.String] $PhpVersion, 83 | [Parameter(Mandatory=$true)] [System.String] $BuildType, 84 | [Parameter(Mandatory=$true)] [System.String] $VC, 85 | [Parameter(Mandatory=$true)] [System.String] $Platform, 86 | [Parameter(Mandatory=$false)] [System.String] $InstallPath = "C:\php-devpack" 87 | ) 88 | 89 | SetupPrerequisites 90 | $Version = SetupPhpVersionString -Pattern $PhpVersion 91 | 92 | Write-Debug "Install PHP Dev for PHP v${Version}" 93 | 94 | $ReleasesPart = "releases" 95 | if ([System.Convert]::ToDecimal($PhpVersion) -lt 7.1) { 96 | $ReleasesPart = "releases/archives" 97 | } 98 | 99 | $RemoteUrl = "http://windows.php.net/downloads/{0}/php-devel-pack-{1}-{2}-{3}-{4}.zip" -f 100 | $ReleasesPart, $Version, $BuildType, $VC, $Platform 101 | 102 | $Archive = "C:\Downloads\php-devel-pack-${Version}-${BuildType}-${VC}-${Platform}.zip" 103 | 104 | if (-not (Test-Path "${InstallPath}\phpize.bat")) { 105 | if (-not (Test-Path $Archive)) { 106 | DownloadFile $RemoteUrl $Archive 107 | } 108 | 109 | $UnzipPath = "${Env:Temp}\php-${Version}-devel-${VC}-${Platform}" 110 | if (-not (Test-Path "${UnzipPath}\phpize.bat")) { 111 | Expand-Item7zip $Archive $Env:Temp 112 | } 113 | 114 | if (Test-Path "${InstallPath}") { 115 | Move-Item -Path "${UnzipPath}\*" -Destination $InstallPath 116 | } else { 117 | Move-Item -Path $UnzipPath -Destination $InstallPath 118 | } 119 | } 120 | } 121 | 122 | function InstallPeclExtension { 123 | param ( 124 | [Parameter(Mandatory=$true)] [System.String] $Name, 125 | [Parameter(Mandatory=$true)] [System.String] $Version, 126 | [Parameter(Mandatory=$true)] [System.String] $PhpVersion, 127 | [Parameter(Mandatory=$true)] [System.String] $BuildType, 128 | [Parameter(Mandatory=$true)] [System.String] $VC, 129 | [Parameter(Mandatory=$true)] [System.String] $Platform, 130 | [Parameter(Mandatory=$false)] [System.String] $InstallPath = "C:\php\ext", 131 | [Parameter(Mandatory=$false)] [System.Boolean] $Headers = $false, 132 | [Parameter(Mandatory=$false)] [System.Boolean] $Enable = $false 133 | ) 134 | 135 | SetupPrerequisites 136 | 137 | $BaseUri = "https://windows.php.net/downloads/pecl/releases/${Name}/${Version}" 138 | $LocalPart = "php_${Name}-${Version}-${PhpVersion}" 139 | 140 | if ($BuildType -Match "nts-Win32") { 141 | $TS = "nts" 142 | } else { 143 | $TS = "ts" 144 | } 145 | 146 | $RemoteUrl = "${BaseUri}/${LocalPart}-${TS}-${VC}-${Platform}.zip" 147 | $DestinationPath = "C:\Downloads\${LocalPart}-${TS}-${VC}-${Platform}.zip" 148 | 149 | if (-not (Test-Path "${InstallPath}\php_${Name}.dll")) { 150 | if (-not (Test-Path $DestinationPath)) { 151 | DownloadFile $RemoteUrl $DestinationPath 152 | } 153 | 154 | Expand-Item7zip $DestinationPath $InstallPath 155 | } 156 | 157 | if ($Headers) { 158 | InstallPeclHeaders -Name $Name -Version $Version 159 | } 160 | 161 | if ($Enable) { 162 | EnablePhpExtension -Name $Name 163 | } 164 | } 165 | 166 | Function InstallPeclHeaders { 167 | Param( 168 | [Parameter(Mandatory=$true)] [System.String] $Name, 169 | [Parameter(Mandatory=$true)] [System.String] $Version, 170 | [Parameter(Mandatory=$false)] [System.String] $InstallPath = 'C:\php-devpack\include\ext\' 171 | ) 172 | 173 | $RemoteUrl = "https://pecl.php.net/get/${Name}-${Version}.tgz" 174 | $DownloadFile = "C:\Downloads\${Name}-${Version}.tgz" 175 | 176 | If (-not [System.IO.File]::Exists($DownloadFile)) { 177 | DownloadFile $RemoteUrl $DownloadFile 178 | } 179 | 180 | Ensure7ZipIsInstalled 181 | 182 | Expand-Item7zip $DownloadFile "${Env:Temp}" 183 | 184 | Write-Debug "Copy header files to ${InstallPath}\${Name}" 185 | 186 | New-Item -Path "${InstallPath}" -Name "${Name}" -ItemType "directory" | Out-Null 187 | Copy-Item "${Env:Temp}\${Name}-${Version}\*.h" -Destination "${InstallPath}\${Name}" -Recurse 188 | } 189 | 190 | function InstallComposer { 191 | param ( 192 | [Parameter(Mandatory=$false)] [System.String] $PhpInstallPath = 'C:\php', 193 | [Parameter(Mandatory=$false)] [System.String] $InstallPath = '.' 194 | ) 195 | 196 | $InstallPath = Resolve-Path $InstallPath 197 | 198 | $ComposerBatch = "${InstallPath}\composer.bat" 199 | $ComposerPhar = "${InstallPath}\composer.phar" 200 | 201 | if (-not (Test-Path -Path $ComposerPhar)) { 202 | DownloadFile "https://getcomposer.org/composer.phar" "${ComposerPhar}" 203 | 204 | Write-Output '@echo off' | Out-File -Encoding "ASCII" $ComposerBatch 205 | Write-Output "${PhpInstallPath}\php.exe `"${ComposerPhar}`" %*" | Out-File -Encoding "ASCII" -Append $ComposerBatch 206 | } 207 | } 208 | 209 | function EnablePhpExtension { 210 | param ( 211 | [Parameter(Mandatory=$true)] [System.String] $Name, 212 | [Parameter(Mandatory=$false)] [System.String] $PhpInstallPath = 'C:\php', 213 | [Parameter(Mandatory=$false)] [System.String] $ExtPath = 'C:\php\ext', 214 | [Parameter(Mandatory=$false)] [System.String] $PrintableName = '' 215 | ) 216 | 217 | $FullyQualifiedExtensionPath = "${ExtPath}\php_${Name}.dll" 218 | 219 | $IniFile = "${PhpInstallPath}\php.ini" 220 | $PhpExe = "${PhpInstallPath}\php.exe" 221 | 222 | if (-not (Test-Path $IniFile)) { 223 | throw "Unable to locate ${IniFile}" 224 | } 225 | 226 | if (-not (Test-Path "${ExtPath}")) { 227 | throw "Unable to locate ${ExtPath} direcory" 228 | } 229 | 230 | Write-Debug "Add `"extension = ${FullyQualifiedExtensionPath}`" to the ${IniFile}" 231 | Write-Output "extension = ${FullyQualifiedExtensionPath}" | Out-File -Encoding "ASCII" -Append $IniFile 232 | 233 | if (Test-Path -Path "${PhpExe}") { 234 | if ($PrintableName) { 235 | Write-Debug "Minimal load test using command: ${PhpExe} --ri `"${PrintableName}`"" 236 | $Result = (& "${PhpExe}" --ri "${PrintableName}") 237 | } else { 238 | Write-Debug "Minimal load test using command: ${PhpExe} --ri ${Name}" 239 | $Result = (& "${PhpExe}" --ri $Name) 240 | } 241 | 242 | $ExitCode = $LASTEXITCODE 243 | if ($ExitCode -ne 0) { 244 | throw "An error occurred while enabling ${Name} at ${IniFile}. ${Result}" 245 | } 246 | } 247 | } 248 | 249 | function TuneUpPhp { 250 | param ( 251 | [Parameter(Mandatory=$false)] [System.String] $MemoryLimit = '256M', 252 | [Parameter(Mandatory=$false)] [System.String[]] $DefaultExtensions = @(), 253 | [Parameter(Mandatory=$false)] [System.String] $IniFile = 'C:\php\php.ini', 254 | [Parameter(Mandatory=$false)] [System.String] $ExtPath = 'C:\php\ext' 255 | ) 256 | 257 | Write-Debug "Tune up PHP using file `"${IniFile}`"" 258 | 259 | if (-not (Test-Path $IniFile)) { 260 | throw "Unable to locate ${IniFile} file" 261 | } 262 | 263 | if (-not (Test-Path $ExtPath)) { 264 | throw "Unable to locate ${ExtPath} direcory" 265 | } 266 | 267 | Write-Output "" | Out-File -Encoding "ASCII" -Append $IniFile 268 | 269 | Write-Output "extension_dir = ${ExtPath}" | Out-File -Encoding "ASCII" -Append $IniFile 270 | Write-Output "memory_limit = ${MemoryLimit}" | Out-File -Encoding "ASCII" -Append $IniFile 271 | 272 | if ($DefaultExtensions.count -gt 0) { 273 | Write-Output "" | Out-File -Encoding "ASCII" -Append $IniFile 274 | 275 | foreach ($Ext in $DefaultExtensions) { 276 | Write-Output "extension = php_${Ext}.dll" | Out-File -Encoding "ASCII" -Append $IniFile 277 | } 278 | } 279 | } 280 | 281 | function PrepareReleaseNote { 282 | param ( 283 | [Parameter(Mandatory=$true)] [System.String] $PhpVersion, 284 | [Parameter(Mandatory=$true)] [System.String] $BuildType, 285 | [Parameter(Mandatory=$true)] [System.String] $Platform, 286 | [Parameter(Mandatory=$false)] [System.String] $ReleaseFile, 287 | [Parameter(Mandatory=$false)] [System.String] $ReleaseDirectory, 288 | [Parameter(Mandatory=$false)] [System.String] $BasePath 289 | ) 290 | 291 | $Destination = "${BasePath}\${ReleaseDirectory}" 292 | 293 | if (-not (Test-Path $Destination)) { 294 | New-Item -ItemType Directory -Force -Path "${Destination}" | Out-Null 295 | } 296 | 297 | $ReleaseFile = "${Destination}\${ReleaseFile}" 298 | $ReleaseDate = Get-Date -Format o 299 | 300 | $Image = $Env:APPVEYOR_BUILD_WORKER_IMAGE 301 | $Version = $Env:APPVEYOR_BUILD_VERSION 302 | $Commit = $Env:APPVEYOR_REPO_COMMIT 303 | $CommitDate = $Env:APPVEYOR_REPO_COMMIT_TIMESTAMP 304 | 305 | Write-Output "Release date: ${ReleaseDate}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 306 | Write-Output "Release version: ${Version}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 307 | Write-Output "Git commit: ${Commit}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 308 | Write-Output "Commit date: ${CommitDate}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 309 | Write-Output "Build type: ${BuildType}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 310 | Write-Output "Platform: ${Platform}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 311 | Write-Output "Target PHP version: ${PhpVersion}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 312 | Write-Output "Build worker image: ${Image}" | Out-File -Encoding "ASCII" -Append "${ReleaseFile}" 313 | } 314 | 315 | function PrepareReleasePackage { 316 | param ( 317 | [Parameter(Mandatory=$true)] [System.String] $PhpVersion, 318 | [Parameter(Mandatory=$true)] [System.String] $BuildType, 319 | [Parameter(Mandatory=$true)] [System.String] $Platform, 320 | [Parameter(Mandatory=$false)] [System.String] $ZipballName = '', 321 | [Parameter(Mandatory=$false)] [System.String[]] $ReleaseFiles = @(), 322 | [Parameter(Mandatory=$false)] [System.String] $ReleaseFile = 'RELEASE.txt', 323 | [Parameter(Mandatory=$false)] [System.Boolean] $ConverMdToHtml = $false, 324 | [Parameter(Mandatory=$false)] [System.String] $BasePath = '.' 325 | ) 326 | 327 | $BasePath = Resolve-Path $BasePath 328 | $ReleaseDirectory = "${Env:APPVEYOR_PROJECT_NAME}-${Env:APPVEYOR_BUILD_ID}-${Env:APPVEYOR_JOB_ID}-${Env:APPVEYOR_JOB_NUMBER}" 329 | 330 | PrepareReleaseNote ` 331 | -PhpVersion $PhpVersion ` 332 | -BuildType $BuildType ` 333 | -Platform $Platform ` 334 | -ReleaseFile $ReleaseFile ` 335 | -ReleaseDirectory $ReleaseDirectory ` 336 | -BasePath $BasePath 337 | 338 | $ReleaseDestination = "${BasePath}\${ReleaseDirectory}" 339 | 340 | $CurrentPath = Resolve-Path '.' 341 | 342 | if ($ConverMdToHtml) { 343 | InstallReleaseDependencies 344 | FormatReleaseFiles -ReleaseDirectory $ReleaseDirectory 345 | } 346 | 347 | if ($ReleaseFiles.count -gt 0) { 348 | foreach ($File in $ReleaseFiles) { 349 | Copy-Item "${File}" "${ReleaseDestination}" 350 | Write-Debug "Copy ${File} to ${ReleaseDestination}" 351 | } 352 | } 353 | 354 | if (!$ZipballName) { 355 | if (!$Env:RELEASE_ZIPBALL) { 356 | throw "Required parameter `"ZipballName`" is missing" 357 | } else { 358 | $ZipballName = $Env:RELEASE_ZIPBALL; 359 | } 360 | } 361 | 362 | Ensure7ZipIsInstalled 363 | 364 | Set-Location "${ReleaseDestination}" 365 | $Output = (& 7z a "${ZipballName}.zip" *) 366 | $ExitCode = $LASTEXITCODE 367 | 368 | $DirectoryContents = Get-ChildItem -Path "${ReleaseDestination}" 369 | Write-Debug ($DirectoryContents | Out-String) 370 | 371 | if ($ExitCode -ne 0) { 372 | Set-Location "${CurrentPath}" 373 | throw "An error occurred while creating release zippbal: `"${ZipballName}`". ${Output}" 374 | } 375 | 376 | Move-Item "${ZipballName}.zip" -Destination "${BasePath}" 377 | Set-Location "${CurrentPath}" 378 | } 379 | 380 | function FormatReleaseFiles { 381 | param ( 382 | [Parameter(Mandatory=$true)] [System.String] $ReleaseDirectory, 383 | [Parameter(Mandatory=$false)] [System.String] $BasePath = '.' 384 | ) 385 | 386 | EnsurePandocIsInstalled 387 | 388 | $CurrentPath = (Get-Item -Path ".\" -Verbose).FullName 389 | 390 | $BasePath = Resolve-Path $BasePath 391 | Set-Location "${BasePath}" 392 | 393 | Get-ChildItem (Get-Item -Path ".\" -Verbose).FullName *.md | 394 | ForEach-Object{ 395 | $BaseName = $_.BaseName 396 | pandoc -f markdown -t html5 "${BaseName}.md" > "${BasePath}\${ReleaseDirectory}\${BaseName}.html" 397 | } 398 | 399 | Set-Location "${CurrentPath}" 400 | } 401 | 402 | function SetupPhpVersionString { 403 | param ( 404 | [Parameter(Mandatory=$true)] [String] $Pattern 405 | ) 406 | 407 | $RemoteUrl = 'http://windows.php.net/downloads/releases/sha256sum.txt' 408 | $Destination = "${Env:Temp}\php-sha256sum.txt" 409 | 410 | if (-not (Test-Path $Destination)) { 411 | DownloadFile $RemoteUrl $Destination 412 | } 413 | 414 | $VersionString = Get-Content $Destination | Where-Object { 415 | $_ -match "php-($Pattern\.\d+)-src" 416 | } | ForEach-Object { $matches[1] } 417 | 418 | if ($VersionString -NotMatch '\d+\.\d+\.\d+' -or $null -eq $VersionString) { 419 | throw "Unable to obtain PHP version string using pattern 'php-($Pattern\.\d+)-src'" 420 | } 421 | 422 | Write-Output $VersionString.Split(' ')[-1] 423 | } 424 | 425 | function SetupPrerequisites { 426 | Ensure7ZipIsInstalled 427 | EnsureRequiredDirectoriesPresent -Directories C:\Downloads 428 | } 429 | 430 | function Ensure7ZipIsInstalled { 431 | if (-not (Get-Command "7z" -ErrorAction SilentlyContinue)) { 432 | $7zipInstallationDirectory = "${Env:ProgramFiles}\7-Zip" 433 | 434 | if (-not (Test-Path "${7zipInstallationDirectory}")) { 435 | throw "The 7-zip file archiver is needed to use this module" 436 | } 437 | 438 | $Env:Path += ";$7zipInstallationDirectory" 439 | } 440 | } 441 | 442 | function InstallReleaseDependencies { 443 | EnsureChocolateyIsInstalled 444 | $Output = (choco install -y --no-progress pandoc) 445 | $ExitCode = $LASTEXITCODE 446 | 447 | if ($ExitCode -ne 0) { 448 | throw "An error occurred while installing pandoc. ${Output}" 449 | } 450 | } 451 | 452 | function EnsureChocolateyIsInstalled { 453 | if (-not (Get-Command "choco" -ErrorAction SilentlyContinue)) { 454 | $ChocolateyInstallationDirectory = "${Env:ChocolateyInstall}\bin" 455 | 456 | if (-not (Test-Path "$ChocolateyInstallationDirectory")) { 457 | throw "The choco is needed to use this module" 458 | } 459 | 460 | $Env:Path += ";$ChocolateyInstallationDirectory" 461 | } 462 | } 463 | 464 | function EnsurePandocIsInstalled { 465 | if (-not (Get-Command "pandoc" -ErrorAction SilentlyContinue)) { 466 | $PandocInstallationDirectory = "${Env:ChocolateyInstall}\bin" 467 | 468 | if (-not (Test-Path "$PandocInstallationDirectory")) { 469 | throw "The pandoc is needed to use this module" 470 | } 471 | 472 | $Env:Path += ";$PandocInstallationDirectory" 473 | } 474 | 475 | $Output = (& "pandoc" -v) 476 | $ExitCode = $LASTEXITCODE 477 | 478 | if ($ExitCode -ne 0) { 479 | throw "An error occurred while self testing pandoc. ${Output}" 480 | } 481 | } 482 | 483 | function EnsureRequiredDirectoriesPresent { 484 | param ( 485 | [Parameter(Mandatory=$true)] [String[]] $Directories, 486 | [Parameter(Mandatory=$false)] [String] $Prefix = "" 487 | ) 488 | 489 | foreach ($Dir in $Directories) { 490 | if (-not (Test-Path $Dir)) { 491 | if ($Prefix) { 492 | New-Item -ItemType Directory -Force -Path "${Prefix}\${Dir}" | Out-Null 493 | } else { 494 | New-Item -ItemType Directory -Force -Path "${Dir}" | Out-Null 495 | } 496 | 497 | } 498 | } 499 | } 500 | 501 | function DownloadFile { 502 | param ( 503 | [Parameter(Mandatory=$true)] [System.String] $RemoteUrl, 504 | [Parameter(Mandatory=$true)] [System.String] $Destination 505 | ) 506 | 507 | $RetryMax = 5 508 | $RetryCount = 0 509 | $Completed = $false 510 | 511 | $WebClient = New-Object System.Net.WebClient 512 | $WebClient.Headers.Add('User-Agent', 'AppVeyor PowerShell Script') 513 | 514 | Write-Debug "Downloading: '${RemoteUrl}' => '${Destination}' ..." 515 | 516 | while (-not $Completed) { 517 | try { 518 | $WebClient.DownloadFile($RemoteUrl, $Destination) 519 | $Completed = $true 520 | } catch { 521 | if ($RetryCount -ge $RetryMax) { 522 | $ErrorMessage = $_.Exception.Message 523 | Write-Error -Message "${ErrorMessage}" 524 | $Completed = $true 525 | } else { 526 | $RetryCount++ 527 | } 528 | } 529 | } 530 | } 531 | 532 | function Expand-Item7zip { 533 | param( 534 | [Parameter(Mandatory=$true)] [System.String] $Archive, 535 | [Parameter(Mandatory=$true)] [System.String] $Destination 536 | ) 537 | 538 | if (-not (Test-Path -Path $Archive -PathType Leaf)) { 539 | throw "Specified archive file does not exist: ${Archive}" 540 | } 541 | 542 | Write-Debug "Unzipping ${Archive} to ${Destination} ..." 543 | 544 | if (-not (Test-Path -Path $Destination -PathType Container)) { 545 | New-Item $Destination -ItemType Directory | Out-Null 546 | } 547 | 548 | $ExitCode = 0 549 | 550 | if ("${Archive}" -like "*.tgz") { 551 | $Output = (& 7z x -tgzip "$Archive" -bd -y "-o${Env:Temp}") 552 | $ExitCode = $LASTEXITCODE 553 | 554 | if ($ExitCode -eq 0) { 555 | $Archive = "${Env:Temp}/{0}.tar" -f [System.IO.Path]::GetFileNameWithoutExtension($Archive) 556 | } 557 | } 558 | 559 | if ($ExitCode -eq 0) { 560 | $Output = (& 7z x "$Archive" "-o$Destination" -aoa -bd -y -r) 561 | $ExitCode = $LASTEXITCODE 562 | } 563 | 564 | if ($ExitCode -ne 0) { 565 | throw "An error occurred while unzipping '${Archive}' to '${Destination}'. ${Output}" 566 | } 567 | } 568 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .deps 2 | acinclude.m4 3 | aclocal.m4 4 | autom4te.cache/ 5 | build/ 6 | config.h 7 | config.log 8 | config.nice 9 | config.status 10 | config.guess 11 | config.h.in 12 | config.sub 13 | configure 14 | configure.in 15 | install-sh 16 | ltmain.sh 17 | missing 18 | mkinstalldirs 19 | run-tests.php 20 | Makefile 21 | Makefile.* 22 | !Makefile.frag 23 | libtool 24 | *~ 25 | modules/ 26 | .libs/ 27 | *.la 28 | *.lo 29 | php_test_results_*.txt 30 | tests/* 31 | !tests/*.phpt 32 | configure.ac 33 | /cmake-* 34 | /run-php 35 | *.tgz 36 | 37 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | env: 2 | EXTNAME: base58 3 | 4 | language: php 5 | php: 6 | - 7.2 7 | - 7.3 8 | - 7.4 9 | - 8.0 10 | 11 | branches: 12 | only: 13 | - master 14 | - travis 15 | - /^v\d+\.\d+\.\d+$/ 16 | 17 | install: 18 | - phpize 19 | - ./configure 20 | - make 21 | 22 | before_script: 23 | make install 24 | 25 | script: 26 | make test 27 | 28 | after_failure: 29 | - | 30 | for FILE in $(find tests -name '*.diff'); do 31 | echo $FILE 32 | cat FILE 33 | echo 34 | done 35 | 36 | before_deploy: 37 | - pecl package 38 | - export RELEASE_PACKAGE=$(ls "$EXTNAME"-*.tgz) 39 | 40 | deploy: 41 | provider: releases 42 | api_key: 43 | secure: "k/GzEf1hM424VqbIE2qSaGA7D5DsITF5l5G2s2VEwGqrb7qThWFTFXmM72u+B7CITkabUu6CwPh7lMgVr/IrZhjOVkxv99qyOkN87v8MR+rx5A6o7R5h/NrqiBQMDVNt2TAFO78ADxj0ek2bCR5UZxHpnWhz5R6YVYC14bUmscNaxtxiQMPtdudcM7SRiZCBZ3DwMylKKdqWdnvBjKj4ZJo/AwTNa0dVnv0Vn5rWONc8T3Rh3bMIHIsf0Hxq7BxNwpBMyG1EX/2q6z899X9D7SIXCItYnEkCxB5WSOqpCh5pl+1FvCllxzXSuRUrCPl5buqwDauF/oJqSXaGHhSt5/P3ez7axzHFnGiKMoc9H71pzxdCjrftiHmHjvK1NI52l9yTr1hR/MuDGWelC+NWVJjm336owND9wq1l+VfeFx4e7DhaSD47fXCj+zQpZ9+j5qnnj0EWCssVPt1MB+cpEZ0k/1UgIqE+Qgr6WO66kvsOQWYMARQu7/f3qVNarXpJ4pjbs140tSeKlPRDXHb7xtLsy8ulMqpyhEPKApnSk4r0QCH7XMd6NY+SCiFOwfJjaz8F4EDHBjZkH/cuSumL9IoSkkiwwH2daV8kgE8jNus4gGAZWbAtR5W3rMOlCVrIRIBQ4uZs6nDogzfyWGPPHriUX3LLTcx60zMrX8JdN8Y=" 44 | file: "$RELEASE_PACKAGE" 45 | skip_cleanup: true 46 | name: "$TRAVIS_TAG" 47 | prerelease: false 48 | on: 49 | tags: true 50 | ` -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.8) 2 | project(base58 C) 3 | 4 | add_compile_definitions(HAVE_BASE58) 5 | 6 | set(SOURCE_FILES php_base58 base58.c lib/libbase58.c) 7 | 8 | execute_process ( 9 | COMMAND php-config --include-dir 10 | OUTPUT_VARIABLE PHP_SOURCE 11 | ) 12 | string(REGEX REPLACE "\n$" "" PHP_SOURCE "${PHP_SOURCE}") 13 | 14 | message("Using source directory: ${PHP_SOURCE}") 15 | 16 | include_directories(${PHP_SOURCE}) 17 | include_directories(${PHP_SOURCE}/main) 18 | include_directories(${PHP_SOURCE}/Zend) 19 | include_directories(${PHP_SOURCE}/TSRM) 20 | include_directories(${PROJECT_SOURCE_DIR}) 21 | 22 | add_custom_target(configure 23 | COMMAND phpize && ./configure 24 | DEPENDS ${SOURCE_FILES} 25 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) 26 | 27 | add_library(___ EXCLUDE_FROM_ALL ${SOURCE_FILES}) 28 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | LTO Network 2 | Arnold Daniels 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Arnold Daniels 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. 22 | -------------------------------------------------------------------------------- /Makefile.frag: -------------------------------------------------------------------------------- 1 | clean-tests: 2 | rm -f tests/*.diff tests/*.exp tests/*.log tests/*.out tests/*.php tests/*.sh 3 | 4 | mrproper: clean clean-tests 5 | rm -rf autom4te.cache build modules vendor 6 | rm -f acinclude.m4 aclocal.m4 config.guess config.h config.h.in config.log config.nice config.status config.sub \ 7 | configure configure.ac install-sh libtool ltmain.sh Makefile Makefile.fragments Makefile.global \ 8 | Makefile.objects missing mkinstalldirs run-tests.php *~ 9 | 10 | info: $(all_targets) 11 | "$(PHP_EXECUTABLE)" -d "extension=$(phplibdir)/$(PHP_PECL_EXTENSION).so" --re "$(PHP_PECL_EXTENSION)" 12 | 13 | package.xml: php_$(PHP_PECL_EXTENSION).h 14 | $(PHP_EXECUTABLE) build-packagexml.php 15 | 16 | .PHONY: all clean install distclean test prof-gen prof-clean prof-use clean-tests mrproper info 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![improved PHP library](https://user-images.githubusercontent.com/100821/46372249-e5eb7500-c68a-11e8-801a-2ee57da3e5e3.png) 2 | 3 | # Base58 PHP extension 4 | 5 | [![Build Status](https://api.travis-ci.org/jasny/base58-php-ext.svg?branch=master)](https://travis-ci.org/jasny/base58-php-ext) 6 | [![Build status](https://ci.appveyor.com/api/projects/status/7rof1vr8mv4kam17/branch/master?svg=true)](https://ci.appveyor.com/project/jasny/base58-php-ext/branch/master) 7 | 8 | PHP extension for base58 encoding and decoding using the Bitcoin alphabet. 9 | 10 | Using this extension is about 100 times faster than using userspace functions. 11 | 12 | ## Requirements 13 | 14 | * PHP 7.x or 8.x 15 | 16 | ## Installation 17 | 18 | The extension is [available from pecl](https://pecl.php.net/package/base58). 19 | 20 | pecl install base58-beta 21 | 22 | ### Manual build 23 | 24 | Instead of installing this extension from pecl, you can build it manually 25 | 26 | phpize 27 | ./configure --with-base58 28 | make 29 | make install 30 | 31 | Add the following line to your `php.ini` 32 | 33 | extension=base58.so 34 | 35 | ## Functions 36 | 37 | ### base58_encode 38 | 39 | Base58 encode a string. 40 | 41 | string base58_encode(string $data) 42 | 43 | Triggers an `E_WARNING` and returns `false` if string can't be encoded. 44 | 45 | ### base58_encode 46 | 47 | Decode a base58 encoded string. 48 | 49 | string base58_decode(string $data) 50 | 51 | Triggers an `E_WARNING` and returns `false` if string can't be decoded. 52 | 53 | ## Caveat 54 | 55 | To encode a hash, make sure you're using the raw hash and not a hexidecimal string. 56 | 57 | $rawHash = hash('sha256', 'some string', true); // The `true` makes the function return a raw hash 58 | $encodedHash = base58_encode($rawHash); 59 | 60 | 61 | ## Benchmark 62 | 63 | The extension is run in test `Base58ExtEvent`. The `Base58BCMathEvent` and `Base58GMPEvent` tests use 64 | the `StephenHill\Base58` PHP library. 65 | 66 | ``` 67 | StephenHill\Benchmarks\Base16Event 68 | Method Name Iterations Average Time Ops/second 69 | ------------ ------------ -------------- ------------- 70 | encodeBase16: [10,000 ] [0.0000001919985] [5,208,374.51881] 71 | decodeBase16: [10,000 ] [0.0000004031897] [2,480,222.34049] 72 | 73 | 74 | StephenHill\Benchmarks\Base58BCMathEvent 75 | Method Name Iterations Average Time Ops/second 76 | ------------ ------------ -------------- ------------- 77 | encodeBase58: [10,000 ] [0.0000484058857] [20,658.64482] 78 | decodeBase58: [10,000 ] [0.0000523419857] [19,105.12157] 79 | 80 | 81 | StephenHill\Benchmarks\Base58ExtEvent 82 | Method Name Iterations Average Time Ops/second 83 | ------------ ------------ -------------- ------------- 84 | encodeBase58: [10,000 ] [0.0000003235340] [3,090,865.14370] 85 | decodeBase58: [10,000 ] [0.0000003539085] [2,825,588.79008] 86 | 87 | 88 | StephenHill\Benchmarks\Base58GMPEvent 89 | Method Name Iterations Average Time Ops/second 90 | ------------ ------------ -------------- ------------- 91 | encodeBase58: [10,000 ] [0.0000255326509] [39,165.53757] 92 | decodeBase58: [10,000 ] [0.0000418104410] [23,917.47075] 93 | 94 | 95 | StephenHill\Benchmarks\Base64Event 96 | Method Name Iterations Average Time Ops/second 97 | ------------ ------------ -------------- ------------- 98 | encodeBase64: [10,000 ] [0.0000003066778] [3,260,750.99122] 99 | decodeBase64: [10,000 ] [0.0000003187656] [3,137,100.97233] 100 | ``` 101 | 102 | -------------------------------------------------------------------------------- /autoconf/pecl.m4: -------------------------------------------------------------------------------- 1 | 2 | yes() { 3 | true 4 | } 5 | no() { 6 | false 7 | } 8 | dnl 9 | dnl PECL_INIT(name) 10 | dnl 11 | dnl Start configuring the PECL extension. 12 | dnl 13 | AC_DEFUN([PECL_INIT], [dnl 14 | m4_define([PECL_NAME],[$1])dnl 15 | ])dnl 16 | dnl 17 | dnl 18 | dnl PECL_VAR(name) 19 | dnl 20 | AC_DEFUN([PECL_VAR], [dnl 21 | AS_TR_CPP([PHP_]PECL_NAME[_$1])dnl 22 | ])dnl 23 | dnl 24 | dnl PECL_CACHE_VAR(name) 25 | dnl 26 | AC_DEFUN([PECL_CACHE_VAR], [dnl 27 | AS_TR_SH([PECL_cv_$1])dnl 28 | ])dnl 29 | dnl 30 | dnl PECL_SAVE_VAR(name) 31 | dnl 32 | AC_DEFUN([PECL_SAVE_VAR], [dnl 33 | AS_TR_SH([PECL_sv_$1])dnl 34 | ])dnl 35 | dnl 36 | dnl PECL_DEFINE(what, to[, desc]) 37 | dnl 38 | AC_DEFUN([PECL_DEFINE], [dnl 39 | AC_DEFINE(PECL_VAR([$1]), ifelse([$2],,1,[$2]), ifelse([$3],,[ ],[$3])) 40 | ])dnl 41 | dnl 42 | dnl PECL_DEFINE_UQ(what, to[, desc]) 43 | dnl 44 | AC_DEFUN([PECL_DEFINE_UQ], [dnl 45 | AC_DEFINE_UNQUOTED(PECL_VAR([$1]), [$2], ifelse([$3],,[ ],[$3])) 46 | ])dnl 47 | dnl 48 | dnl PECL_DEFINE_SH(what, to[, desc]) 49 | dnl 50 | AC_DEFUN([PECL_DEFINE_SH], [dnl 51 | PECL_VAR([$1])=$2 52 | PECL_DEFINE_UQ([$1], [$2], [$3]) 53 | ]) 54 | dnl 55 | dnl PECL_DEFINE_FN(fn) 56 | dnl 57 | AC_DEFUN([PECL_DEFINE_FN], [ 58 | AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1], [ ]) 59 | ]) 60 | dnl 61 | dnl PECL_SAVE_ENV(var, ns) 62 | dnl 63 | AC_DEFUN([PECL_SAVE_ENV], [ 64 | PECL_SAVE_VAR([$2_$1])=[$]$1 65 | ]) 66 | dnl 67 | dnl PECL_RESTORE_ENV(var, ns) 68 | dnl 69 | AC_DEFUN([PECL_RESTORE_ENV], [ 70 | $1=$PECL_SAVE_VAR([$2_$1]) 71 | ]) 72 | dnl 73 | dnl PECL_EVAL_LIBLINE(libline) 74 | dnl 75 | AC_DEFUN([PECL_EVAL_LIBLINE], [ 76 | PECL_SAVE_ENV(ext_shared, pecl) 77 | ext_shared=no 78 | PHP_EVAL_LIBLINE([$1], _pecl_eval_libline_dummy) 79 | PECL_RESTORE_ENV(ext_shared, pecl) 80 | ]) 81 | dnl 82 | dnl PECL_PROG_EGREP 83 | dnl 84 | dnl Checks for an egrep. Defines $EGREP. 85 | dnl 86 | AC_DEFUN([PECL_PROG_EGREP], [ 87 | ifdef([AC_PROG_EGREP], [ 88 | AC_PROG_EGREP 89 | ], [ 90 | AC_CHECK_PROG(EGREP, egrep, egrep) 91 | ]) 92 | ]) 93 | dnl 94 | dnl PECL_PROG_AWK 95 | dnl 96 | dnl Checks for an awk. Defines $AWK. 97 | dnl 98 | AC_DEFUN([PECL_PROG_AWK], [ 99 | ifdef([AC_PROG_AWK], [ 100 | AC_PROG_AWK 101 | ], [ 102 | AC_CHECK_PROG(AWK, awk, awk) 103 | ]) 104 | ]) 105 | dnl 106 | dnl PECL_PROG_SED 107 | dnl 108 | dnl Checks for the sed program. Defines $SED. 109 | dnl 110 | AC_DEFUN([PECL_PROG_SED], [ 111 | ifdef([AC_PROG_SED], [ 112 | AC_PROG_SED 113 | ], [ 114 | ifdef([LT_AC_PROG_SED], [ 115 | LT_AC_PROG_SED 116 | ], [ 117 | AC_CHECK_PROG(SED, sed, sed) 118 | ]) 119 | ]) 120 | ]) 121 | dnl 122 | dnl PECL_PROG_PKGCONFIG 123 | dnl 124 | dnl Checks for pkg-config program and defines $PKG_CONFIG (to false if not found). 125 | dnl 126 | AC_DEFUN([PECL_PROG_PKGCONFIG], [ 127 | if test -z "$PKG_CONFIG"; then 128 | AC_PATH_PROG([PKG_CONFIG], [pkg-config], [false]) 129 | fi 130 | ]) 131 | dnl 132 | dnl PECL_HAVE_PHP_EXT(name[, code-if-yes[, code-if-not]]) 133 | dnl 134 | dnl Check whether ext/$name is enabled in $PHP_EXECUTABLE (PECL build) 135 | dnl or if $PHP_ is defined to anything else than "no" (in-tree build). 136 | dnl Defines shell var PECL_VAR(HAVE_EXT_) to true or false. 137 | dnl 138 | AC_DEFUN([PECL_HAVE_PHP_EXT], [ 139 | AC_REQUIRE([PECL_PROG_EGREP])dnl 140 | AC_CACHE_CHECK([whether ext/$1 is enabled], PECL_CACHE_VAR([HAVE_EXT_$1]), [ 141 | PECL_CACHE_VAR([HAVE_EXT_$1])=no 142 | if test -x "$PHP_EXECUTABLE"; then 143 | if $PHP_EXECUTABLE -m | $EGREP -q ^$1\$; then 144 | PECL_CACHE_VAR([HAVE_EXT_$1])=yes 145 | fi 146 | elif test -n "$AS_TR_CPP([PHP_$1])" && test "$AS_TR_CPP([PHP_$1])" != "no"; then 147 | PECL_CACHE_VAR([HAVE_EXT_$1])=yes 148 | fi 149 | ]) 150 | if $PECL_CACHE_VAR([HAVE_EXT_$1]); then 151 | PECL_VAR([HAVE_EXT_$1])=true 152 | PECL_DEFINE([HAVE_EXT_$1]) 153 | $2 154 | else 155 | PECL_VAR([HAVE_EXT_$1])=false 156 | $3 157 | fi 158 | ]) 159 | dnl 160 | dnl PECL_HAVE_PHP_EXT_HEADER(ext[, header]) 161 | dnl 162 | dnl Check where to find a header for ext and add the found dir to $INCLUDES. 163 | dnl If header is not specified php_.h is assumed. 164 | dnl Defines shell var PHP__EXT__INCDIR to the found dir. 165 | dnl Defines PHP__HAVE_
to the found path. 166 | dnl 167 | AC_DEFUN([PECL_HAVE_PHP_EXT_HEADER], [dnl 168 | AC_REQUIRE([PECL_PROG_SED])dnl 169 | m4_define([EXT_HEADER], ifelse([$2],,php_$1.h,[$2]))dnl 170 | AC_CACHE_CHECK([for EXT_HEADER of ext/$1], PECL_CACHE_VAR([EXT_$1]_INCDIR), [ 171 | for i in $(printf "%s" "$INCLUDES" | $SED -e's/-I//g') $abs_srcdir ../$1; do 172 | if test -d $i; then 173 | for j in $i/EXT_HEADER $i/ext/$1/EXT_HEADER; do 174 | if test -f $j; then 175 | PECL_CACHE_VAR([EXT_$1]_INCDIR)=$(dirname "$j") 176 | break 177 | fi 178 | done 179 | fi 180 | done 181 | ]) 182 | PECL_VAR([EXT_$1]_INCDIR)=$PECL_CACHE_VAR([EXT_$1]_INCDIR) 183 | PHP_ADD_INCLUDE([$PECL_VAR([EXT_$1]_INCDIR)]) 184 | PECL_DEFINE_UQ([HAVE_]EXT_HEADER, "$PECL_VAR([EXT_$1]_INCDIR)/EXT_HEADER") 185 | ]) 186 | dnl 187 | dnl PECL_HAVE_CONST(header, const[, type=int[, code-if-yes[, code-if-mno]]]) 188 | dnl 189 | AC_DEFUN([PECL_HAVE_CONST], [dnl 190 | AC_REQUIRE([PECL_PROG_EGREP])dnl 191 | AC_CACHE_CHECK([for $2 in $1], PECL_CACHE_VAR([HAVE_$1_$2]), [ 192 | AC_TRY_COMPILE([ 193 | #include "$1" 194 | ], [ 195 | ]ifelse([$3],,int,[$3])[ _c = $2; 196 | (void) _c; 197 | ], [ 198 | PECL_CACHE_VAR([HAVE_$1_$2])=yes 199 | ], [ 200 | PECL_CACHE_VAR([HAVE_$1_$2])=no 201 | ]) 202 | ]) 203 | if $PECL_CACHE_VAR([HAVE_$1_$2]); then 204 | PECL_DEFINE([HAVE_$2]) 205 | $4 206 | else 207 | ifelse([$5],,:,[$5]) 208 | fi 209 | ]) 210 | dnl 211 | dnl _PECL_TR_VERSION(version) 212 | dnl 213 | AC_DEFUN([_PECL_TR_VERSION], [dnl 214 | AC_REQUIRE([PECL_PROG_AWK])dnl 215 | $(printf "%s" $1 | $AWK -F "[.]" '{print $[]1*1000000 + $[]2*10000 + $[]3*100 + $[]4}') 216 | ]) 217 | dnl 218 | dnl PECL_CHECKED_VERSION(name) 219 | dnl 220 | dnl Shell var name of an already checked version. 221 | dnl 222 | AC_DEFUN([PECL_CHECKED_VERSION], [PECL_VAR([$1][_VERSION])]) 223 | dnl 224 | dnl PECL_HAVE_VERSION(name, min-version[, code-if-yes[, code-if-not]]) 225 | dnl 226 | dnl Perform a min-version check while in an PECL_CHECK_* block. 227 | dnl Expands AC_MSG_ERROR when code-if-not is empty and the version check fails. 228 | dnl 229 | AC_DEFUN([PECL_HAVE_VERSION], [ 230 | aversion=_PECL_TR_VERSION([$PECL_CHECKED_VERSION([$1])]) 231 | mversion=_PECL_TR_VERSION([$2]) 232 | AC_MSG_CHECKING([whether $1 version $PECL_CHECKED_VERSION([$1]) >= $2]) 233 | if test -z "$aversion" || test "$aversion" -lt "$mversion"; then 234 | ifelse($4,,AC_MSG_ERROR([no]), [ 235 | AC_MSG_RESULT([no]) 236 | $4 237 | ]) 238 | else 239 | AC_MSG_RESULT([ok]) 240 | $3 241 | fi 242 | ]) 243 | dnl 244 | dnl PECL_CHECK_CUSTOM(name, path, header, lib, version) 245 | dnl 246 | AC_DEFUN([PECL_CHECK_CUSTOM], [ 247 | PECL_SAVE_ENV([CPPFLAGS], [$1]) 248 | PECL_SAVE_ENV([LDFLAGS], [$1]) 249 | PECL_SAVE_ENV([LIBS], [$1]) 250 | 251 | AC_MSG_CHECKING([for $1]) 252 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_prefix]), [ 253 | for path in $2 /usr/local /usr /opt; do 254 | if test "$path" = "" || test "$path" = "yes" || test "$path" = "no"; then 255 | continue 256 | elif test -f "$path/include/$3"; then 257 | PECL_CACHE_VAR([$1_prefix])="$path" 258 | break 259 | fi 260 | done 261 | ]) 262 | if test -n "$PECL_CACHE_VAR([$1_prefix])"; then 263 | CPPFLAGS="-I$PECL_CACHE_VAR([$1_prefix])/include" 264 | LDFLAGS="-L$PECL_CACHE_VAR([$1_prefix])/$PHP_LIBDIR" 265 | LIBS="-l$4" 266 | PECL_EVAL_LIBLINE([$LDFLAGS $LIBS]) 267 | 268 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_version]), [ 269 | pushd $PECL_CACHE_VAR([$1_prefix]) >/dev/null 270 | PECL_CACHE_VAR([$1_version])=$5 271 | popd >/dev/null 272 | ]) 273 | PECL_CHECKED_VERSION([$1])=$PECL_CACHE_VAR([$1_version]) 274 | 275 | if test -n "$PECL_CHECKED_VERSION([$1])"; then 276 | PECL_VAR([HAVE_$1])=true 277 | PECL_DEFINE([HAVE_$1]) 278 | PECL_DEFINE_UQ($1[_VERSION], "$PECL_CHECKED_VERSION([$1])") 279 | else 280 | PECL_VAR([HAVE_$1])=false 281 | fi 282 | else 283 | PECL_VAR([HAVE_$1])=false 284 | fi 285 | AC_MSG_RESULT([${PECL_CHECKED_VERSION([$1]):-no}]) 286 | ]) 287 | dnl 288 | dnl PECL_CHECK_CONFIG(name, prog-config, version-flag, cppflags-flag, ldflags-flag, libs-flag) 289 | dnl 290 | AC_DEFUN([PECL_CHECK_CONFIG], [ 291 | PECL_SAVE_ENV([CPPFLAGS], [$1]) 292 | PECL_SAVE_ENV([LDFLAGS], [$1]) 293 | PECL_SAVE_ENV([LIBS], [$1]) 294 | 295 | 296 | AC_MSG_CHECKING([for $1]) 297 | ifelse($2, [$PKG_CONFIG $1], [ 298 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_exists]), [ 299 | if $($2 --exists); then 300 | PECL_CACHE_VAR([$1_exists])=yes 301 | else 302 | PECL_CACHE_VAR([$1_exists])=no 303 | fi 304 | ]) 305 | if $PECL_CACHE_VAR([$1_exists]); then 306 | ]) 307 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_version]), [ 308 | PECL_CACHE_VAR([$1_version])=$($2 $3) 309 | ]) 310 | PECL_CHECKED_VERSION([$1])=$PECL_CACHE_VAR([$1_version]) 311 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_cppflags]), [ 312 | PECL_CACHE_VAR([$1_cppflags])=$($2 $4) 313 | ]) 314 | CPPFLAGS=$PECL_CACHE_VAR([$1_cppflags]) 315 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_ldflags]), [ 316 | PECL_CACHE_VAR([$1_ldflags])=$($2 $5) 317 | ]) 318 | LDFLAGS=$PECL_CACHE_VAR([$1_ldflags]) 319 | AC_CACHE_VAL(PECL_CACHE_VAR([$1_libs]), [ 320 | PECL_CACHE_VAR([$1_libs])=$($2 $6) 321 | ]) 322 | LIBS=$PECL_CACHE_VAR([$1_libs]) 323 | PECL_EVAL_LIBLINE([$LDFLAGS $LIBS]) 324 | ifelse($2, [$PKG_CONFIG $1], [ 325 | fi 326 | ]) 327 | 328 | if test -n "$PECL_CHECKED_VERSION([$1])"; then 329 | PECL_VAR([HAVE_$1])=true 330 | PECL_DEFINE([HAVE_$1]) 331 | PECL_DEFINE_UQ([$1_VERSION], "$PECL_CHECKED_VERSION([$1])") 332 | else 333 | PECL_VAR([HAVE_$1])=false 334 | fi 335 | 336 | AC_MSG_RESULT([${PECL_CHECKED_VERSION([$1]):-no}]) 337 | ]) 338 | dnl 339 | dnl PECL_CHECK_PKGCONFIG(pkg[, additional-pkg-config-path]) 340 | dnl 341 | AC_DEFUN([PECL_CHECK_PKGCONFIG], [dnl 342 | AC_REQUIRE([PECL_PROG_PKGCONFIG])dnl 343 | ifelse($2,,, [ 344 | PECL_SAVE_VAR(pkgconfig_path)="$PKG_CONFIG_PATH" 345 | if test -d "$2"; then 346 | export PKG_CONFIG_PATH="$2/lib/pkgconfig:$PKG_CONFIG_PATH" 347 | fi 348 | ]) 349 | PECL_CHECK_CONFIG([$1], [$PKG_CONFIG $1], [--modversion], [--cflags-only-I], [--libs-only-L], [--libs-only-l]) 350 | ifelse($2,,, [ 351 | PKG_CONFIG_PATH="$PECL_SAVE_VAR(pkgconfig_path)" 352 | ]) 353 | ]) 354 | dnl 355 | dnl PECL_CHECK_DONE(name, success[, incline, libline]) 356 | dnl 357 | AC_DEFUN([PECL_CHECK_DONE], [ 358 | if $2; then 359 | incline=$CPPFLAGS 360 | libline="$LDFLAGS $LIBS" 361 | PECL_DEFINE([HAVE_$1]) 362 | else 363 | incline=$3 364 | libline=$4 365 | fi 366 | 367 | PECL_RESTORE_ENV([CPPFLAGS], [$1]) 368 | PECL_RESTORE_ENV([LDFLAGS], [$1]) 369 | PECL_RESTORE_ENV([LIBS], [$1]) 370 | 371 | PHP_EVAL_INCLINE([$incline]) 372 | PHP_EVAL_LIBLINE([$libline], AS_TR_CPP(PECL_NAME[_SHARED_LIBADD])) 373 | ]) 374 | 375 | dnl 376 | dnl PECL_CHECK_CA([additional-ca-paths,[ additional-ca-bundles]]) 377 | dnl 378 | AC_DEFUN([PECL_CHECK_CA], [ 379 | AC_CACHE_CHECK([for default CA path], PECL_CACHE_VAR([CAPATH]), [ 380 | PECL_VAR([CAPATH])= 381 | for ca_path in $1 \ 382 | /etc/ssl/certs \ 383 | /System/Library/OpenSSL 384 | do 385 | # check if it's actually a hashed directory 386 | if test -d "$ca_path" && ls "$ca_path"/@<:@0-9a-f@:>@@<:@0-9a-f@:>@@<:@0-9a-f@:>@@<:@0-9a-f@:>@@<:@0-9a-f@:>@@<:@0-9a-f@:>@@<:@0-9a-f@:>@@<:@0-9a-f@:>@.0 >/dev/null 2>&1; then 387 | PECL_CACHE_VAR([CAPATH])=$ca_path 388 | break 389 | fi 390 | done 391 | ]) 392 | if test -n "$PECL_CACHE_VAR([CAPATH])"; then 393 | PECL_DEFINE_SH([CAPATH], "$PECL_CACHE_VAR([CAPATH])") 394 | fi 395 | 396 | AC_CACHE_CHECK([for default CA info], PECL_CACHE_VAR([CAINFO]), [ 397 | for ca_info in $2 \ 398 | /etc/ssl/{cert,ca-bundle}.pem \ 399 | /{etc,usr/share}/ssl/certs/ca-{bundle,ceritifcates}.crt \ 400 | /etc/{pki/ca-trust,ca-certificates}/extracted/pem/tls-ca-bundle.pem \ 401 | /etc/pki/tls/certs/ca-bundle{,.trust}.crt \ 402 | /usr/local/etc/{,open}ssl/cert.pem \ 403 | /usr/local/share/certs/ca-root-nss.crt \ 404 | /{usr,usr/local,opt}/local/share/curl/curl-ca-bundle.crt 405 | do 406 | if test -f "$ca_info"; then 407 | PECL_CACHE_VAR([CAINFO])=$ca_info 408 | break 409 | fi 410 | done 411 | ]) 412 | if test -n "$PECL_CACHE_VAR([CAINFO])"; then 413 | PECL_DEFINE_SH([CAINFO], "$PECL_CACHE_VAR([CAINFO])") 414 | fi 415 | ]) 416 | -------------------------------------------------------------------------------- /autoconf/php-executable.m4: -------------------------------------------------------------------------------- 1 | dnl 2 | dnl Symlink current php executable 3 | dnl 4 | AC_CONFIG_COMMANDS_POST([ 5 | ln -s "$PHP_EXECUTABLE" build/php 6 | ]) 7 | -------------------------------------------------------------------------------- /base58.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | Base58 PHP extension | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 2020 Arnold Daniels | 6 | +----------------------------------------------------------------------+ 7 | | Permission is hereby granted, free of charge, to any person | 8 | | obtaining a copy of this software and associated documentation files | 9 | | (the "Software"), to deal in the Software without restriction, | 10 | | including without limitation the rights to use, copy, modify, merge, | 11 | | publish, distribute, sublicense, and/or sell copies of the Software, | 12 | | and to permit persons to whom the Software is furnished to do so, | 13 | | subject to the following conditions: | 14 | | | 15 | | The above copyright notice and this permission notice shall be | 16 | | included in all copies or substantial portions of the Software. | 17 | | | 18 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 19 | | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 20 | | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 21 | | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | 22 | | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | 23 | | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | 24 | | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 25 | | SOFTWARE. | 26 | +----------------------------------------------------------------------+ 27 | | Author: Arnold Daniels | 28 | +----------------------------------------------------------------------+ 29 | */ 30 | 31 | #ifdef HAVE_CONFIG_H 32 | # include "config.h" 33 | #endif 34 | 35 | #include "php.h" 36 | #include "php_base58.h" 37 | #include "zend_exceptions.h" 38 | 39 | #include "lib/libbase58.h" 40 | 41 | #if HAVE_BASE58 42 | 43 | ZEND_BEGIN_ARG_INFO_EX(arginfo_base58_encode, 0, 0, 1) 44 | ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0) 45 | ZEND_END_ARG_INFO() 46 | 47 | ZEND_BEGIN_ARG_INFO_EX(arginfo_base58_decode, 0, 0, 1) 48 | ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0) 49 | ZEND_END_ARG_INFO() 50 | 51 | static const zend_function_entry base58_functions[] = { 52 | PHP_FE(base58_encode, arginfo_base58_encode) 53 | PHP_FE(base58_decode, arginfo_base58_decode) 54 | PHP_FE_END 55 | }; 56 | 57 | zend_module_entry base58_module_entry = { 58 | STANDARD_MODULE_HEADER, 59 | PHP_BASE58_EXTNAME, 60 | base58_functions, 61 | NULL, 62 | NULL, 63 | NULL, 64 | NULL, 65 | NULL, 66 | PHP_BASE58_VERSION, 67 | STANDARD_MODULE_PROPERTIES 68 | }; 69 | 70 | #ifdef COMPILE_DL_BASE58 71 | ZEND_GET_MODULE(base58) 72 | #endif 73 | 74 | PHP_FUNCTION(base58_encode) 75 | { 76 | zend_string *data; 77 | 78 | zend_string *b58; 79 | 80 | ZEND_PARSE_PARAMETERS_START(1, 1) 81 | Z_PARAM_STR(data) 82 | ZEND_PARSE_PARAMETERS_END(); 83 | 84 | b58 = zend_string_alloc((size_t)ceil(ZSTR_LEN(data) * 1.5) + 1, 0); 85 | 86 | if (!b58enc(ZSTR_VAL(b58), &ZSTR_LEN(b58), ZSTR_VAL(data), ZSTR_LEN(data))) { 87 | zend_string_free(b58); 88 | 89 | php_error_docref(NULL, E_WARNING, "Failed to base58 encode string"); 90 | RETURN_FALSE; 91 | } 92 | 93 | /* Exclude ending '\0` from string length */ 94 | ZSTR_LEN(b58)--; 95 | 96 | RETURN_STR(b58); 97 | } 98 | 99 | PHP_FUNCTION(base58_decode) 100 | { 101 | zend_string *b58; 102 | 103 | char *data; 104 | size_t data_len; 105 | 106 | zend_string *result; 107 | 108 | ZEND_PARSE_PARAMETERS_START(1, 1) 109 | Z_PARAM_STR(b58) 110 | ZEND_PARSE_PARAMETERS_END(); 111 | 112 | data_len = ZSTR_LEN(b58); 113 | data = emalloc(data_len); 114 | 115 | if (!b58tobin(data, &data_len, ZSTR_VAL(b58), ZSTR_LEN(b58))) { 116 | efree(data); 117 | 118 | php_error_docref(NULL, E_WARNING, "Failed to base58 decode string"); 119 | RETURN_FALSE; 120 | } 121 | 122 | /* libbase58 starts at the end of the buffer, so skip preceding '\0' chars. */ 123 | result = zend_string_init(data + (ZSTR_LEN(b58) - data_len), data_len, 0); 124 | efree(data); 125 | 126 | RETURN_STR(result); 127 | } 128 | 129 | #endif 130 | 131 | -------------------------------------------------------------------------------- /build-packagexml.php: -------------------------------------------------------------------------------- 1 | 15 | * @license PHP License 16 | * @license MIT 17 | */ 18 | 19 | declare (strict_types = 1); 20 | 21 | set_exception_handler(function (Throwable $exception): void { 22 | $msg = ($exception instanceof RuntimeException ? "" : "Unexpected error: ") . $exception->getMessage(); 23 | 24 | fwrite(STDERR, "\033[0;31m" /* red */ . $msg . "\033[0m" . "\n"); 25 | exit(1); 26 | }); 27 | 28 | if (!extension_loaded('dom') || !extension_loaded('simplexml') || !extension_loaded('spl')) { 29 | throw new RuntimeException("Following extensions are required: DOM, SimpleXML and SPL"); 30 | } 31 | 32 | // 1. Load package.xml and create release 33 | $package = (function (): PackageXMLElement { 34 | return file_exists('package.xml') 35 | ? simplexml_load_file('package.xml', PackageXMLElement::class) 36 | : PackageXMLElement::create(); 37 | })(); 38 | 39 | $release = new Release(); 40 | 41 | // 2. Process php_{extname}.h 42 | (function () use ($package, $release): void { 43 | $extname = (string)$package->name ?: getenv('PHP_PECL_EXTENSION') ?: null; 44 | 45 | if ($extname !== null) { 46 | $filename = "php_{$extname}.h"; 47 | 48 | if (!file_exists($filename)) { 49 | throw new RuntimeException("{$filename} not found"); 50 | } 51 | } else { 52 | $filename = glob('php_*.h')[0] ?? null; 53 | 54 | if ($filename === null) { 55 | throw new RuntimeException("Couldn't find the main header file (php_*.h)"); 56 | } 57 | 58 | $extname = preg_replace('/^php_(.+)\.h$/', '$1', $filename); 59 | } 60 | 61 | if ((string)$package->name === '') { 62 | $package->name = $extname; 63 | } 64 | 65 | 66 | $macroPrefix = strtoupper(pathinfo($filename, PATHINFO_FILENAME)); 67 | $contents = file_get_contents($filename); 68 | 69 | preg_match_all("/^[ \t]*#define\s+{$macroPrefix}_(?\w+)[ \t]+\"(?.+)\"/m", $contents, $matches, 70 | PREG_PATTERN_ORDER); 71 | $macros = array_combine($matches['key'], $matches['value']); 72 | 73 | // Package name 74 | if (isset($macros['EXTNAME'])) { 75 | if ((string)$package->name !== '' && (string)$package->name !== $macros['EXTNAME']) { 76 | throw new RuntimeException("Package name '{$package->name}' (package.xml) doesn't match " 77 | . "{$macroPrefix}_EXTNAME '{$macros['EXTNAME']}' ($filename)"); 78 | } 79 | } 80 | 81 | // Release version 82 | if (!isset($macros['VERSION'])) { 83 | throw new RuntimeException("$filename does not contain {$macroPrefix}_VERSION macro"); 84 | } 85 | $release->version = $macros['VERSION']; 86 | 87 | if (strpos($release->version, 'dev') !== false) { 88 | throw new RuntimeException("Development versions shouldn't be released ({$macros['VERSION']}). " 89 | . "Please change {$macroPrefix}_VERSION in $filename."); 90 | } 91 | if ($release->existsIn($package->changelog)) { 92 | throw new RuntimeException("Version {$macros['VERSION']} already released. " 93 | . "Please change {$macroPrefix}_VERSION in $filename."); 94 | } 95 | })(); 96 | 97 | // 3. Copy info from package to release 98 | (function () use ($package, $release): void { 99 | $release->license = (string)$package->license; 100 | $release->licenseUri = (string)$package->license['uri']; 101 | 102 | if (strpos($release->version, 'alpha') !== false) { 103 | $release->stability = 'alpha'; 104 | } else if (strpos($release->version, 'beta') !== false || strpos($release->version, 'RC') !== false) { 105 | $release->stability = 'beta'; 106 | } else if (substr($release->version, 0, 1) === '0') { 107 | $release->stability = ((string)$package->stability->release) ?: 'alpha'; 108 | } else { 109 | $release->stability = 'stable'; 110 | } 111 | 112 | if ($release->isMajor((string)$package->version->release)) { 113 | $release->apiVersion = $release->version; 114 | $release->apiStability = $release->stability; 115 | } else { 116 | $release->apiVersion = (string)$package->version->api; 117 | $release->apiStability = (string)$package->stability->api; 118 | } 119 | })(); 120 | 121 | // 4. Get release notes from stdin 122 | $release->notes = (function (string $name, string $version): string { 123 | if (function_exists('posix_isatty') && posix_isatty(STDIN)) { 124 | fwrite(STDOUT, "Enter the release notes for $name $version (end with Ctrl-D):\n"); 125 | } 126 | 127 | $notes = ''; 128 | 129 | do { 130 | $notes .= fread(STDIN, 1024); 131 | } while (!feof(STDIN)); 132 | 133 | return trim($notes); 134 | })((string)$package->name, $release->version); 135 | 136 | // 5. Add release to package 137 | if (!isset($package->changelog)) { 138 | $package->addChild('changelog'); 139 | } 140 | $release->update($package->changelog->prependChild('release')); 141 | $release->update($package); 142 | 143 | // 6. Removes files that no longer exist from package.xml 144 | (function () use ($package): void { 145 | $fileElements = $package->xpath('p:contents//p:file'); 146 | 147 | foreach ($fileElements as $element) { 148 | $path = join("/", array_map('strval', $element->xpath('ancestor-or-self::*[@name!="/"]/@name'))); 149 | 150 | if (!file_exists($path)) { 151 | unset($element[0]); 152 | } 153 | }; 154 | })(); 155 | 156 | // 7. Add new files to package.xml 157 | (function () use ($package): void { 158 | $ext = ['c', 'h', 'phpt']; 159 | 160 | $dir = new RecursiveDirectoryIterator('.', FilesystemIterator::SKIP_DOTS | FilesystemIterator::CURRENT_AS_PATHNAME); 161 | $itDir = new RecursiveIteratorIterator($dir); 162 | $itReg = new RegexIterator($itDir, '~^./(.+\.(?:' . join('|', $ext) . '))$~', RegexIterator::GET_MATCH); 163 | $files = iterable_column($itReg, 1); 164 | 165 | $newFiles = new CallbackFilterIterator($files, function ($path) use ($package): bool { 166 | $file = basename($path); 167 | $dirs = dirname($path) !== '.' ? explode('/', dirname($path)) : []; 168 | array_unshift($dirs, '/'); 169 | 170 | $xpath = 'p:dir[@name="' . join('"]/p:dir[@name="', $dirs) . '"]/p:file[@name="' . $file . '"]'; 171 | return count($package->contents->xpath($xpath)) === 0; 172 | }); 173 | 174 | if (is_dir('.git')) { 175 | $newFiles = gitignore_filter($newFiles); 176 | } 177 | 178 | foreach ($newFiles as $file) { 179 | $dirs = dirname($file) !== '.' ? explode('/', dirname($file)) : []; 180 | 181 | $dirElement = array_reduce($dirs, function (SimpleXMLElement $parent, string $dir): SimpleXMLElement { 182 | $cur = $parent->xpath('p:dir[@name="' . $dir . '"]')[0] ?? null; 183 | 184 | if ($cur === null) { 185 | $cur = $parent->addChild('dir'); 186 | $cur['name'] = $dir; 187 | } 188 | 189 | return $cur; 190 | }, $package->contents->dir[0]); 191 | 192 | $fileElement = $dirElement->addChild('file'); 193 | $fileElement['name'] = basename($file); 194 | $fileElement['role'] = pathinfo($file, PATHINFO_EXTENSION) === 'phpt' ? 'test' : 'src'; 195 | } 196 | })(); 197 | 198 | // 8. Remove empty dirs from package.xml 199 | (function () use ($package): void { 200 | $emptyDirs = $package->xpath('p:contents//p:dir[not(descendant::*[local-name()="file"])]'); 201 | 202 | foreach (array_reverse($emptyDirs) as $element) { // reverse so children are deleted first 203 | unset($element[0]); 204 | } 205 | })(); 206 | 207 | // 9. Sort files 208 | (function () use ($package): void { 209 | $dirElements = $package->xpath('p:contents//p:dir'); 210 | 211 | $sorter = function(SimpleXMLElement $first, SimpleXMLElement $second): int { 212 | return 213 | (($first->getName() !== 'file') <=> ($second->getName() !== 'file')) ?: 214 | strcasecmp((string)$first['name'], (string)$second['name']); 215 | }; 216 | 217 | foreach ($dirElements as $element) { 218 | $element->sort($sorter); 219 | } 220 | })(); 221 | 222 | // 10. Save package.xml 223 | $package->asXML('package.xml'); 224 | 225 | // :) friendly message 226 | echo "\033[0;32m", /* green */ "Updated package.xml for {$package->name} {$release->version}", "\033[0;0m", "\n"; 227 | 228 | // ================= classes and functions ==================== 229 | 230 | class Release 231 | { 232 | public $version; 233 | public $apiVersion; 234 | public $stability; 235 | public $apiStability; 236 | 237 | public $license; 238 | public $licenseUri; 239 | public $notes; 240 | 241 | public function isMajor(string $oldVersion): bool 242 | { 243 | if ($oldVersion === '') { 244 | return true; 245 | } 246 | 247 | [$major, $minor] = explode('.', $this->version); 248 | [$oldMajor, $oldMinor] = explode('.', $oldVersion); 249 | 250 | return ($major !== $oldMajor) || ($major === '0' && $minor !== $oldMinor); 251 | } 252 | 253 | public function existsIn(SimpleXMLElement $changelog): bool 254 | { 255 | if (!isset($changelog->release)) { 256 | return false; 257 | } 258 | 259 | foreach ($changelog->release as $release) { 260 | if ((string)($release->version->release) === $this->version) { 261 | return true; 262 | } 263 | } 264 | 265 | return false; 266 | } 267 | 268 | public function update(SimpleXMLElement $element) 269 | { 270 | $noTime = isset($element->date) && !isset($element->time); 271 | 272 | $element->date = date('Y-m-d'); 273 | if (!$noTime) { 274 | $element->time = date('H:i:s'); 275 | } 276 | 277 | $element->version->release = $this->version; 278 | $element->version->api = $this->apiVersion; 279 | $element->stability->release = $this->stability; 280 | $element->stability->api = $this->apiStability; 281 | 282 | $element->license = $this->license; 283 | $element->license['uri'] = $this->licenseUri; 284 | 285 | $indent = str_repeat(' ', count($element->xpath('ancestor::*')) + 1); 286 | $element->notes = "\n" . $this->notes . "\n$indent"; 287 | } 288 | }; 289 | 290 | class PackageXMLElement extends SimpleXMLElement 291 | { 292 | private const BLANK_PACKAGE = << 294 | 295 | 296 | pecl.php.net 297 | 298 | 299 | 300 | 301 | 302 | 303 | yes 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | MIT License 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 7.0.0 333 | 334 | 335 | 1.4.3 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | XML; 344 | 345 | public static function create(): self 346 | { 347 | return new static(self::BLANK_PACKAGE); 348 | } 349 | 350 | public function prependChild($name, $value = '') 351 | { 352 | $dom = dom_import_simplexml($this); 353 | 354 | $new = $dom->insertBefore( 355 | $dom->ownerDocument->createElement($name, $value), 356 | $dom->firstChild 357 | ); 358 | 359 | return simplexml_import_dom($new, __CLASS__); 360 | } 361 | 362 | public function sort(callable $sorter): void 363 | { 364 | if ($this->count() === 0) { 365 | return; 366 | } 367 | 368 | $children = iterator_to_array($this->children(), false); 369 | usort($children, $sorter); 370 | 371 | $dom = dom_import_simplexml($this); 372 | 373 | while ($dom->hasChildNodes()) { 374 | $dom->removeChild($dom->firstChild); 375 | } 376 | 377 | foreach ($children as $child) { 378 | $dom->appendChild(dom_import_simplexml($child)); 379 | } 380 | } 381 | 382 | public function asXML($filename = null) 383 | { 384 | $dom = new DOMDocument("1.0"); 385 | $dom->preserveWhiteSpace = false; 386 | $dom->formatOutput = true; 387 | $dom->loadXML(parent::asXML()); 388 | 389 | $xml = $dom->saveXML(); 390 | 391 | // Go from 2 space indentation to 1. 392 | $xml = preg_replace('~^([ ]+)\1<(?!/notes>)~m', '\1<', $xml); 393 | 394 | if ($filename === null) { 395 | return $xml; 396 | } 397 | 398 | if (file_exists($filename)) { 399 | rename($filename, $filename . '~'); 400 | } 401 | file_put_contents($filename, $xml); 402 | } 403 | 404 | public function xpath($xpath) 405 | { 406 | $this->registerXPathNamespace('p', 'http://pear.php.net/dtd/package-2.0'); 407 | 408 | return parent::xpath($xpath); 409 | } 410 | } 411 | 412 | function iterable_column(iterable $iterable, $column): Generator 413 | { 414 | foreach ($iterable as $key => $item) { 415 | yield $key => $item[$column]; 416 | } 417 | } 418 | 419 | function gitignore_filter(iterable $files): Generator 420 | { 421 | $spec = [ 422 | ["pipe", "r"], 423 | ["pipe", "w"], 424 | ["pipe", "w"], 425 | ]; 426 | 427 | $process = proc_open('git check-ignore --non-matching --verbose --stdin', $spec, $pipes); 428 | stream_set_timeout($pipes[1], 1); 429 | stream_set_blocking($pipes[2], false); 430 | 431 | foreach ($files as $file) { 432 | fwrite($pipes[0], $file . "\n"); 433 | $line = fgets($pipes[1], 1024); 434 | 435 | if ($line === false || substr($line, 0, 2) === '::') { 436 | yield $file; 437 | } 438 | } 439 | 440 | $err = fread($pipes[2], 10000); 441 | 442 | fclose($pipes[0]); 443 | fclose($pipes[1]); 444 | fclose($pipes[2]); 445 | 446 | $ret = proc_close($process); 447 | 448 | if ($ret !== 0 && $err !== '') { 449 | fwrite(STDERR, "\033[0;31m" /* red */ . $err . "\033[0m" /* no color */ . "\n"); 450 | throw new RuntimeException("Checking .gitignore failed"); 451 | } 452 | } 453 | 454 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl $Id$ 2 | dnl config.m4 for extension base58 3 | 4 | sinclude(./autoconf/pecl.m4) 5 | sinclude(./autoconf/php-executable.m4) 6 | 7 | PECL_INIT([base58]) 8 | 9 | PHP_ARG_ENABLE(base58, whether to enable base58, [ --enable-base58 Enable base58]) 10 | 11 | if test "$PHP_BASE58" != "no"; then 12 | AC_DEFINE(HAVE_BASE58, 1, [whether base58 is enabled]) 13 | PHP_NEW_EXTENSION(base58, base58.c lib/libbase58.c, $ext_shared) 14 | 15 | PHP_ADD_MAKEFILE_FRAGMENT 16 | PHP_INSTALL_HEADERS([ext/base58], [php_base58.h]) 17 | fi 18 | -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | // vim:ft=javascript 3 | 4 | ARG_ENABLE("base58", "enable base58", "no"); 5 | 6 | if (PHP_BASE58 != "no") { 7 | EXTENSION("base58", "base58.c"); 8 | ADD_SOURCES(configure_module_dirname + "/lib", "libbase58.c", "base58"); 9 | AC_DEFINE('HAVE_BASE58', 1 , 'whether base58 is enabled'); 10 | PHP_INSTALL_HEADERS("ext/base58/", "php_base58.h"); 11 | } 12 | -------------------------------------------------------------------------------- /lib/AUTHORS: -------------------------------------------------------------------------------- 1 | Luke Dashjr 2 | Huang Le <4tarhl@gmail.com> 3 | -------------------------------------------------------------------------------- /lib/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Luke Dashjr 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /lib/libbase58.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2014 Luke Dashjr 3 | * 4 | * This program is free software; you can redistribute it and/or modify it 5 | * under the terms of the standard MIT license. See COPYING for more details. 6 | */ 7 | 8 | #ifndef _WIN32 9 | #include 10 | #else 11 | #include 12 | #endif 13 | 14 | #ifdef _MSC_VER 15 | #include 16 | #endif 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "libbase58.h" 24 | 25 | bool (*b58_sha256_impl)(void *, const void *, size_t) = NULL; 26 | 27 | static const int8_t b58digits_map[] = { 28 | -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, 29 | -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, 30 | -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, 31 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1, 32 | -1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1, 33 | 22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1, 34 | -1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46, 35 | 47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1, 36 | }; 37 | 38 | typedef uint64_t b58_maxint_t; 39 | typedef uint32_t b58_almostmaxint_t; 40 | #define b58_almostmaxint_bits (sizeof(b58_almostmaxint_t) * 8) 41 | static const b58_almostmaxint_t b58_almostmaxint_mask = ((((b58_maxint_t)1) << b58_almostmaxint_bits) - 1); 42 | 43 | // MSVC 2017 C99 doesn't support dynamic arrays in C 44 | #ifdef _MSC_VER 45 | #define b58_alloc_mem(type, name, count) \ 46 | type *name = NULL; \ 47 | do { \ 48 | name = _malloca(count * sizeof(type)); \ 49 | if (!name) { \ 50 | return false; \ 51 | } \ 52 | } while (0) 53 | 54 | #define b58_free_mem(v) \ 55 | do { \ 56 | if ((v)) { \ 57 | _freea((v)); \ 58 | } \ 59 | } while (0) 60 | #else 61 | #define b58_alloc_mem(type, name, count) type name[count] 62 | #define b58_free_mem(v) 63 | #endif 64 | 65 | bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz) 66 | { 67 | size_t binsz = *binszp; 68 | const unsigned char *b58u = (void*)b58; 69 | unsigned char *binu = bin; 70 | size_t outisz = (binsz + sizeof(b58_almostmaxint_t) - 1) / sizeof(b58_almostmaxint_t); 71 | b58_alloc_mem(b58_almostmaxint_t, outi, outisz); 72 | b58_maxint_t t; 73 | b58_almostmaxint_t c; 74 | size_t i, j; 75 | uint8_t bytesleft = binsz % sizeof(b58_almostmaxint_t); 76 | b58_almostmaxint_t zeromask = bytesleft ? (b58_almostmaxint_mask << (bytesleft * 8)) : 0; 77 | unsigned zerocount = 0; 78 | 79 | if (!b58sz) 80 | b58sz = strlen(b58); 81 | 82 | for (i = 0; i < outisz; ++i) { 83 | outi[i] = 0; 84 | } 85 | 86 | // Leading zeros, just count 87 | for (i = 0; i < b58sz && b58u[i] == '1'; ++i) 88 | ++zerocount; 89 | 90 | for ( ; i < b58sz; ++i) 91 | { 92 | if (b58u[i] & 0x80) { 93 | // High-bit set on invalid digit 94 | b58_free_mem(outi); 95 | return false; 96 | } 97 | if (b58digits_map[b58u[i]] == -1) { 98 | // Invalid base58 digit 99 | b58_free_mem(outi); 100 | return false; 101 | } 102 | c = (unsigned)b58digits_map[b58u[i]]; 103 | for (j = outisz; j--; ) 104 | { 105 | t = ((b58_maxint_t)outi[j]) * 58 + c; 106 | c = t >> b58_almostmaxint_bits; 107 | outi[j] = t & b58_almostmaxint_mask; 108 | } 109 | if (c) { 110 | // Output number too big (carry to the next int32) 111 | b58_free_mem(outi); 112 | return false; 113 | } 114 | if (outi[0] & zeromask) { 115 | // Output number too big (last int32 filled too far) 116 | b58_free_mem(outi); 117 | return false; 118 | } 119 | } 120 | 121 | j = 0; 122 | if (bytesleft) { 123 | for (i = bytesleft; i > 0; --i) { 124 | *(binu++) = (outi[0] >> (8 * (i - 1))) & 0xff; 125 | } 126 | ++j; 127 | } 128 | 129 | for (; j < outisz; ++j) 130 | { 131 | for (i = sizeof(*outi); i > 0; --i) { 132 | *(binu++) = (outi[j] >> (8 * (i - 1))) & 0xff; 133 | } 134 | } 135 | 136 | // Count canonical base58 byte count 137 | binu = bin; 138 | for (i = 0; i < binsz; ++i) 139 | { 140 | if (binu[i]) 141 | break; 142 | --*binszp; 143 | } 144 | *binszp += zerocount; 145 | 146 | b58_free_mem(outi); 147 | return true; 148 | } 149 | 150 | static 151 | bool my_dblsha256(void *hash, const void *data, size_t datasz) 152 | { 153 | uint8_t buf[0x20]; 154 | return b58_sha256_impl(buf, data, datasz) && b58_sha256_impl(hash, buf, sizeof(buf)); 155 | } 156 | 157 | int b58check(const void *bin, size_t binsz, const char *base58str, size_t b58sz) 158 | { 159 | unsigned char buf[32]; 160 | const uint8_t *binc = bin; 161 | unsigned i; 162 | if (binsz < 4) 163 | return -4; 164 | if (!my_dblsha256(buf, bin, binsz - 4)) 165 | return -2; 166 | if (memcmp(&binc[binsz - 4], buf, 4)) 167 | return -1; 168 | 169 | // Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end) 170 | for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) 171 | {} // Just finding the end of zeros, nothing to do in loop 172 | if (binc[i] == '\0' || base58str[i] == '1') 173 | return -3; 174 | 175 | return binc[0]; 176 | } 177 | 178 | static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; 179 | 180 | bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz) 181 | { 182 | const uint8_t *bin = data; 183 | int carry; 184 | size_t i, j, high, zcount = 0; 185 | size_t size; 186 | 187 | while (zcount < binsz && !bin[zcount]) 188 | ++zcount; 189 | 190 | size = (binsz - zcount) * 138 / 100 + 1; 191 | b58_alloc_mem(uint8_t, buf, size); 192 | memset(buf, 0, size); 193 | 194 | for (i = zcount, high = size - 1; i < binsz; ++i, high = j) 195 | { 196 | for (carry = bin[i], j = size - 1; (j > high) || carry; --j) 197 | { 198 | carry += 256 * buf[j]; 199 | buf[j] = carry % 58; 200 | carry /= 58; 201 | if (!j) { 202 | // Otherwise j wraps to maxint which is > high 203 | break; 204 | } 205 | } 206 | } 207 | 208 | for (j = 0; j < size && !buf[j]; ++j); 209 | 210 | if (*b58sz <= zcount + size - j) 211 | { 212 | *b58sz = zcount + size - j + 1; 213 | b58_free_mem(buf); 214 | return false; 215 | } 216 | 217 | if (zcount) 218 | memset(b58, '1', zcount); 219 | for (i = zcount; j < size; ++i, ++j) 220 | b58[i] = b58digits_ordered[buf[j]]; 221 | b58[i] = '\0'; 222 | *b58sz = i + 1; 223 | 224 | b58_free_mem(buf); 225 | return true; 226 | } 227 | 228 | bool b58check_enc(char *b58c, size_t *b58c_sz, uint8_t ver, const void *data, size_t datasz) 229 | { 230 | b58_alloc_mem(uint8_t, buf, 1 + datasz + 0x20); 231 | uint8_t *hash = &buf[1 + datasz]; 232 | 233 | buf[0] = ver; 234 | memcpy(&buf[1], data, datasz); 235 | if (!my_dblsha256(hash, buf, datasz + 1)) 236 | { 237 | *b58c_sz = 0; 238 | b58_free_mem(buf); 239 | return false; 240 | } 241 | 242 | b58_free_mem(buf); 243 | return b58enc(b58c, b58c_sz, buf, 1 + datasz + 4); 244 | } 245 | -------------------------------------------------------------------------------- /lib/libbase58.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBBASE58_H 2 | #define LIBBASE58_H 3 | 4 | #include 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | extern bool (*b58_sha256_impl)(void *, const void *, size_t); 12 | 13 | extern bool b58tobin(void *bin, size_t *binsz, const char *b58, size_t b58sz); 14 | extern int b58check(const void *bin, size_t binsz, const char *b58, size_t b58sz); 15 | 16 | extern bool b58enc(char *b58, size_t *b58sz, const void *bin, size_t binsz); 17 | extern bool b58check_enc(char *b58c, size_t *b58c_sz, uint8_t ver, const void *data, size_t datasz); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | base58 4 | pecl.php.net 5 | Encode and decode data with base58 6 | PHP extension for base58 encoding and decoding using the Bitcoin alphabet 7 | 8 | Arnold Daniels 9 | jasny 10 | jasny@php.net 11 | yes 12 | 13 | 2020-12-27 14 | 15 | 1.0.2 16 | 1.0.0 17 | 18 | 19 | stable 20 | stable 21 | 22 | MIT License 23 | 24 | Casing fix config.m4 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 7.0.0 52 | 53 | 54 | 1.4.3 55 | 56 | 57 | 58 | base58 59 | 60 | 61 | 62 | 2020-12-26 63 | 64 | 65 | 1.0.2 66 | 1.0.0 67 | 68 | 69 | stable 70 | stable 71 | 72 | MIT License 73 | 74 | Casing fix config.m4 75 | 76 | 77 | 78 | 2020-12-26 79 | 80 | 81 | 1.0.1 82 | 1.0.0 83 | 84 | 85 | stable 86 | stable 87 | 88 | MIT License 89 | 90 | Release as v1.0.1 with build fix 91 | 92 | 93 | 94 | 2020-12-26 95 | 96 | 97 | 1.0.0 98 | 1.0.0 99 | 100 | 101 | stable 102 | stable 103 | 104 | PHP License 105 | 106 | Release as v1.0.0 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /php_base58.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | Base58 PHP extension | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 2020 Arnold Daniels | 6 | +----------------------------------------------------------------------+ 7 | | Permission is hereby granted, free of charge, to any person | 8 | | obtaining a copy of this software and associated documentation files | 9 | | (the "Software"), to deal in the Software without restriction, | 10 | | including without limitation the rights to use, copy, modify, merge, | 11 | | publish, distribute, sublicense, and/or sell copies of the Software, | 12 | | and to permit persons to whom the Software is furnished to do so, | 13 | | subject to the following conditions: | 14 | | | 15 | | The above copyright notice and this permission notice shall be | 16 | | included in all copies or substantial portions of the Software. | 17 | | | 18 | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 19 | | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 20 | | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 21 | | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | 22 | | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | 23 | | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | 24 | | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 25 | | SOFTWARE. | 26 | +----------------------------------------------------------------------+ 27 | | Author: Arnold Daniels | 28 | +----------------------------------------------------------------------+ 29 | */ 30 | 31 | #ifndef PHP_BASE58_H 32 | #define PHP_BASE58_H 1 33 | 34 | #define PHP_BASE58_VERSION "1.0.2" 35 | #define PHP_BASE58_EXTNAME "base58" 36 | 37 | #ifdef PHP_WIN32 38 | # define PHP_BASE58_API __declspec(dllexport) 39 | #elif defined(__GNUC__) && __GNUC__ >= 4 40 | # define PHP_BASE58_API __attribute__ ((visibility("default"))) 41 | #else 42 | # define PHP_BASE58_API 43 | #endif 44 | 45 | static PHP_FUNCTION(base58_encode); 46 | static PHP_FUNCTION(base58_decode); 47 | 48 | extern zend_module_entry base58_module_entry; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /tests/base58_decode.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test base58_decode 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 12 | --EXPECT-- 13 | string(11) "Hello World" 14 | string(6) "000000" 15 | string(64) "2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae" 16 | 17 | -------------------------------------------------------------------------------- /tests/base58_encode.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Test base58_encode 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 12 | --EXPECT-- 13 | string(15) "JxF12TrwUP45BMd" 14 | string(3) "111" 15 | string(44) "3yMApqCuCjXDWPrbjfR5mjCPTHqFG8Pux1TxQrEM35jj" 16 | 17 | --------------------------------------------------------------------------------