From 8ca9579834e2ed2b3811eb4773127de98157e808 Mon Sep 17 00:00:00 2001 From: Keisuke Maeda <120993695+kmaeda-rakus@users.noreply.github.com> Date: Thu, 23 Jul 2026 21:45:09 +0900 Subject: [PATCH] Add support for pinning tools to a checksum (#1098) Tools in the tools input can now be pinned to a checksum using the tool:version@sha256: or tool:version@sha512: syntax. The downloaded tool is verified against the checksum on all platforms, including when it is served from the tools cache, and it is removed along with its cache entry if the verification fails. Checksum verification is supported for tools downloaded as phar archives. Specifying a checksum for tools set up using composer packages or custom package scripts results in an error. Co-authored-by: Claude Fable 5 --- README.md | 12 ++++ __tests__/tools.test.ts | 98 +++++++++++++++++++++++++++++---- dist/index.js | 2 +- src/scripts/tools/add_tools.ps1 | 25 ++++++++- src/scripts/tools/add_tools.sh | 15 ++++- src/scripts/unix.sh | 18 ++++++ src/tools.ts | 71 +++++++++++++++++++++++- 7 files changed, 225 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 230cf2b5..4563ce05 100644 --- a/README.md +++ b/README.md @@ -264,6 +264,18 @@ These tools can be set up globally using the `tools` input. It accepts a string When you specify just the major version or the version in `major.minor` format, the latest patch version matching the input will be set up. +- To harden your workflow against supply chain attacks, you can pin a tool to a checksum in the form `tool:version@sha256:` or `tool:version@sha512:`. The downloaded tool is verified against the checksum and it is not set up if the verification fails, even if the tool is served from the tools cache. + +```yaml +- name: Setup PHP with tools pinned to a checksum + uses: shivammathur/setup-php@v2 + with: + php-version: '8.5' + tools: composer:2.9.8@sha256:59b2c50e10cafa0d8efc19ede9a326d782f096c674a26baf98cf042ce23de890 +``` + + Checksum verification is supported for tools which are downloaded as phar archives. It is not supported for tools set up using `composer` packages or custom package scripts, specifying a checksum for these tools will result in an error. For checksum pinning to be effective, pin the tool to an exact version, as mutable versions like `latest` or `major.minor` can resolve to a different release with a different checksum. + - The latest stable version of `composer` is set up by default. You can set up the required `composer` version by specifying the major version `v1` or `v2`, or the version in `major.minor` or `semver` format. Additionally, for composer `snapshot` and `preview` can also be specified to set up the respective releases. ```yaml diff --git a/__tests__/tools.test.ts b/__tests__/tools.test.ts index 6805aa58..1da2215d 100644 --- a/__tests__/tools.test.ts +++ b/__tests__/tools.test.ts @@ -222,17 +222,41 @@ describe('Tools tests', () => { }); it.each` - input_list | filtered_list - ${'a, b'} | ${'composer, a, b'} - ${'a, b, composer'} | ${'composer, a, b'} - ${'a, b, composer:1.2.3'} | ${'composer:1.2.3, a, b'} - ${'a, b, composer:v1.2.3'} | ${'composer:1.2.3, a, b'} - ${'a, b, composer:snapshot'} | ${'composer:snapshot, a, b'} - ${'a, b, composer:preview'} | ${'composer:preview, a, b'} - ${'a, b, composer:1'} | ${'composer:1, a, b'} - ${'a, b, composer:2'} | ${'composer:2, a, b'} - ${'a, b, composer:v1'} | ${'composer:1, a, b'} - ${'a, b, composer:v2'} | ${'composer:2, a, b'} + release | expected_release | checksum | error + ${'tool:1.2.3'} | ${'tool:1.2.3'} | ${undefined} | ${undefined} + ${'tool:1.2.3@sha256:' + 'a'.repeat(64)} | ${'tool:1.2.3'} | ${'sha256:' + 'a'.repeat(64)} | ${undefined} + ${'tool:1.2.3@sha256:' + 'A'.repeat(64)} | ${'tool:1.2.3'} | ${'sha256:' + 'a'.repeat(64)} | ${undefined} + ${'tool:1.2.3@sha512:' + 'b'.repeat(128)} | ${'tool:1.2.3'} | ${'sha512:' + 'b'.repeat(128)} | ${undefined} + ${'composer:2.9.8@sha256:' + 'c'.repeat(64)} | ${'composer:2.9.8'} | ${'sha256:' + 'c'.repeat(64)} | ${undefined} + ${'tool:1.2.3@sha256:xyz'} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid sha256 checksum, expected 64 hexadecimal characters'} + ${'tool:1.2.3@sha256:' + 'a'.repeat(63)} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid sha256 checksum, expected 64 hexadecimal characters'} + ${'tool:1.2.3@sha512:' + 'b'.repeat(64)} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid sha512 checksum, expected 128 hexadecimal characters'} + ${'tool:1.0@dev'} | ${'tool:1.0@dev'} | ${undefined} | ${undefined} + `( + 'checking extractChecksum: $release', + ({release, expected_release, checksum, error}) => { + expect(tools.extractChecksum(release)).toStrictEqual({ + release: expected_release, + ...(checksum !== undefined && {checksum}), + ...(error !== undefined && {error}) + }); + } + ); + + it.each` + input_list | filtered_list + ${'a, b'} | ${'composer, a, b'} + ${'a, b, composer'} | ${'composer, a, b'} + ${'a, b, composer:1.2.3'} | ${'composer:1.2.3, a, b'} + ${'a, b, composer:v1.2.3'} | ${'composer:1.2.3, a, b'} + ${'a, b, composer:snapshot'} | ${'composer:snapshot, a, b'} + ${'a, b, composer:preview'} | ${'composer:preview, a, b'} + ${'a, b, composer:1'} | ${'composer:1, a, b'} + ${'a, b, composer:2'} | ${'composer:2, a, b'} + ${'a, b, composer:v1'} | ${'composer:1, a, b'} + ${'a, b, composer:v2'} | ${'composer:2, a, b'} + ${'a, b, composer:2.7.1@sha256:' + 'a'.repeat(64)} | ${'composer:2.7.1@sha256:' + 'a'.repeat(64) + ', a, b'} + ${'a, b, composer:v2.7.1@sha256:' + 'a'.repeat(64)} | ${'composer:2.7.1@sha256:' + 'a'.repeat(64) + ', a, b'} `('checking filterList $input_list', async ({input_list, filtered_list}) => { expect(await tools.filterList(input_list.split(', '))).toStrictEqual( filtered_list.split(', ') @@ -304,6 +328,23 @@ describe('Tools tests', () => { expect(await tools.addArchive(data)).toContain(script); }); + it.each` + os | script + ${'linux'} | ${'add_tool https://example.com/tool.phar tool "-v" sha256:' + 'a'.repeat(64)} + ${'darwin'} | ${'add_tool https://example.com/tool.phar tool "-v" sha256:' + 'a'.repeat(64)} + ${'win32'} | ${'Add-Tool https://example.com/tool.phar tool "-v" sha256:' + 'a'.repeat(64)} + `('checking addArchive with checksum: $os', async ({os, script}) => { + const data = getData({ + tool: 'tool', + version: '1.2.3', + version_parameter: JSON.stringify('-v'), + os: os, + url: 'https://example.com/tool.phar' + }); + data.checksum = 'sha256:' + 'a'.repeat(64); + expect(await tools.addArchive(data)).toContain(script); + }); + it.each` os | release | scope | script ${'linux'} | ${'tool:1.2.3'} | ${'global'} | ${'add_composer_tool tool tool:1.2.3 user/ global'} @@ -774,6 +815,41 @@ describe('Tools tests', () => { expect(await tools.addTools(tools_csv, '7.4', 'linux')).toContain(script); }); + it.each` + tools_csv | os | script + ${'phpunit:9.5.0@sha256:' + 'a'.repeat(64)} | ${'linux'} | ${'add_tool https://phar.phpunit.de/phpunit-9.5.0.phar,https://phar.phpunit.de/phpunit-9.phar phpunit "--version" sha256:' + 'a'.repeat(64)} + ${'phpunit:9.5.0@sha256:' + 'a'.repeat(64)} | ${'win32'} | ${'Add-Tool https://phar.phpunit.de/phpunit-9.5.0.phar,https://phar.phpunit.de/phpunit-9.phar phpunit "--version" sha256:' + 'a'.repeat(64)} + ${'composer:2.9.8@sha256:' + 'b'.repeat(64)} | ${'linux'} | ${'composer 2.9.8 sha256:' + 'b'.repeat(64)} + ${'cs2pr:1.2.3@sha256:' + 'd'.repeat(64)} | ${'linux'} | ${'add_tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/download/1.2.3/cs2pr cs2pr "-V" sha256:' + 'd'.repeat(64)} + ${'phive:0.15.3@sha512:' + 'c'.repeat(128)} | ${'darwin'} | ${'add_tool https://github.com/phar-io/phive/releases/download/0.15.3/phive-0.15.3.phar phive "status" sha512:' + 'c'.repeat(128)} + ${'phinx:1.2.3@sha256:' + 'a'.repeat(64)} | ${'linux'} | ${'add_log "$cross" "phinx" "Checksum verification is not supported for phinx"'} + ${'pecl@sha256:' + 'a'.repeat(64)} | ${'linux'} | ${'add_log "$cross" "pecl" "Checksum verification is not supported for pecl"'} + ${'phpunit:9.5.0@sha256:invalid'} | ${'linux'} | ${'add_log "$cross" "phpunit" "Invalid sha256 checksum, expected 64 hexadecimal characters"'} + `( + 'checking addTools with checksum: $tools_csv, $os', + async ({tools_csv, os, script}) => { + expect(await tools.addTools(tools_csv, '7.4', os)).toContain(script); + } + ); + + it.each` + type | tool_function | supported + ${'phar'} | ${undefined} | ${true} + ${'custom-function'} | ${undefined} | ${true} + ${'custom-function'} | ${'composer'} | ${true} + ${'custom-function'} | ${'pecl'} | ${false} + ${'custom-function'} | ${'dev_tools'} | ${false} + ${'composer'} | ${undefined} | ${false} + ${'custom-package'} | ${undefined} | ${false} + `( + 'checking supportsChecksum: $type, $tool_function', + async ({type, tool_function, supported}) => { + const data = getData({tool: 'tool', type: type}); + data.function = tool_function; + expect(await tools.supportsChecksum(data)).toBe(supported); + } + ); + it.each` tools_csv | token | script ${'cs2pr:1.2'} | ${'invalid_token'} | ${'add_log "$cross" "cs2pr" "Invalid token"'} diff --git a/dist/index.js b/dist/index.js index 532cac5f..777e51b3 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1 +1 @@ -(()=>{var e={472:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var i=Object.getOwnPropertyDescriptor(t,r);if(!i||("get"in i?!t.__esModule:i.writable||i.configurable)){i={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,i)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var s=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),s=0;so.escapeForShell(e,"linux")).join("\n")+'" | sudo tee -a "${pecl_file:-${ini_file[@]}}" >/dev/null 2>&1'+r}async function addINIValuesWindows(e){const t=await o.CSVArray(e);let r="\n";await o.asyncForEach(t,async function(e){r+=await o.addLog("$tick",e,"Added to php.ini","win32")+"\n"});return'Add-Content "$php_dir\\php.ini" "'+t.map(e=>o.escapeForShell(e,"win32")).join("\n")+'"'+r}async function addINIValues(e,t,r=false){let n="\n";switch(r){case true:n+=await o.stepLog("Add php.ini values",t)+await o.suppressOutput(t)+"\n";break;case false:default:n+=await o.stepLog("Add php.ini values",t)+"\n";break}switch(t){case"win32":return n+await addINIValuesWindows(e);case"darwin":case"linux":return n+await addINIValuesUnix(e);default:return await o.log("Platform "+t+" is not supported",t,"error")}}},469:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:true});t.issueCommand=issueCommand;t.error=error;t.setFailed=setFailed;t.getInput=getInput;const n=r(857);function toCommandValue(e){if(e instanceof Error){return e.toString()}return e}function escapeData(e){return toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A")}function escapeProperty(e){return e.replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A").replace(/:/g,"%3A").replace(/,/g,"%2C")}function issueCommand(e,t,r){let i=`::${e}`;if(t&&Object.keys(t).length>0){i+=" ";const e=Object.entries(t).filter(([,e])=>e).map(([e,t])=>`${e}=${escapeProperty(t)}`).join(",");i+=e}i+=`::${escapeData(r)}`;process.stdout.write(i+n.EOL)}function error(e){issueCommand("error",{},e)}function setFailed(e){process.exitCode=1;error(e)}function getInput(e,t=false){const r=process.env[`INPUT_${e.replace(/ /g,"_").toUpperCase()}`]||"";if(t&&!r){throw new Error(`Input required and not supplied: ${e}`)}return r.trim()}},524:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var i=Object.getOwnPropertyDescriptor(t,r);if(!i||("get"in i?!t.__esModule:i.writable||i.configurable)){i={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,i)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var s=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),s=0;s{"use strict";Object.defineProperty(t,"__esModule",{value:true});t.fetch=fetch;const r=new Set([301,302,303,307,308]);async function fetch(e,t,n=5){const i={"User-Agent":`Mozilla/5.0 (${process.platform} ${process.arch}) setup-php`};if(t){i["Authorization"]="Bearer "+t}try{const t=await globalThis.fetch(e,{headers:i,redirect:n>0?"follow":"manual"});if(t.ok){const e=await t.text();return{data:e}}else if(r.has(t.status)&&n<=0){return{error:`${t.status}: Redirect error`}}else{return{error:`${t.status}: ${t.statusText}`}}}catch(e){return{error:`Fetch error: ${e.message}`}}}},755:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var i=Object.getOwnPropertyDescriptor(t,r);if(!i||("get"in i?!t.__esModule:i.writable||i.configurable)){i={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,i)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var s=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),s=0;s{await run()})().catch(e=>{l.setFailed(e.message)})},75:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var i=Object.getOwnPropertyDescriptor(t,r);if(!i||("get"in i?!t.__esModule:i.writable||i.configurable)){i={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,i)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var s=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),s=0;so.compareVersions(t.version,e.version));const i=r.find(e=>{if(e?.require?.php){return e?.require?.php.split("|").some(e=>e&&o.satisfies(t+".0",e))}return false});return i?i.version:null}return null}},159:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var i=Object.getOwnPropertyDescriptor(t,r);if(!i||("get"in i?!t.__esModule:i.writable||i.configurable)){i={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,i)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var s=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),s=0;s{const[r,n]=t.trim().split(/\s+/);return u.compareVersions(e,r)>=0&&u.compareVersions(e,n)<0})}function cleanComposerAuthJson(){try{const e=process.env["COMPOSER_AUTH_JSON"]||"";if(!e.includes("github-oauth"))return;const t=JSON.parse(e);delete t["github-oauth"];if(!Object.keys(t).length){delete process.env["COMPOSER_AUTH_JSON"]}else{process.env["COMPOSER_AUTH_JSON"]=JSON.stringify(t)}}catch{return}}async function getSemverVersion(e){const fixSemver=e=>{if(/^\d+\.\d+\.\d+(-|$)/.test(e))return e;const t=e.match(/^(\d+\.\d+\.\d+)([A-Za-z]+[0-9A-Za-z.]+)$/);return t?`${t[1]}-${t[2]}`:e};const t=e["version_prefix"]+e["version"];const r=`https://api.github.com/repos/${e["repository"]}/git/matching-refs/tags%2F${t}.`;const n=await f.readEnv("GITHUB_TOKEN")||await f.readEnv("COMPOSER_TOKEN");const i=await d.fetch(r,n);if(i.error||i.data==="[]"){e.error=i.error??`No version found with prefix ${t}.`;return e.version}else{const e=JSON.parse(i.data);const t=e.map(e=>(e.ref?.split("/").pop()??"").replace(/^v(?=\d)/,"")).filter(e=>e.length>0);const r=new Map;const n=t.map(e=>{const t=fixSemver(e);r.set(t,e);return t});const s=n.toSorted((e,t)=>{try{return u.compareVersions(t,e)}catch{return t.localeCompare(e,"en",{numeric:true,sensitivity:"base"})}});return r.get(s[0])??s[0]}}async function getLatestVersion(e){if(!e.version&&e.fetch_latest==="false"){return"latest"}if(e.fetch_latest==="true"&&!e.repository){return"latest"}const t=await d.fetch(`${e.github}/${e.repository}/releases.atom`);if(t.data){const e=[...t.data.matchAll(/releases\/tag\/([a-zA-Z]*)?(\d+\.\d+\.\d+)"/g)].map(e=>e[2]);const r=e.toSorted((e,t)=>e.localeCompare(t,undefined,{numeric:true}));return r.at(-1)||"latest"}return"latest"}async function getVersion(e,t){const r=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;const n=/^composer:(stable|preview|snapshot|[12])$/;const i=/[><=^~]+.*/;const s=/^\d+(\.\d+)?$/;t.version=e.replace(/v?(\d)/,"$1").replace(/\.x/,"");switch(true){case n.test(t.release):case r.test(t.version):case i.test(t.version)&&t.type==="composer":return t.version;case s.test(t.version)&&t.type==="composer":t.release=`${t.tool}:${t.version}.*`;return`${t.version}.*`;case!!t.repository&&s.test(t.version):return await getSemverVersion(t);default:return t.version.replace(/[^a-zA-Z0-9_.:@+,/-]/g,"")}}async function getRelease(e,t){e=e.includes("/")?e.split("/")[1]:e;return e.includes(":")?[t.tool,e.split(":")[1]].join(":"):t.tool}async function filterList(e){const t=/^composer($|:.*)/;const r=/^composer:?($|preview$|snapshot$|v?\d+(\.\d+)?$|v?\d+\.\d+\.\d+[\w-]*$)/;const n=e.filter(e=>r.test(e));let i="composer";e=e.filter(e=>!t.test(e));switch(true){case n[0]==undefined:break;default:i=n.at(-1).replace(/v(\d\S*)/,"$1");break}e.unshift(i);return e}async function getUrl(e){const t=e.version??"latest";if(t==="latest"||t===""){return[e.domain,e.repository,e.prefix,"latest",e.verb,e.tool+e.extension].filter(Boolean).join("/")}else{return[e.domain,e.repository,e.prefix,e.verb,e.version_prefix+e.version,e.tool+e.extension].filter(Boolean).join("/")}}async function getPharUrl(e){if(e.version==="latest"){return e.domain+"/"+e.tool+".phar"}else{return e.domain+"/"+e.tool+"-"+e.version_prefix+e.version+".phar"}}async function addArchive(e){return await f.getCommand(e.os,"tool")+await f.joins(e.url,e.tool,e.version_parameter)}async function addPackage(e){const t=await f.getCommand(e.os,"composer_tool");const r=e.repository.split("/");const n=[r[1],e.release,r[0]+"/",e.scope].map(t=>f.safeArg(t,e.os)).join(" ");return t+n}async function addBlackfirePlayer(e){switch(e.os){case"win32":return await f.addLog("$cross",e.tool,e.tool+" is not a windows tool","win32");default:if(e.version=="latest"){if(/5\.[5-6]|7\.0/.test(e.php_version)){e.version="1.9.3"}else if(/7\.[1-4]|8\.0/.test(e.php_version)){e.version="1.22.0"}}e.url=await getPharUrl(e);return addArchive(e)}}async function addCastor(e){e.tool="castor."+e.os.replace("win32","windows")+"-amd64";e.url=await getUrl(e);e.tool="castor";e.version_parameter=c.default.existsSync("castor.php")?e.version_parameter:"";return await addArchive(e)}async function addComposer(e){const t=e.version.replace("latest","stable");const r=e.github;const n=e.domain;const i="https://dl.cloudsmith.io";const s="https://artifacts.setup-php.com";const o=`composer-${e.php_version}-${t}.phar`;const a=`${r}/shivammathur/composer-cache/releases/latest/download/${o}`;const c=`${i}/public/shivammathur/composer-cache/raw/files/${o}`;const u=`${s}/composer/${o}`;const d=`${n}/download/latest-2.2.x/composer.phar`;const l=/^5\.[3-6]$|^7\.[0-1]$/.test(e.php_version);const p=`${n}/composer-${t}.phar`;const h=`${n}/download/${t}/composer.phar`;let g=`${a},${u},${c}`;let w=`${n}/composer.phar`;let v="";switch(true){case/^snapshot$/.test(t):w=l?d:w;break;case/^preview$|^2$/.test(t):w=l?d:p;break;case/^1$/.test(t):w=p;break;case/^\d+\.\d+\.\d+(?:-[\w-]+)?$/.test(e.version):if(skipGitHubAuthForComposerVersion(e.version)){cleanComposerAuthJson();v=" true"}g=`${r}/${e.repository}/releases/download/${e.version}/composer.phar`;w=h;break;default:w=l?d:p}const m=await f.readEnv("NO_TOOLS_CACHE")!=="true";e.url=m?`${g},${w}`:w;e.version_parameter=e.version+v;return await addArchive(e)}async function addDeployer(e){if(e.version==="latest"){e.url=e.domain+"/deployer.phar"}else{const t=await d.fetch("https://deployer.org/manifest.json");const r=JSON.parse(t.data);const n=Object.keys(r).find(t=>r[t].version===e.version);if(n){e.url=r[n].url}else{return await f.addLog("$cross","deployer","Version missing in deployer manifest",e.os)}}return await addArchive(e)}async function addDevTools(e){switch(e.os){case"linux":case"darwin":return"add_devtools "+e.tool;case"win32":return await f.addLog("$tick",e.tool,e.tool+" is not a windows tool","win32");default:return await f.log("Platform "+e.os+" is not supported",e.os,"error")}}async function addPECL(e){return await f.getCommand(e.os,"pecl")}async function addPhing(e){e.url=e.domain+"/get/phing-"+e.version+e.extension;if(e.version!="latest"){[e.prefix,e.verb]=["releases","download"];e.domain=e.github;e.extension="-"+e.version+e.extension;e.url+=","+await getUrl(e)}return await addArchive(e)}async function addPhive(e){switch(true){case/5\.[3-5]/.test(e.php_version):return await f.addLog("$cross","phive","Phive is not supported on PHP "+e.php_version,e.os);case/5\.6|7\.0/.test(e.php_version):e.version="0.12.1";break;case/7\.1/.test(e.php_version):e.version="0.13.5";break;case/7\.2/.test(e.php_version):e.version="0.14.5";break;case/7\.3|7\.4/.test(e.php_version):e.version="0.15.3";break;case/^latest$/.test(e.version):e.version=await getLatestVersion(e);break}e.extension="-"+e.version+e.extension;e.url=await getUrl(e);return await addArchive(e)}async function addPHPUnitTools(e){if(e.version==="latest"){e.version=await l.search(e.packagist,e.php_version)??"latest"}e.url=await getPharUrl(e);if(e.url.match(/-\d+/)){e.url+=","+e.url.replace(/-(\d+)\.\d+\.\d+/,"-$1")}return await addArchive(e)}async function addWPCLI(e){if(e.version==="latest"){e.uri="wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true";e.url=[e.domain,e.uri].join("/")}else{e.extension="-"+e.version+e.extension;e.url=await getUrl(e)}return await addArchive(e)}async function getData(e,t,r){const n=a.default.join(__dirname,"../src/configs/tools.json");const i=c.default.readFileSync(n,"utf8");const s=JSON.parse(i);e=e.replace(/\s+/g,"");const o=e.split(":");const u=o[0];const d=o[1];let l;if(Object.hasOwn(s,u)){l={...s[u],tool:u}}else{const e=Object.keys(s).find(e=>s[e].alias==u);if(e){l={...s[e],tool:e}}else if(u.includes("/")){l={tool:u.split("/")[1],repository:u,type:"composer"}}else{l={tool:u}}}const f="https://github.com";const p=l.domain??f;const h={tool:l.tool,version:"",url:"",os:r,php_version:t,github:f,domain:p,extension:l.extension??".phar",repository:l.repository??"",prefix:p===f?"releases":"",verb:p===f?"download":"",fetch_latest:l.fetch_latest??"false",scope:l.scope??"global",version_parameter:l.version_parameter!=null?JSON.stringify(l.version_parameter):"",version_prefix:l.version_prefix??"",release:"",packagist:l.packagist??l.repository??"",type:l.type,function:l.function,alias:l.alias};h.release=await getRelease(e,h);h.version=d?await getVersion(d,h):await getLatestVersion(h);h.url=await getUrl(h);return h}t.functionRecord={castor:addCastor,composer:addComposer,deployer:addDeployer,dev_tools:addDevTools,phive:addPhive,blackfire_player:addBlackfirePlayer,pecl:addPECL,phing:addPhing,phpunit:addPHPUnitTools,phpcpd:addPHPUnitTools,wp_cli:addWPCLI};async function addTools(e,r,n){let i="\n";if(e==="none"){return""}else{i+=await f.stepLog("Setup Tools",n)}const s=await filterList(await f.CSVArray(e));await f.asyncForEach(s,async function(e){const s=await getData(e,r,n);i+="\n";switch(true){case s.error!==undefined:i+=await f.addLog("$cross",s.tool,s.error,s.os);break;case"phar"===s.type:i+=await addArchive(s);break;case"composer"===s.type:i+=await addPackage(s);break;case"custom-package"===s.type:i+=await f.customPackage(s.tool.split("-")[0],"tools",s.version,s.os);break;case"custom-function"===s.type:if(!s.function){i+=await f.addLog("$cross",s.tool,s.tool+" has no function defined. Please report this issue.",s.os)}else{i+=await t.functionRecord[s.function](s)}break;case/^none$/.test(s.tool):break;default:i+=await f.addLog("$cross",s.tool,"Tool "+s.tool+" is not supported",s.os);break}});return i}},277:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var i=Object.getOwnPropertyDescriptor(t,r);if(!i||("get"in i?!t.__esModule:i.writable||i.configurable)){i={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,i)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var s=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),s=0;sr.indexOf(e)===t);return n.map(e=>process.env[e]||"").find(Boolean)||""}async function getInput(e,t){const r=u.getInput(e);const n=await readEnv(e);switch(true){case r!="":return r;case r==""&&n!="":return n;case r==""&&n==""&&t:throw new Error(`Input required and not supplied: ${e}`);default:return""}}async function getManifestURLS(){return["https://raw.githubusercontent.com/shivammathur/setup-php/develop/src/configs/php-versions.json","https://setup-php.com/php-versions.json"]}async function parseVersion(e){switch(true){case/^pre(-installed)?$/.test(e):return"pre";case/^(latest|lowest|highest|nightly|master|\d+\.x)$/.test(e):for(const t of await getManifestURLS()){const r=await d.fetch(t);if(r["data"]??false){const t=JSON.parse(r["data"])[e];if(t===undefined){throw new Error(`Invalid PHP version: ${e.slice(0,20)}`)}if(!/^\d+\.\d+$/.test(t)){throw new Error(`Invalid PHP version in manifest: ${t.slice(0,10)}`)}return t}}throw new Error(`Could not fetch the PHP version manifest.`);default:if(!/^\d+(\.\d+){0,2}$/.test(e)){throw new Error(`Invalid PHP version: ${e.slice(0,20)}`)}switch(true){case e.length>1:return e.slice(0,3);default:return e+".0"}}}async function parseIniFile(e){if(/^(production|development|none)$/.test(e)){return e}const t=e.match(/php\.ini-(production|development)$/);return t?t[1]:"production"}async function asyncForEach(e,t){for(const[r,n]of e.entries()){await t(n,r,e)}}async function color(e){switch(e){case"error":return"31";default:case"success":return"32";case"warning":return"33"}}async function log(e,t,r){switch(t){case"win32":return'printf "\\033['+await color(r)+";1m"+e+' \\033[0m"';case"linux":case"darwin":default:return'echo "\\033['+await color(r)+";1m"+e+'\\033[0m"'}}async function stepLog(e,t){switch(t){case"win32":return'Step-Log "'+escapeForShell(e,t)+'"';case"linux":case"darwin":return'step_log "'+escapeForShell(e,t)+'"';default:return await log("Platform "+t+" is not supported",t,"error")}}async function addLog(e,t,r,n){const i=escapeForShell(t,n);const s=escapeForShell(r,n);switch(n){case"win32":return`Add-Log "${e}" "${i}" "${s}"`;case"linux":case"darwin":return`add_log "${e}" "${i}" "${s}"`;default:return await log("Platform "+n+" is not supported",n,"error")}}function escapeForShell(e,t){if(t==="win32"){return e.replace(/[`$"]/g,"`$&")}return e.replace(/[\\`$"]/g,"\\$&")}function safeArg(e,t){if(!/^[a-zA-Z0-9_./:@+,~^-]*$/.test(e)){return'"'+escapeForShell(e,t)+'"'}return e}function sanitizeShellInput(e,t=false){const r=t?/[$`"';|&(){}[\]\\<>*?\n\r\t]/g:/[$`"';|&(){}[\]\\\n\r\t]/g;return e.replace(r,"")}async function extensionArray(e){switch(e){case"":case" ":return[];default:return[e.match(/(^|,\s?)none(\s?,|$)/)?"none":"",...e.split(",").map(function(e){e=e.trim().replace(/^\\\s*/,"");if(/.+-.+\/.+@.+/.test(e)){return e}return e.toLowerCase().replace(/^(:)?(php[-_]|none|zend )|(-[^-]*)-/,"$1$3")})].filter(Boolean)}}async function CSVArray(e){switch(e){case"":case" ":return[];default:return e.split(/,(?=(?:(?:[^"']*["']){2})*[^"']*$)/).map(function(e){return e.trim().replace(/^["']|["']$|(?<==)["']/g,"").replace(/=(((?!E_).)*[?{}|&~![()^]+((?!E_).)+)/,"='$1'").replace(/=(.*?)(=.*)/,"='$1$2'").replace(/:\s*["'](.*?)/g,":$1")}).filter(Boolean)}}async function getExtensionPrefix(e){switch(true){default:return"extension";case/xdebug([2-3])?$|opcache|ioncube|eaccelerator/.test(e):return"zend_extension"}}async function suppressOutput(e){switch(e){case"win32":return" >$null 2>&1";case"linux":case"darwin":return" >/dev/null 2>&1";default:return await log("Platform "+e+" is not supported",e,"error")}}async function getUnsupportedLog(e,t,r){return"\n"+await addLog("$cross",e,[e,"is not supported on PHP",t].join(" "),r)+"\n"}async function getCommand(e,t){switch(e){case"linux":case"darwin":return"add_"+t+" ";case"win32":return"Add-"+t.split("_").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("")+" ";default:return await log("Platform "+e+" is not supported",e,"error")}}async function joins(...e){return[...e].join(" ")}async function scriptExtension(e){switch(e){case"win32":return".ps1";case"linux":case"darwin":return".sh";default:return await log("Platform "+e+" is not supported",e,"error")}}async function scriptTool(e){switch(e){case"win32":return"pwsh ";case"linux":case"darwin":return"bash ";default:return await log("Platform "+e+" is not supported",e,"error")}}async function customPackage(e,t,r,n){const i=e.replace(/\d+|(pdo|pecl)[_-]|[_-]db2/,"");const s=await scriptExtension(n);const o=c.join(__dirname,"../src/scripts/"+t+"/"+i+s);const a=await getCommand(n,i);return"\n. "+o+"\n"+a+r}async function parseExtensionSource(e,t){const r=/(\w+)-(\w+:\/\/.{1,253}(?:[.:][^:/\s]{2,63})+\/)?([\w.-]+)\/([\w.-]+)@(.+)/;const n=r.exec(e);n[2]=n[2]?n[2].slice(0,-1):"https://github.com";return await joins("\nadd_extension_from_source",...n.splice(1,n.length),t)}const l=/^(latest|lowest|highest|nightly|master|pre|pre-installed|\d+\.x|\d+(\.\d+){0,2})$/;function validatePHPVersionInput(e,t){if(!l.test(e)){throw new Error(`Invalid PHP version in ${t}: ${e.slice(0,20)}`)}return e}async function readPHPVersion(){const e=await getInput("php-version",false);if(e){return validatePHPVersionInput(e,"php-version input")}const t=await getInput("php-version-file",false)||".php-version";if(a.default.existsSync(t)){const e=a.default.readFileSync(t,"utf8");const r=e.match(/^(?:php\s)?(\d+\.\d+\.\d+)$/m);return validatePHPVersionInput(r?r[1]:e.trim(),t)}else if(t!==".php-version"){throw new Error(`Could not find '${t}' file.`)}const r=await readEnv("COMPOSER_PROJECT_DIR");const n=c.join(r,"composer.lock");if(a.default.existsSync(n)){const e=JSON.parse(a.default.readFileSync(n,"utf8"));if(e["platform-overrides"]?.["php"]){return validatePHPVersionInput(e["platform-overrides"]["php"],"composer.lock platform-overrides.php")}}const i=c.join(r,"composer.json");if(a.default.existsSync(i)){const e=JSON.parse(a.default.readFileSync(i,"utf8"));if(e["config"]?.["platform"]?.["php"]){return validatePHPVersionInput(e["config"]["platform"]["php"],"composer.json config.platform.php")}}return"latest"}async function setVariable(e,t,r){switch(r){case"win32":return"\n$"+e+" = "+t+"\n";case"linux":case"darwin":default:return"\n"+e+'="$('+t+')"\n'}}},236:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var i=Object.getOwnPropertyDescriptor(t,r);if(!i||("get"in i?!t.__esModule:i.writable||i.configurable)){i={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,i)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var s=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),s=0;s{o+=u.write(e);if(l){l(e)}};const stdOutListener=e=>{s+=c.write(e);if(d){d(e)}};const f=Object.assign(Object.assign({},r===null||r===void 0?void 0:r.listeners),{stdout:stdOutListener,stderr:stdErrListener});const p=yield exec(e,t,Object.assign(Object.assign({},r),{listeners:f}));s+=c.end();o+=u.end();return{exitCode:p,stdout:s,stderr:o}})}},665:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var i=Object.getOwnPropertyDescriptor(t,r);if(!i||("get"in i?!t.__esModule:i.writable||i.configurable)){i={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,i)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var s=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),s=0;s-1){const e=n.substring(0,i);r(e);n=n.substring(i+a.EOL.length);i=n.indexOf(a.EOL)}return n}catch(e){this._debug(`error processing line. Failed with error ${e}`);return""}}_getSpawnFileName(){if(h){if(this._isCmdFile()){return process.env["COMSPEC"]||"cmd.exe"}}return this.toolPath}_getSpawnArgs(e){if(h){if(this._isCmdFile()){let t=`/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`;for(const r of this.args){t+=" ";t+=e.windowsVerbatimArguments?r:this._windowsQuoteCmdArg(r)}t+='"';return[t]}}return this.args}_endsWith(e,t){return e.endsWith(t)}_isCmdFile(){const e=this.toolPath.toUpperCase();return this._endsWith(e,".CMD")||this._endsWith(e,".BAT")}_windowsQuoteCmdArg(e){if(!this._isCmdFile()){return this._uvQuoteCmdArg(e)}if(!e){return'""'}const t=[" ","\t","&","(",")","[","]","{","}","^","=",";","!","'","+",",","`","~","|","<",">",'"'];let r=false;for(const n of e){if(t.some(e=>e===n)){r=true;break}}if(!r){return e}let n='"';let i=true;for(let t=e.length;t>0;t--){n+=e[t-1];if(i&&e[t-1]==="\\"){n+="\\"}else if(e[t-1]==='"'){i=true;n+='"'}else{i=false}}n+='"';return n.split("").reverse().join("")}_uvQuoteCmdArg(e){if(!e){return'""'}if(!e.includes(" ")&&!e.includes("\t")&&!e.includes('"')){return e}if(!e.includes('"')&&!e.includes("\\")){return`"${e}"`}let t='"';let r=true;for(let n=e.length;n>0;n--){t+=e[n-1];if(r&&e[n-1]==="\\"){t+="\\"}else if(e[n-1]==='"'){r=true;t+="\\"}else{r=false}}t+='"';return t.split("").reverse().join("")}_cloneExecOptions(e){e=e||{};const t={cwd:e.cwd||process.cwd(),env:e.env||process.env,silent:e.silent||false,windowsVerbatimArguments:e.windowsVerbatimArguments||false,failOnStdErr:e.failOnStdErr||false,ignoreReturnCode:e.ignoreReturnCode||false,delay:e.delay||1e4};t.outStream=e.outStream||process.stdout;t.errStream=e.errStream||process.stderr;return t}_getSpawnOptions(e,t){e=e||{};const r={};r.cwd=e.cwd;r.env=e.env;r["windowsVerbatimArguments"]=e.windowsVerbatimArguments||this._isCmdFile();if(e.windowsVerbatimArguments){r.argv0=`"${t}"`}return r}exec(){return o(this,void 0,void 0,function*(){if(!f.isRooted(this.toolPath)&&(this.toolPath.includes("/")||h&&this.toolPath.includes("\\"))){this.toolPath=d.resolve(process.cwd(),this.options.cwd||process.cwd(),this.toolPath)}this.toolPath=yield l.which(this.toolPath,true);return new Promise((e,t)=>o(this,void 0,void 0,function*(){this._debug(`exec tool: ${this.toolPath}`);this._debug("arguments:");for(const e of this.args){this._debug(` ${e}`)}const r=this._cloneExecOptions(this.options);if(!r.silent&&r.outStream){r.outStream.write(this._getCommandString(r)+a.EOL)}const n=new ExecState(r,this.toolPath);n.on("debug",e=>{this._debug(e)});if(this.options.cwd&&!(yield f.exists(this.options.cwd))){return t(new Error(`The cwd: ${this.options.cwd} does not exist!`))}const i=this._getSpawnFileName();const s=u.spawn(i,this._getSpawnArgs(r),this._getSpawnOptions(this.options,i));let o="";if(s.stdout){s.stdout.on("data",e=>{if(this.options.listeners&&this.options.listeners.stdout){this.options.listeners.stdout(e)}if(!r.silent&&r.outStream){r.outStream.write(e)}o=this._processLineBuffer(e,o,e=>{if(this.options.listeners&&this.options.listeners.stdline){this.options.listeners.stdline(e)}})})}let c="";if(s.stderr){s.stderr.on("data",e=>{n.processStderr=true;if(this.options.listeners&&this.options.listeners.stderr){this.options.listeners.stderr(e)}if(!r.silent&&r.errStream&&r.outStream){const t=r.failOnStdErr?r.errStream:r.outStream;t.write(e)}c=this._processLineBuffer(e,c,e=>{if(this.options.listeners&&this.options.listeners.errline){this.options.listeners.errline(e)}})})}s.on("error",e=>{n.processError=e.message;n.processExited=true;n.processClosed=true;n.CheckComplete()});s.on("exit",e=>{n.processExitCode=e;n.processExited=true;this._debug(`Exit code ${e} received from tool '${this.toolPath}'`);n.CheckComplete()});s.on("close",e=>{n.processExitCode=e;n.processExited=true;n.processClosed=true;this._debug(`STDIO streams have closed for tool '${this.toolPath}'`);n.CheckComplete()});n.on("done",(r,n)=>{if(o.length>0){this.emit("stdline",o)}if(c.length>0){this.emit("errline",c)}s.removeAllListeners();if(r){t(r)}else{e(n)}});if(this.options.input){if(!s.stdin){throw new Error("child process missing stdin")}s.stdin.end(this.options.input)}}))})}}t.ToolRunner=ToolRunner;function argStringToArray(e){const t=[];let r=false;let n=false;let i="";function append(e){if(n&&e!=='"'){i+="\\"}i+=e;n=false}for(let s=0;s0){t.push(i);i=""}continue}append(o)}if(i.length>0){t.push(i.trim())}return t}class ExecState extends c.EventEmitter{constructor(e,t){super();this.processClosed=false;this.processError="";this.processExitCode=0;this.processExited=false;this.processStderr=false;this.delay=1e4;this.done=false;this.timeout=null;if(!t){throw new Error("toolPath must not be empty")}this.options=e;this.toolPath=t;if(e.delay){this.delay=e.delay}}CheckComplete(){if(this.done){return}if(this.processClosed){this._setResult()}else if(this.processExited){this.timeout=(0,p.setTimeout)(ExecState.HandleTimeout,this.delay,this)}}_debug(e){this.emit("debug",e)}_setResult(){let e;if(this.processExited){if(this.processError){e=new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`)}else if(this.processExitCode!==0&&!this.options.ignoreReturnCode){e=new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`)}else if(this.processStderr&&this.options.failOnStdErr){e=new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`)}}if(this.timeout){clearTimeout(this.timeout);this.timeout=null}this.done=true;this.emit("done",e,this.processExitCode)}static HandleTimeout(e){if(e.done){return}if(!e.processClosed&&e.processExited){const t=`The STDIO streams did not close within ${e.delay/1e3} seconds of the exit event from process '${e.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`;e._debug(t)}e._setResult()}}},207:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var i=Object.getOwnPropertyDescriptor(t,r);if(!i||("get"in i?!t.__esModule:i.writable||i.configurable)){i={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,i)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var s=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),s=0;se.toUpperCase()===t)){return e}}else{if(isUnixExecutable(n)){return e}}}const i=e;for(const s of r){e=i+s;n=undefined;try{n=yield(0,t.stat)(e)}catch(t){if(t.code!=="ENOENT"){console.log(`Unexpected error attempting to determine if executable file exists '${e}': ${t}`)}}if(n&&n.isFile()){if(t.IS_WINDOWS){try{const r=u.dirname(e);const n=u.basename(e).toUpperCase();for(const i of yield(0,t.readdir)(r)){if(n===i.toUpperCase()){e=u.join(r,i);break}}}catch(t){console.log(`Unexpected error attempting to determine the actual case of the file '${e}': ${t}`)}return e}else{if(isUnixExecutable(n)){return e}}}}return""})}function normalizeSeparators(e){e=e||"";if(t.IS_WINDOWS){e=e.replace(/\//g,"\\");return e.replace(/\\\\+/g,"\\")}return e.replace(/\/\/+/g,"/")}function isUnixExecutable(e){return(e.mode&1)>0||(e.mode&8)>0&&process.getgid!==undefined&&e.gid===process.getgid()||(e.mode&64)>0&&process.getuid!==undefined&&e.uid===process.getuid()}function getCmdPath(){var e;return(e=process.env["COMSPEC"])!==null&&e!==void 0?e:`cmd.exe`}},994:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var i=Object.getOwnPropertyDescriptor(t,r);if(!i||("get"in i?!t.__esModule:i.writable||i.configurable)){i={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,i)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var i=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var s=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),s=0;s|]/.test(e)){throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows')}}try{yield u.rm(e,{force:true,maxRetries:3,recursive:true,retryDelay:300})}catch(e){throw new Error(`File was unable to be removed ${e}`)}})}function mkdirP(e){return o(this,void 0,void 0,function*(){(0,a.ok)(e,"a path argument must be provided");yield u.mkdir(e,{recursive:true})})}function which(e,t){return o(this,void 0,void 0,function*(){if(!e){throw new Error("parameter 'tool' is required")}if(t){const t=yield which(e,false);if(!t){if(u.IS_WINDOWS){throw new Error(`Unable to locate executable file: ${e}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`)}else{throw new Error(`Unable to locate executable file: ${e}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`)}}return t}const r=yield findInPath(e);if(r&&r.length>0){return r[0]}return""})}function findInPath(e){return o(this,void 0,void 0,function*(){if(!e){throw new Error("parameter 'tool' is required")}const t=[];if(u.IS_WINDOWS&&process.env["PATHEXT"]){for(const e of process.env["PATHEXT"].split(c.delimiter)){if(e){t.push(e)}}}if(u.isRooted(e)){const r=yield u.tryGetExecutablePath(e,t);if(r){return[r]}return[]}if(e.includes(c.sep)){return[]}const r=[];if(process.env.PATH){for(const e of process.env.PATH.split(c.delimiter)){if(e){r.push(e)}}}const n=[];for(const i of r){const r=yield u.tryGetExecutablePath(c.join(i,e),t);if(r){n.push(r)}}return n})}function readCopyOptions(e){const t=e.force==null?true:e.force;const r=Boolean(e.recursive);const n=e.copySourceDirectory==null?true:Boolean(e.copySourceDirectory);return{force:t,recursive:r,copySourceDirectory:n}}function cpDirRecursive(e,t,r,n){return o(this,void 0,void 0,function*(){if(r>=255)return;r++;yield mkdirP(t);const i=yield u.readdir(e);for(const s of i){const i=`${e}/${s}`;const o=`${t}/${s}`;const a=yield u.lstat(i);if(a.isDirectory()){yield cpDirRecursive(i,o,r,n)}else{yield copyFile(i,o,n)}}yield u.chmod(t,(yield u.stat(e)).mode)})}function copyFile(e,t,r){return o(this,void 0,void 0,function*(){if((yield u.lstat(e)).isSymbolicLink()){try{yield u.lstat(t);yield u.unlink(t)}catch(e){if(e.code==="EPERM"){yield u.chmod(t,"0666");yield u.unlink(t)}}const r=yield u.readlink(e);yield u.symlink(r,t,u.IS_WINDOWS?"junction":null)}else if(!(yield u.exists(t))||r){yield u.copyFile(e,t)}})}},26:function(e,t){(function(e,r){true?r(t):0})(this,function(e){"use strict";const t=/^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;const validateAndParse=e=>{if(typeof e!=="string"){throw new TypeError("Invalid argument expected string")}const r=e.match(t);if(!r){throw new Error(`Invalid argument not valid semver ('${e}' received)`)}r.shift();return r};const isWildcard=e=>e==="*"||e==="x"||e==="X";const tryParse=e=>{const t=parseInt(e,10);return isNaN(t)?e:t};const forceType=(e,t)=>typeof e!==typeof t?[String(e),String(t)]:[e,t];const compareStrings=(e,t)=>{if(isWildcard(e)||isWildcard(t))return 0;const[r,n]=forceType(tryParse(e),tryParse(t));if(r>n)return 1;if(r{for(let r=0;r{const r=validateAndParse(e);const n=validateAndParse(t);const i=r.pop();const s=n.pop();const o=compareSegments(r,n);if(o!==0)return o;if(i&&s){return compareSegments(i.split("."),s.split("."))}else if(i||s){return i?-1:1}return 0};const compare=(e,t,n)=>{assertValidOperator(n);const i=compareVersions(e,t);return r[n].includes(i)};const r={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1],"!=":[-1,1]};const n=Object.keys(r);const assertValidOperator=e=>{if(typeof e!=="string"){throw new TypeError(`Invalid operator type, expected string but got ${typeof e}`)}if(n.indexOf(e)===-1){throw new Error(`Invalid operator, expected one of ${n.join("|")}`)}};const satisfies=(e,t)=>{t=t.replace(/([><=]+)\s+/g,"$1");if(t.includes("||")){return t.split("||").some(t=>satisfies(e,t))}else if(t.includes(" - ")){const[r,n]=t.split(" - ",2);return satisfies(e,`>=${r} <=${n}`)}else if(t.includes(" ")){return t.trim().replace(/\s{2,}/g," ").split(" ").every(t=>satisfies(e,t))}const r=t.match(/^([<>=~^]+)/);const n=r?r[1]:"=";if(n!=="^"&&n!=="~")return compare(e,t,n);const[i,s,o,,a]=validateAndParse(e);const[c,u,d,,l]=validateAndParse(t);const f=[i,s,o];const p=[c,u!==null&&u!==void 0?u:"x",d!==null&&d!==void 0?d:"x"];if(l){if(!a)return false;if(compareSegments(f,p)!==0)return false;if(compareSegments(a.split("."),l.split("."))===-1)return false}const h=p.findIndex(e=>e!=="0")+1;const g=n==="~"?2:h>1?h:1;if(compareSegments(f.slice(0,g),p.slice(0,g))!==0)return false;if(compareSegments(f.slice(g),p.slice(g))===-1)return false;return true};const validate=e=>typeof e==="string"&&/^[v\d]/.test(e)&&t.test(e);const validateStrict=e=>typeof e==="string"&&/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/.test(e);e.compare=compare;e.compareVersions=compareVersions;e.satisfies=satisfies;e.validate=validate;e.validateStrict=validateStrict})},613:e=>{"use strict";e.exports=require("assert")},317:e=>{"use strict";e.exports=require("child_process")},434:e=>{"use strict";e.exports=require("events")},896:e=>{"use strict";e.exports=require("fs")},857:e=>{"use strict";e.exports=require("os")},928:e=>{"use strict";e.exports=require("path")},193:e=>{"use strict";e.exports=require("string_decoder")},557:e=>{"use strict";e.exports=require("timers")}};var t={};function __nccwpck_require__(r){var n=t[r];if(n!==undefined){return n.exports}var i=t[r]={exports:{}};var s=true;try{e[r].call(i.exports,i,i.exports,__nccwpck_require__);s=false}finally{if(s)delete t[r]}return i.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var r=__nccwpck_require__(755);module.exports=r})(); \ No newline at end of file +(()=>{var e={472:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var s=Object.getOwnPropertyDescriptor(t,r);if(!s||("get"in s?!t.__esModule:s.writable||s.configurable)){s={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,s)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var i=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),i=0;io.escapeForShell(e,"linux")).join("\n")+'" | sudo tee -a "${pecl_file:-${ini_file[@]}}" >/dev/null 2>&1'+r}async function addINIValuesWindows(e){const t=await o.CSVArray(e);let r="\n";await o.asyncForEach(t,async function(e){r+=await o.addLog("$tick",e,"Added to php.ini","win32")+"\n"});return'Add-Content "$php_dir\\php.ini" "'+t.map(e=>o.escapeForShell(e,"win32")).join("\n")+'"'+r}async function addINIValues(e,t,r=false){let n="\n";switch(r){case true:n+=await o.stepLog("Add php.ini values",t)+await o.suppressOutput(t)+"\n";break;case false:default:n+=await o.stepLog("Add php.ini values",t)+"\n";break}switch(t){case"win32":return n+await addINIValuesWindows(e);case"darwin":case"linux":return n+await addINIValuesUnix(e);default:return await o.log("Platform "+t+" is not supported",t,"error")}}},469:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:true});t.issueCommand=issueCommand;t.error=error;t.setFailed=setFailed;t.getInput=getInput;const n=r(857);function toCommandValue(e){if(e instanceof Error){return e.toString()}return e}function escapeData(e){return toCommandValue(e).replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A")}function escapeProperty(e){return e.replace(/%/g,"%25").replace(/\r/g,"%0D").replace(/\n/g,"%0A").replace(/:/g,"%3A").replace(/,/g,"%2C")}function issueCommand(e,t,r){let s=`::${e}`;if(t&&Object.keys(t).length>0){s+=" ";const e=Object.entries(t).filter(([,e])=>e).map(([e,t])=>`${e}=${escapeProperty(t)}`).join(",");s+=e}s+=`::${escapeData(r)}`;process.stdout.write(s+n.EOL)}function error(e){issueCommand("error",{},e)}function setFailed(e){process.exitCode=1;error(e)}function getInput(e,t=false){const r=process.env[`INPUT_${e.replace(/ /g,"_").toUpperCase()}`]||"";if(t&&!r){throw new Error(`Input required and not supplied: ${e}`)}return r.trim()}},524:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var s=Object.getOwnPropertyDescriptor(t,r);if(!s||("get"in s?!t.__esModule:s.writable||s.configurable)){s={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,s)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var i=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),i=0;i{"use strict";Object.defineProperty(t,"__esModule",{value:true});t.fetch=fetch;const r=new Set([301,302,303,307,308]);async function fetch(e,t,n=5){const s={"User-Agent":`Mozilla/5.0 (${process.platform} ${process.arch}) setup-php`};if(t){s["Authorization"]="Bearer "+t}try{const t=await globalThis.fetch(e,{headers:s,redirect:n>0?"follow":"manual"});if(t.ok){const e=await t.text();return{data:e}}else if(r.has(t.status)&&n<=0){return{error:`${t.status}: Redirect error`}}else{return{error:`${t.status}: ${t.statusText}`}}}catch(e){return{error:`Fetch error: ${e.message}`}}}},755:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var s=Object.getOwnPropertyDescriptor(t,r);if(!s||("get"in s?!t.__esModule:s.writable||s.configurable)){s={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,s)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var i=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),i=0;i{await run()})().catch(e=>{l.setFailed(e.message)})},75:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var s=Object.getOwnPropertyDescriptor(t,r);if(!s||("get"in s?!t.__esModule:s.writable||s.configurable)){s={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,s)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var i=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),i=0;io.compareVersions(t.version,e.version));const s=r.find(e=>{if(e?.require?.php){return e?.require?.php.split("|").some(e=>e&&o.satisfies(t+".0",e))}return false});return s?s.version:null}return null}},159:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var s=Object.getOwnPropertyDescriptor(t,r);if(!s||("get"in s?!t.__esModule:s.writable||s.configurable)){s={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,s)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var i=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),i=0;i{const[r,n]=t.trim().split(/\s+/);return u.compareVersions(e,r)>=0&&u.compareVersions(e,n)<0})}function cleanComposerAuthJson(){try{const e=process.env["COMPOSER_AUTH_JSON"]||"";if(!e.includes("github-oauth"))return;const t=JSON.parse(e);delete t["github-oauth"];if(!Object.keys(t).length){delete process.env["COMPOSER_AUTH_JSON"]}else{process.env["COMPOSER_AUTH_JSON"]=JSON.stringify(t)}}catch{return}}async function getSemverVersion(e){const fixSemver=e=>{if(/^\d+\.\d+\.\d+(-|$)/.test(e))return e;const t=e.match(/^(\d+\.\d+\.\d+)([A-Za-z]+[0-9A-Za-z.]+)$/);return t?`${t[1]}-${t[2]}`:e};const t=e["version_prefix"]+e["version"];const r=`https://api.github.com/repos/${e["repository"]}/git/matching-refs/tags%2F${t}.`;const n=await f.readEnv("GITHUB_TOKEN")||await f.readEnv("COMPOSER_TOKEN");const s=await d.fetch(r,n);if(s.error||s.data==="[]"){e.error=s.error??`No version found with prefix ${t}.`;return e.version}else{const e=JSON.parse(s.data);const t=e.map(e=>(e.ref?.split("/").pop()??"").replace(/^v(?=\d)/,"")).filter(e=>e.length>0);const r=new Map;const n=t.map(e=>{const t=fixSemver(e);r.set(t,e);return t});const i=n.toSorted((e,t)=>{try{return u.compareVersions(t,e)}catch{return t.localeCompare(e,"en",{numeric:true,sensitivity:"base"})}});return r.get(i[0])??i[0]}}async function getLatestVersion(e){if(!e.version&&e.fetch_latest==="false"){return"latest"}if(e.fetch_latest==="true"&&!e.repository){return"latest"}const t=await d.fetch(`${e.github}/${e.repository}/releases.atom`);if(t.data){const e=[...t.data.matchAll(/releases\/tag\/([a-zA-Z]*)?(\d+\.\d+\.\d+)"/g)].map(e=>e[2]);const r=e.toSorted((e,t)=>e.localeCompare(t,undefined,{numeric:true}));return r.at(-1)||"latest"}return"latest"}async function getVersion(e,t){const r=/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;const n=/^composer:(stable|preview|snapshot|[12])$/;const s=/[><=^~]+.*/;const i=/^\d+(\.\d+)?$/;t.version=e.replace(/v?(\d)/,"$1").replace(/\.x/,"");switch(true){case n.test(t.release):case r.test(t.version):case s.test(t.version)&&t.type==="composer":return t.version;case i.test(t.version)&&t.type==="composer":t.release=`${t.tool}:${t.version}.*`;return`${t.version}.*`;case!!t.repository&&i.test(t.version):return await getSemverVersion(t);default:return t.version.replace(/[^a-zA-Z0-9_.:@+,/-]/g,"")}}async function getRelease(e,t){e=e.includes("/")?e.split("/")[1]:e;return e.includes(":")?[t.tool,e.split(":")[1]].join(":"):t.tool}async function filterList(e){const t=/^composer($|:.*)/;const r=/^composer:?($|preview$|snapshot$|v?\d+(\.\d+)?$|v?\d+\.\d+\.\d+[\w-]*$)/;const n=e.filter(e=>r.test(e.replace(p,"")));let s="composer";e=e.filter(e=>!t.test(e));switch(true){case n[0]==undefined:break;default:s=n.at(-1).replace(/v(\d\S*)/,"$1");break}e.unshift(s);return e}async function getUrl(e){const t=e.version??"latest";if(t==="latest"||t===""){return[e.domain,e.repository,e.prefix,"latest",e.verb,e.tool+e.extension].filter(Boolean).join("/")}else{return[e.domain,e.repository,e.prefix,e.verb,e.version_prefix+e.version,e.tool+e.extension].filter(Boolean).join("/")}}async function getPharUrl(e){if(e.version==="latest"){return e.domain+"/"+e.tool+".phar"}else{return e.domain+"/"+e.tool+"-"+e.version_prefix+e.version+".phar"}}async function addArchive(e){return await f.getCommand(e.os,"tool")+await f.joins(e.url,e.tool,e.version_parameter)+(e.checksum?" "+e.checksum:"")}async function addPackage(e){const t=await f.getCommand(e.os,"composer_tool");const r=e.repository.split("/");const n=[r[1],e.release,r[0]+"/",e.scope].map(t=>f.safeArg(t,e.os)).join(" ");return t+n}async function addBlackfirePlayer(e){switch(e.os){case"win32":return await f.addLog("$cross",e.tool,e.tool+" is not a windows tool","win32");default:if(e.version=="latest"){if(/5\.[5-6]|7\.0/.test(e.php_version)){e.version="1.9.3"}else if(/7\.[1-4]|8\.0/.test(e.php_version)){e.version="1.22.0"}}e.url=await getPharUrl(e);return addArchive(e)}}async function addCastor(e){e.tool="castor."+e.os.replace("win32","windows")+"-amd64";e.url=await getUrl(e);e.tool="castor";e.version_parameter=c.default.existsSync("castor.php")?e.version_parameter:"";return await addArchive(e)}async function addComposer(e){const t=e.version.replace("latest","stable");const r=e.github;const n=e.domain;const s="https://dl.cloudsmith.io";const i="https://artifacts.setup-php.com";const o=`composer-${e.php_version}-${t}.phar`;const a=`${r}/shivammathur/composer-cache/releases/latest/download/${o}`;const c=`${s}/public/shivammathur/composer-cache/raw/files/${o}`;const u=`${i}/composer/${o}`;const d=`${n}/download/latest-2.2.x/composer.phar`;const l=/^5\.[3-6]$|^7\.[0-1]$/.test(e.php_version);const p=`${n}/composer-${t}.phar`;const h=`${n}/download/${t}/composer.phar`;let g=`${a},${u},${c}`;let w=`${n}/composer.phar`;let v="";switch(true){case/^snapshot$/.test(t):w=l?d:w;break;case/^preview$|^2$/.test(t):w=l?d:p;break;case/^1$/.test(t):w=p;break;case/^\d+\.\d+\.\d+(?:-[\w-]+)?$/.test(e.version):if(skipGitHubAuthForComposerVersion(e.version)){cleanComposerAuthJson();v=" true"}g=`${r}/${e.repository}/releases/download/${e.version}/composer.phar`;w=h;break;default:w=l?d:p}const m=await f.readEnv("NO_TOOLS_CACHE")!=="true";e.url=m?`${g},${w}`:w;e.version_parameter=e.version+v;return await addArchive(e)}async function addDeployer(e){if(e.version==="latest"){e.url=e.domain+"/deployer.phar"}else{const t=await d.fetch("https://deployer.org/manifest.json");const r=JSON.parse(t.data);const n=Object.keys(r).find(t=>r[t].version===e.version);if(n){e.url=r[n].url}else{return await f.addLog("$cross","deployer","Version missing in deployer manifest",e.os)}}return await addArchive(e)}async function addDevTools(e){switch(e.os){case"linux":case"darwin":return"add_devtools "+e.tool;case"win32":return await f.addLog("$tick",e.tool,e.tool+" is not a windows tool","win32");default:return await f.log("Platform "+e.os+" is not supported",e.os,"error")}}async function addPECL(e){return await f.getCommand(e.os,"pecl")}async function addPhing(e){e.url=e.domain+"/get/phing-"+e.version+e.extension;if(e.version!="latest"){[e.prefix,e.verb]=["releases","download"];e.domain=e.github;e.extension="-"+e.version+e.extension;e.url+=","+await getUrl(e)}return await addArchive(e)}async function addPhive(e){switch(true){case/5\.[3-5]/.test(e.php_version):return await f.addLog("$cross","phive","Phive is not supported on PHP "+e.php_version,e.os);case/5\.6|7\.0/.test(e.php_version):e.version="0.12.1";break;case/7\.1/.test(e.php_version):e.version="0.13.5";break;case/7\.2/.test(e.php_version):e.version="0.14.5";break;case/7\.3|7\.4/.test(e.php_version):e.version="0.15.3";break;case/^latest$/.test(e.version):e.version=await getLatestVersion(e);break}e.extension="-"+e.version+e.extension;e.url=await getUrl(e);return await addArchive(e)}async function addPHPUnitTools(e){if(e.version==="latest"){e.version=await l.search(e.packagist,e.php_version)??"latest"}e.url=await getPharUrl(e);if(e.url.match(/-\d+/)){e.url+=","+e.url.replace(/-(\d+)\.\d+\.\d+/,"-$1")}return await addArchive(e)}async function addWPCLI(e){if(e.version==="latest"){e.uri="wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true";e.url=[e.domain,e.uri].join("/")}else{e.extension="-"+e.version+e.extension;e.url=await getUrl(e)}return await addArchive(e)}async function getData(e,t,r){const n=a.default.join(__dirname,"../src/configs/tools.json");const s=c.default.readFileSync(n,"utf8");const i=JSON.parse(s);e=e.replace(/\s+/g,"");const o=extractChecksum(e);e=o.release;const u=e.split(":");const d=u[0];const l=u[1];let f;if(Object.hasOwn(i,d)){f={...i[d],tool:d}}else{const e=Object.keys(i).find(e=>i[e].alias==d);if(e){f={...i[e],tool:e}}else if(d.includes("/")){f={tool:d.split("/")[1],repository:d,type:"composer"}}else{f={tool:d}}}const p="https://github.com";const h=f.domain??p;const g={tool:f.tool,version:"",url:"",os:r,php_version:t,github:p,domain:h,extension:f.extension??".phar",repository:f.repository??"",prefix:h===p?"releases":"",verb:h===p?"download":"",fetch_latest:f.fetch_latest??"false",scope:f.scope??"global",version_parameter:f.version_parameter!=null?JSON.stringify(f.version_parameter):"",version_prefix:f.version_prefix??"",release:"",packagist:f.packagist??f.repository??"",type:f.type,function:f.function,alias:f.alias};g.checksum=o.checksum;g.error=o.error;g.release=await getRelease(e,g);g.version=l?await getVersion(l,g):await getLatestVersion(g);g.url=await getUrl(g);return g}t.functionRecord={castor:addCastor,composer:addComposer,deployer:addDeployer,dev_tools:addDevTools,phive:addPhive,blackfire_player:addBlackfirePlayer,pecl:addPECL,phing:addPhing,phpunit:addPHPUnitTools,phpcpd:addPHPUnitTools,wp_cli:addWPCLI};async function supportsChecksum(e){switch(e.type){case"phar":return true;case"custom-function":return!["pecl","dev_tools"].includes(e.function??"");default:return false}}async function addTools(e,r,n){let s="\n";if(e==="none"){return""}else{s+=await f.stepLog("Setup Tools",n)}const i=await filterList(await f.CSVArray(e));await f.asyncForEach(i,async function(e){const i=await getData(e,r,n);s+="\n";switch(true){case i.error!==undefined:s+=await f.addLog("$cross",i.tool,i.error,i.os);break;case i.checksum!==undefined&&!await supportsChecksum(i):s+=await f.addLog("$cross",i.tool,"Checksum verification is not supported for "+i.tool,i.os);break;case"phar"===i.type:s+=await addArchive(i);break;case"composer"===i.type:s+=await addPackage(i);break;case"custom-package"===i.type:s+=await f.customPackage(i.tool.split("-")[0],"tools",i.version,i.os);break;case"custom-function"===i.type:if(!i.function){s+=await f.addLog("$cross",i.tool,i.tool+" has no function defined. Please report this issue.",i.os)}else{s+=await t.functionRecord[i.function](i)}break;case/^none$/.test(i.tool):break;default:s+=await f.addLog("$cross",i.tool,"Tool "+i.tool+" is not supported",i.os);break}});return s}},277:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var s=Object.getOwnPropertyDescriptor(t,r);if(!s||("get"in s?!t.__esModule:s.writable||s.configurable)){s={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,s)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var i=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),i=0;ir.indexOf(e)===t);return n.map(e=>process.env[e]||"").find(Boolean)||""}async function getInput(e,t){const r=u.getInput(e);const n=await readEnv(e);switch(true){case r!="":return r;case r==""&&n!="":return n;case r==""&&n==""&&t:throw new Error(`Input required and not supplied: ${e}`);default:return""}}async function getManifestURLS(){return["https://raw.githubusercontent.com/shivammathur/setup-php/develop/src/configs/php-versions.json","https://setup-php.com/php-versions.json"]}async function parseVersion(e){switch(true){case/^pre(-installed)?$/.test(e):return"pre";case/^(latest|lowest|highest|nightly|master|\d+\.x)$/.test(e):for(const t of await getManifestURLS()){const r=await d.fetch(t);if(r["data"]??false){const t=JSON.parse(r["data"])[e];if(t===undefined){throw new Error(`Invalid PHP version: ${e.slice(0,20)}`)}if(!/^\d+\.\d+$/.test(t)){throw new Error(`Invalid PHP version in manifest: ${t.slice(0,10)}`)}return t}}throw new Error(`Could not fetch the PHP version manifest.`);default:if(!/^\d+(\.\d+){0,2}$/.test(e)){throw new Error(`Invalid PHP version: ${e.slice(0,20)}`)}switch(true){case e.length>1:return e.slice(0,3);default:return e+".0"}}}async function parseIniFile(e){if(/^(production|development|none)$/.test(e)){return e}const t=e.match(/php\.ini-(production|development)$/);return t?t[1]:"production"}async function asyncForEach(e,t){for(const[r,n]of e.entries()){await t(n,r,e)}}async function color(e){switch(e){case"error":return"31";default:case"success":return"32";case"warning":return"33"}}async function log(e,t,r){switch(t){case"win32":return'printf "\\033['+await color(r)+";1m"+e+' \\033[0m"';case"linux":case"darwin":default:return'echo "\\033['+await color(r)+";1m"+e+'\\033[0m"'}}async function stepLog(e,t){switch(t){case"win32":return'Step-Log "'+escapeForShell(e,t)+'"';case"linux":case"darwin":return'step_log "'+escapeForShell(e,t)+'"';default:return await log("Platform "+t+" is not supported",t,"error")}}async function addLog(e,t,r,n){const s=escapeForShell(t,n);const i=escapeForShell(r,n);switch(n){case"win32":return`Add-Log "${e}" "${s}" "${i}"`;case"linux":case"darwin":return`add_log "${e}" "${s}" "${i}"`;default:return await log("Platform "+n+" is not supported",n,"error")}}function escapeForShell(e,t){if(t==="win32"){return e.replace(/[`$"]/g,"`$&")}return e.replace(/[\\`$"]/g,"\\$&")}function safeArg(e,t){if(!/^[a-zA-Z0-9_./:@+,~^-]*$/.test(e)){return'"'+escapeForShell(e,t)+'"'}return e}function sanitizeShellInput(e,t=false){const r=t?/[$`"';|&(){}[\]\\<>*?\n\r\t]/g:/[$`"';|&(){}[\]\\\n\r\t]/g;return e.replace(r,"")}async function extensionArray(e){switch(e){case"":case" ":return[];default:return[e.match(/(^|,\s?)none(\s?,|$)/)?"none":"",...e.split(",").map(function(e){e=e.trim().replace(/^\\\s*/,"");if(/.+-.+\/.+@.+/.test(e)){return e}return e.toLowerCase().replace(/^(:)?(php[-_]|none|zend )|(-[^-]*)-/,"$1$3")})].filter(Boolean)}}async function CSVArray(e){switch(e){case"":case" ":return[];default:return e.split(/,(?=(?:(?:[^"']*["']){2})*[^"']*$)/).map(function(e){return e.trim().replace(/^["']|["']$|(?<==)["']/g,"").replace(/=(((?!E_).)*[?{}|&~![()^]+((?!E_).)+)/,"='$1'").replace(/=(.*?)(=.*)/,"='$1$2'").replace(/:\s*["'](.*?)/g,":$1")}).filter(Boolean)}}async function getExtensionPrefix(e){switch(true){default:return"extension";case/xdebug([2-3])?$|opcache|ioncube|eaccelerator/.test(e):return"zend_extension"}}async function suppressOutput(e){switch(e){case"win32":return" >$null 2>&1";case"linux":case"darwin":return" >/dev/null 2>&1";default:return await log("Platform "+e+" is not supported",e,"error")}}async function getUnsupportedLog(e,t,r){return"\n"+await addLog("$cross",e,[e,"is not supported on PHP",t].join(" "),r)+"\n"}async function getCommand(e,t){switch(e){case"linux":case"darwin":return"add_"+t+" ";case"win32":return"Add-"+t.split("_").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("")+" ";default:return await log("Platform "+e+" is not supported",e,"error")}}async function joins(...e){return[...e].join(" ")}async function scriptExtension(e){switch(e){case"win32":return".ps1";case"linux":case"darwin":return".sh";default:return await log("Platform "+e+" is not supported",e,"error")}}async function scriptTool(e){switch(e){case"win32":return"pwsh ";case"linux":case"darwin":return"bash ";default:return await log("Platform "+e+" is not supported",e,"error")}}async function customPackage(e,t,r,n){const s=e.replace(/\d+|(pdo|pecl)[_-]|[_-]db2/,"");const i=await scriptExtension(n);const o=c.join(__dirname,"../src/scripts/"+t+"/"+s+i);const a=await getCommand(n,s);return"\n. "+o+"\n"+a+r}async function parseExtensionSource(e,t){const r=/(\w+)-(\w+:\/\/.{1,253}(?:[.:][^:/\s]{2,63})+\/)?([\w.-]+)\/([\w.-]+)@(.+)/;const n=r.exec(e);n[2]=n[2]?n[2].slice(0,-1):"https://github.com";return await joins("\nadd_extension_from_source",...n.splice(1,n.length),t)}const l=/^(latest|lowest|highest|nightly|master|pre|pre-installed|\d+\.x|\d+(\.\d+){0,2})$/;function validatePHPVersionInput(e,t){if(!l.test(e)){throw new Error(`Invalid PHP version in ${t}: ${e.slice(0,20)}`)}return e}async function readPHPVersion(){const e=await getInput("php-version",false);if(e){return validatePHPVersionInput(e,"php-version input")}const t=await getInput("php-version-file",false)||".php-version";if(a.default.existsSync(t)){const e=a.default.readFileSync(t,"utf8");const r=e.match(/^(?:php\s)?(\d+\.\d+\.\d+)$/m);return validatePHPVersionInput(r?r[1]:e.trim(),t)}else if(t!==".php-version"){throw new Error(`Could not find '${t}' file.`)}const r=await readEnv("COMPOSER_PROJECT_DIR");const n=c.join(r,"composer.lock");if(a.default.existsSync(n)){const e=JSON.parse(a.default.readFileSync(n,"utf8"));if(e["platform-overrides"]?.["php"]){return validatePHPVersionInput(e["platform-overrides"]["php"],"composer.lock platform-overrides.php")}}const s=c.join(r,"composer.json");if(a.default.existsSync(s)){const e=JSON.parse(a.default.readFileSync(s,"utf8"));if(e["config"]?.["platform"]?.["php"]){return validatePHPVersionInput(e["config"]["platform"]["php"],"composer.json config.platform.php")}}return"latest"}async function setVariable(e,t,r){switch(r){case"win32":return"\n$"+e+" = "+t+"\n";case"linux":case"darwin":default:return"\n"+e+'="$('+t+')"\n'}}},236:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var s=Object.getOwnPropertyDescriptor(t,r);if(!s||("get"in s?!t.__esModule:s.writable||s.configurable)){s={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,s)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var i=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),i=0;i{o+=u.write(e);if(l){l(e)}};const stdOutListener=e=>{i+=c.write(e);if(d){d(e)}};const f=Object.assign(Object.assign({},r===null||r===void 0?void 0:r.listeners),{stdout:stdOutListener,stderr:stdErrListener});const p=yield exec(e,t,Object.assign(Object.assign({},r),{listeners:f}));i+=c.end();o+=u.end();return{exitCode:p,stdout:i,stderr:o}})}},665:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var s=Object.getOwnPropertyDescriptor(t,r);if(!s||("get"in s?!t.__esModule:s.writable||s.configurable)){s={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,s)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var i=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),i=0;i-1){const e=n.substring(0,s);r(e);n=n.substring(s+a.EOL.length);s=n.indexOf(a.EOL)}return n}catch(e){this._debug(`error processing line. Failed with error ${e}`);return""}}_getSpawnFileName(){if(h){if(this._isCmdFile()){return process.env["COMSPEC"]||"cmd.exe"}}return this.toolPath}_getSpawnArgs(e){if(h){if(this._isCmdFile()){let t=`/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`;for(const r of this.args){t+=" ";t+=e.windowsVerbatimArguments?r:this._windowsQuoteCmdArg(r)}t+='"';return[t]}}return this.args}_endsWith(e,t){return e.endsWith(t)}_isCmdFile(){const e=this.toolPath.toUpperCase();return this._endsWith(e,".CMD")||this._endsWith(e,".BAT")}_windowsQuoteCmdArg(e){if(!this._isCmdFile()){return this._uvQuoteCmdArg(e)}if(!e){return'""'}const t=[" ","\t","&","(",")","[","]","{","}","^","=",";","!","'","+",",","`","~","|","<",">",'"'];let r=false;for(const n of e){if(t.some(e=>e===n)){r=true;break}}if(!r){return e}let n='"';let s=true;for(let t=e.length;t>0;t--){n+=e[t-1];if(s&&e[t-1]==="\\"){n+="\\"}else if(e[t-1]==='"'){s=true;n+='"'}else{s=false}}n+='"';return n.split("").reverse().join("")}_uvQuoteCmdArg(e){if(!e){return'""'}if(!e.includes(" ")&&!e.includes("\t")&&!e.includes('"')){return e}if(!e.includes('"')&&!e.includes("\\")){return`"${e}"`}let t='"';let r=true;for(let n=e.length;n>0;n--){t+=e[n-1];if(r&&e[n-1]==="\\"){t+="\\"}else if(e[n-1]==='"'){r=true;t+="\\"}else{r=false}}t+='"';return t.split("").reverse().join("")}_cloneExecOptions(e){e=e||{};const t={cwd:e.cwd||process.cwd(),env:e.env||process.env,silent:e.silent||false,windowsVerbatimArguments:e.windowsVerbatimArguments||false,failOnStdErr:e.failOnStdErr||false,ignoreReturnCode:e.ignoreReturnCode||false,delay:e.delay||1e4};t.outStream=e.outStream||process.stdout;t.errStream=e.errStream||process.stderr;return t}_getSpawnOptions(e,t){e=e||{};const r={};r.cwd=e.cwd;r.env=e.env;r["windowsVerbatimArguments"]=e.windowsVerbatimArguments||this._isCmdFile();if(e.windowsVerbatimArguments){r.argv0=`"${t}"`}return r}exec(){return o(this,void 0,void 0,function*(){if(!f.isRooted(this.toolPath)&&(this.toolPath.includes("/")||h&&this.toolPath.includes("\\"))){this.toolPath=d.resolve(process.cwd(),this.options.cwd||process.cwd(),this.toolPath)}this.toolPath=yield l.which(this.toolPath,true);return new Promise((e,t)=>o(this,void 0,void 0,function*(){this._debug(`exec tool: ${this.toolPath}`);this._debug("arguments:");for(const e of this.args){this._debug(` ${e}`)}const r=this._cloneExecOptions(this.options);if(!r.silent&&r.outStream){r.outStream.write(this._getCommandString(r)+a.EOL)}const n=new ExecState(r,this.toolPath);n.on("debug",e=>{this._debug(e)});if(this.options.cwd&&!(yield f.exists(this.options.cwd))){return t(new Error(`The cwd: ${this.options.cwd} does not exist!`))}const s=this._getSpawnFileName();const i=u.spawn(s,this._getSpawnArgs(r),this._getSpawnOptions(this.options,s));let o="";if(i.stdout){i.stdout.on("data",e=>{if(this.options.listeners&&this.options.listeners.stdout){this.options.listeners.stdout(e)}if(!r.silent&&r.outStream){r.outStream.write(e)}o=this._processLineBuffer(e,o,e=>{if(this.options.listeners&&this.options.listeners.stdline){this.options.listeners.stdline(e)}})})}let c="";if(i.stderr){i.stderr.on("data",e=>{n.processStderr=true;if(this.options.listeners&&this.options.listeners.stderr){this.options.listeners.stderr(e)}if(!r.silent&&r.errStream&&r.outStream){const t=r.failOnStdErr?r.errStream:r.outStream;t.write(e)}c=this._processLineBuffer(e,c,e=>{if(this.options.listeners&&this.options.listeners.errline){this.options.listeners.errline(e)}})})}i.on("error",e=>{n.processError=e.message;n.processExited=true;n.processClosed=true;n.CheckComplete()});i.on("exit",e=>{n.processExitCode=e;n.processExited=true;this._debug(`Exit code ${e} received from tool '${this.toolPath}'`);n.CheckComplete()});i.on("close",e=>{n.processExitCode=e;n.processExited=true;n.processClosed=true;this._debug(`STDIO streams have closed for tool '${this.toolPath}'`);n.CheckComplete()});n.on("done",(r,n)=>{if(o.length>0){this.emit("stdline",o)}if(c.length>0){this.emit("errline",c)}i.removeAllListeners();if(r){t(r)}else{e(n)}});if(this.options.input){if(!i.stdin){throw new Error("child process missing stdin")}i.stdin.end(this.options.input)}}))})}}t.ToolRunner=ToolRunner;function argStringToArray(e){const t=[];let r=false;let n=false;let s="";function append(e){if(n&&e!=='"'){s+="\\"}s+=e;n=false}for(let i=0;i0){t.push(s);s=""}continue}append(o)}if(s.length>0){t.push(s.trim())}return t}class ExecState extends c.EventEmitter{constructor(e,t){super();this.processClosed=false;this.processError="";this.processExitCode=0;this.processExited=false;this.processStderr=false;this.delay=1e4;this.done=false;this.timeout=null;if(!t){throw new Error("toolPath must not be empty")}this.options=e;this.toolPath=t;if(e.delay){this.delay=e.delay}}CheckComplete(){if(this.done){return}if(this.processClosed){this._setResult()}else if(this.processExited){this.timeout=(0,p.setTimeout)(ExecState.HandleTimeout,this.delay,this)}}_debug(e){this.emit("debug",e)}_setResult(){let e;if(this.processExited){if(this.processError){e=new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`)}else if(this.processExitCode!==0&&!this.options.ignoreReturnCode){e=new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`)}else if(this.processStderr&&this.options.failOnStdErr){e=new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`)}}if(this.timeout){clearTimeout(this.timeout);this.timeout=null}this.done=true;this.emit("done",e,this.processExitCode)}static HandleTimeout(e){if(e.done){return}if(!e.processClosed&&e.processExited){const t=`The STDIO streams did not close within ${e.delay/1e3} seconds of the exit event from process '${e.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`;e._debug(t)}e._setResult()}}},207:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var s=Object.getOwnPropertyDescriptor(t,r);if(!s||("get"in s?!t.__esModule:s.writable||s.configurable)){s={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,s)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var i=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),i=0;ie.toUpperCase()===t)){return e}}else{if(isUnixExecutable(n)){return e}}}const s=e;for(const i of r){e=s+i;n=undefined;try{n=yield(0,t.stat)(e)}catch(t){if(t.code!=="ENOENT"){console.log(`Unexpected error attempting to determine if executable file exists '${e}': ${t}`)}}if(n&&n.isFile()){if(t.IS_WINDOWS){try{const r=u.dirname(e);const n=u.basename(e).toUpperCase();for(const s of yield(0,t.readdir)(r)){if(n===s.toUpperCase()){e=u.join(r,s);break}}}catch(t){console.log(`Unexpected error attempting to determine the actual case of the file '${e}': ${t}`)}return e}else{if(isUnixExecutable(n)){return e}}}}return""})}function normalizeSeparators(e){e=e||"";if(t.IS_WINDOWS){e=e.replace(/\//g,"\\");return e.replace(/\\\\+/g,"\\")}return e.replace(/\/\/+/g,"/")}function isUnixExecutable(e){return(e.mode&1)>0||(e.mode&8)>0&&process.getgid!==undefined&&e.gid===process.getgid()||(e.mode&64)>0&&process.getuid!==undefined&&e.uid===process.getuid()}function getCmdPath(){var e;return(e=process.env["COMSPEC"])!==null&&e!==void 0?e:`cmd.exe`}},994:function(e,t,r){"use strict";var n=this&&this.__createBinding||(Object.create?function(e,t,r,n){if(n===undefined)n=r;var s=Object.getOwnPropertyDescriptor(t,r);if(!s||("get"in s?!t.__esModule:s.writable||s.configurable)){s={enumerable:true,get:function(){return t[r]}}}Object.defineProperty(e,n,s)}:function(e,t,r,n){if(n===undefined)n=r;e[n]=t[r]});var s=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:true,value:t})}:function(e,t){e["default"]=t});var i=this&&this.__importStar||function(){var ownKeys=function(e){ownKeys=Object.getOwnPropertyNames||function(e){var t=[];for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[t.length]=r;return t};return ownKeys(e)};return function(e){if(e&&e.__esModule)return e;var t={};if(e!=null)for(var r=ownKeys(e),i=0;i|]/.test(e)){throw new Error('File path must not contain `*`, `"`, `<`, `>` or `|` on Windows')}}try{yield u.rm(e,{force:true,maxRetries:3,recursive:true,retryDelay:300})}catch(e){throw new Error(`File was unable to be removed ${e}`)}})}function mkdirP(e){return o(this,void 0,void 0,function*(){(0,a.ok)(e,"a path argument must be provided");yield u.mkdir(e,{recursive:true})})}function which(e,t){return o(this,void 0,void 0,function*(){if(!e){throw new Error("parameter 'tool' is required")}if(t){const t=yield which(e,false);if(!t){if(u.IS_WINDOWS){throw new Error(`Unable to locate executable file: ${e}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`)}else{throw new Error(`Unable to locate executable file: ${e}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`)}}return t}const r=yield findInPath(e);if(r&&r.length>0){return r[0]}return""})}function findInPath(e){return o(this,void 0,void 0,function*(){if(!e){throw new Error("parameter 'tool' is required")}const t=[];if(u.IS_WINDOWS&&process.env["PATHEXT"]){for(const e of process.env["PATHEXT"].split(c.delimiter)){if(e){t.push(e)}}}if(u.isRooted(e)){const r=yield u.tryGetExecutablePath(e,t);if(r){return[r]}return[]}if(e.includes(c.sep)){return[]}const r=[];if(process.env.PATH){for(const e of process.env.PATH.split(c.delimiter)){if(e){r.push(e)}}}const n=[];for(const s of r){const r=yield u.tryGetExecutablePath(c.join(s,e),t);if(r){n.push(r)}}return n})}function readCopyOptions(e){const t=e.force==null?true:e.force;const r=Boolean(e.recursive);const n=e.copySourceDirectory==null?true:Boolean(e.copySourceDirectory);return{force:t,recursive:r,copySourceDirectory:n}}function cpDirRecursive(e,t,r,n){return o(this,void 0,void 0,function*(){if(r>=255)return;r++;yield mkdirP(t);const s=yield u.readdir(e);for(const i of s){const s=`${e}/${i}`;const o=`${t}/${i}`;const a=yield u.lstat(s);if(a.isDirectory()){yield cpDirRecursive(s,o,r,n)}else{yield copyFile(s,o,n)}}yield u.chmod(t,(yield u.stat(e)).mode)})}function copyFile(e,t,r){return o(this,void 0,void 0,function*(){if((yield u.lstat(e)).isSymbolicLink()){try{yield u.lstat(t);yield u.unlink(t)}catch(e){if(e.code==="EPERM"){yield u.chmod(t,"0666");yield u.unlink(t)}}const r=yield u.readlink(e);yield u.symlink(r,t,u.IS_WINDOWS?"junction":null)}else if(!(yield u.exists(t))||r){yield u.copyFile(e,t)}})}},26:function(e,t){(function(e,r){true?r(t):0})(this,function(e){"use strict";const t=/^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;const validateAndParse=e=>{if(typeof e!=="string"){throw new TypeError("Invalid argument expected string")}const r=e.match(t);if(!r){throw new Error(`Invalid argument not valid semver ('${e}' received)`)}r.shift();return r};const isWildcard=e=>e==="*"||e==="x"||e==="X";const tryParse=e=>{const t=parseInt(e,10);return isNaN(t)?e:t};const forceType=(e,t)=>typeof e!==typeof t?[String(e),String(t)]:[e,t];const compareStrings=(e,t)=>{if(isWildcard(e)||isWildcard(t))return 0;const[r,n]=forceType(tryParse(e),tryParse(t));if(r>n)return 1;if(r{for(let r=0;r{const r=validateAndParse(e);const n=validateAndParse(t);const s=r.pop();const i=n.pop();const o=compareSegments(r,n);if(o!==0)return o;if(s&&i){return compareSegments(s.split("."),i.split("."))}else if(s||i){return s?-1:1}return 0};const compare=(e,t,n)=>{assertValidOperator(n);const s=compareVersions(e,t);return r[n].includes(s)};const r={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1],"!=":[-1,1]};const n=Object.keys(r);const assertValidOperator=e=>{if(typeof e!=="string"){throw new TypeError(`Invalid operator type, expected string but got ${typeof e}`)}if(n.indexOf(e)===-1){throw new Error(`Invalid operator, expected one of ${n.join("|")}`)}};const satisfies=(e,t)=>{t=t.replace(/([><=]+)\s+/g,"$1");if(t.includes("||")){return t.split("||").some(t=>satisfies(e,t))}else if(t.includes(" - ")){const[r,n]=t.split(" - ",2);return satisfies(e,`>=${r} <=${n}`)}else if(t.includes(" ")){return t.trim().replace(/\s{2,}/g," ").split(" ").every(t=>satisfies(e,t))}const r=t.match(/^([<>=~^]+)/);const n=r?r[1]:"=";if(n!=="^"&&n!=="~")return compare(e,t,n);const[s,i,o,,a]=validateAndParse(e);const[c,u,d,,l]=validateAndParse(t);const f=[s,i,o];const p=[c,u!==null&&u!==void 0?u:"x",d!==null&&d!==void 0?d:"x"];if(l){if(!a)return false;if(compareSegments(f,p)!==0)return false;if(compareSegments(a.split("."),l.split("."))===-1)return false}const h=p.findIndex(e=>e!=="0")+1;const g=n==="~"?2:h>1?h:1;if(compareSegments(f.slice(0,g),p.slice(0,g))!==0)return false;if(compareSegments(f.slice(g),p.slice(g))===-1)return false;return true};const validate=e=>typeof e==="string"&&/^[v\d]/.test(e)&&t.test(e);const validateStrict=e=>typeof e==="string"&&/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/.test(e);e.compare=compare;e.compareVersions=compareVersions;e.satisfies=satisfies;e.validate=validate;e.validateStrict=validateStrict})},613:e=>{"use strict";e.exports=require("assert")},317:e=>{"use strict";e.exports=require("child_process")},434:e=>{"use strict";e.exports=require("events")},896:e=>{"use strict";e.exports=require("fs")},857:e=>{"use strict";e.exports=require("os")},928:e=>{"use strict";e.exports=require("path")},193:e=>{"use strict";e.exports=require("string_decoder")},557:e=>{"use strict";e.exports=require("timers")}};var t={};function __nccwpck_require__(r){var n=t[r];if(n!==undefined){return n.exports}var s=t[r]={exports:{}};var i=true;try{e[r].call(s.exports,s,s.exports,__nccwpck_require__);i=false}finally{if(i)delete t[r]}return s.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var r=__nccwpck_require__(755);module.exports=r})(); \ No newline at end of file diff --git a/src/scripts/tools/add_tools.ps1 b/src/scripts/tools/add_tools.ps1 index 918e5928..c2ede830 100644 --- a/src/scripts/tools/add_tools.ps1 +++ b/src/scripts/tools/add_tools.ps1 @@ -229,8 +229,18 @@ Function Add-Tool() { [Parameter(Position = 2, Mandatory = $false)] $ver_param, [Parameter(Position = 3, Mandatory = $false)] - $skip_composer_github_auth + $skip_composer_github_auth, + [Parameter(Position = 4, Mandatory = $false)] + $checksum ) + $checksum_regex = '^sha(256|512):[0-9a-fA-F]+$' + if("$ver_param" -match $checksum_regex) { + $checksum = $ver_param + $ver_param = $null + } elseif("$skip_composer_github_auth" -match $checksum_regex) { + $checksum = $skip_composer_github_auth + $skip_composer_github_auth = $null + } if($tool -eq "composer") { $script:skip_composer_github_auth = $skip_composer_github_auth -eq 'true' } @@ -277,6 +287,19 @@ Function Add-Tool() { Remove-Item $backup_path -Force -ErrorAction SilentlyContinue } + if($checksum -and ($status_code -eq 200) -and (Test-Path $tool_path)) { + $checksum_parts = $checksum -split ':' + $actual_checksum = (Get-FileHash -Path $tool_path -Algorithm $checksum_parts[0]).Hash + if($actual_checksum -ne $checksum_parts[1]) { + Remove-Item @($tool_path, $cache_path) -Force -ErrorAction SilentlyContinue + if($tool -eq "composer") { + $env:fail_fast = 'true' + } + Add-Log $cross $tool "Checksum verification failed for $tool" + return + } + } + $escaped_tool = [regex]::Escape($tool) if (((Get-ChildItem -Path $bin_dir/* | Where-Object Name -Match "^$escaped_tool(\.exe|\.phar)?$").Count -gt 0)) { $bat_content = @() diff --git a/src/scripts/tools/add_tools.sh b/src/scripts/tools/add_tools.sh index d8deb299..d3189747 100644 --- a/src/scripts/tools/add_tools.sh +++ b/src/scripts/tools/add_tools.sh @@ -201,8 +201,15 @@ add_tool() { url=$1 tool=$2 ver_param=$3 + checksum= + local arg + for arg in "$@"; do + [[ "$arg" =~ ^sha(256|512):[0-9a-fA-F]+$ ]] && checksum="$arg" + done + [[ "$ver_param" =~ ^sha(256|512): ]] && ver_param= if [ "$tool" = "composer" ]; then skip_composer_github_auth="${4:-false}" + [[ "$skip_composer_github_auth" =~ ^sha(256|512): ]] && skip_composer_github_auth=false fi tool_path="$tool_path_dir/$tool" if ! [ -d "$tool_path_dir" ]; then @@ -235,6 +242,10 @@ add_tool() { fi sudo rm -f "$tool_path.bak" fi + if [ "$status_code" = "200" ] && [ -n "$checksum" ] && ! verify_checksum "$tool_path" "$checksum"; then + sudo rm -f "$tool_path" "$cache_path" + status_code="checksum_mismatch" + fi if [ "$status_code" = "200" ]; then add_tools_helper "$tool" tool_version=$(get_tool_version "$tool" "$ver_param") @@ -244,7 +255,9 @@ add_tool() { if [ "$tool" = "composer" ]; then export fail_fast=true fi - if [ "$status_code" = "404" ]; then + if [ "$status_code" = "checksum_mismatch" ]; then + add_log "$cross" "$tool" "Checksum verification failed for $tool" + elif [ "$status_code" = "404" ]; then add_log "$cross" "$tool" "Failed to download $tool from ${url[*]}" else add_log "$cross" "$tool" "Could not setup $tool" diff --git a/src/scripts/unix.sh b/src/scripts/unix.sh index f0f45fea..86df3777 100644 --- a/src/scripts/unix.sh +++ b/src/scripts/unix.sh @@ -122,6 +122,24 @@ get_sha256() { fi } +# Function to verify the checksum of a file. +# checksum format: sha256: or sha512: +verify_checksum() { + local file_path=$1 + local checksum=$2 + local algo="${checksum%%:*}" + local expected="${checksum#*:}" + local actual= + if command -v "${algo}sum" >/dev/null; then + actual="$(sudo "${algo}sum" "$file_path" | cut -d' ' -f1)" + elif command -v shasum >/dev/null; then + actual="$(sudo shasum -a "${algo#sha}" "$file_path" | cut -d' ' -f1)" + elif command -v openssl >/dev/null; then + actual="$(sudo openssl dgst -"$algo" "$file_path" | awk '{print $NF}')" + fi + [ -n "$actual" ] && [ "$(echo "$actual" | tr '[:upper:]' '[:lower:]')" = "$(echo "$expected" | tr '[:upper:]' '[:lower:]')" ] +} + # Function to download a file using cURL. # mode: -s pipe to stdout, -v save file and return status code # execute: -e save file as executable diff --git a/src/tools.ts b/src/tools.ts index 443668a5..4685e6dd 100644 --- a/src/tools.ts +++ b/src/tools.ts @@ -27,6 +27,7 @@ type ToolFunction = export interface ToolData { tool: string; version: string; + checksum?: string; os: string; php_version: string; github: string; @@ -73,6 +74,38 @@ interface ToolConfig { packagist?: string; } +/** + * Regex to match a checksum suffix in a tool release - tool:version@sha256: + */ +const checksum_suffix_regex = /@(sha256|sha512):([^@]*)$/; + +/** + * Function to parse the checksum suffix in the tool release + * + * @param release + */ +export function extractChecksum(release: string): { + release: string; + checksum?: string; + error?: string; +} { + const matches = release.match(checksum_suffix_regex); + if (!matches) { + return {release}; + } + release = release.slice(0, -matches[0].length); + const algo = matches[1]; + const hash = matches[2].toLowerCase(); + const hash_length = algo === 'sha256' ? 64 : 128; + if (!new RegExp(`^[a-f0-9]{${hash_length}}$`).test(hash)) { + return { + release, + error: `Invalid ${algo} checksum, expected ${hash_length} hexadecimal characters` + }; + } + return {release, checksum: `${algo}:${hash}`}; +} + /** * GitHub reference object from API response */ @@ -260,7 +293,9 @@ export async function filterList(tools_list: string[]): Promise { const regex_any = /^composer($|:.*)/; const regex_valid = /^composer:?($|preview$|snapshot$|v?\d+(\.\d+)?$|v?\d+\.\d+\.\d+[\w-]*$)/; - const matches: string[] = tools_list.filter(tool => regex_valid.test(tool)); + const matches: string[] = tools_list.filter(tool => + regex_valid.test(tool.replace(checksum_suffix_regex, '')) + ); let composer = 'composer'; tools_list = tools_list.filter(tool => !regex_any.test(tool)); switch (true) { @@ -335,7 +370,8 @@ export async function getPharUrl(data: ToolData): Promise { export async function addArchive(data: ToolData): Promise { return ( (await utils.getCommand(data.os, 'tool')) + - (await utils.joins(data.url, data.tool, data.version_parameter)) + (await utils.joins(data.url, data.tool, data.version_parameter)) + + (data.checksum ? ' ' + data.checksum : '') ); } @@ -612,6 +648,8 @@ export async function getData( const json_file: string = fs.readFileSync(json_file_path, 'utf8'); const json_objects: Record = JSON.parse(json_file); release = release.replace(/\s+/g, ''); + const checksum_data = extractChecksum(release); + release = checksum_data.release; const parts: string[] = release.split(':'); const tool = parts[0]; const version = parts[1]; @@ -663,6 +701,8 @@ export async function getData( function: config.function, alias: config.alias }; + data.checksum = checksum_data.checksum; + data.error = checksum_data.error; data.release = await getRelease(release, data); data.version = version ? await getVersion(version, data) @@ -688,6 +728,25 @@ export const functionRecord: Record< wp_cli: addWPCLI }; +/** + * Function to check if a tool supports checksum verification + * + * Only tools downloaded as archives via add_tool support it, so composer + * packages and tools set up using custom package scripts do not. + * + * @param data + */ +export async function supportsChecksum(data: ToolData): Promise { + switch (data.type) { + case 'phar': + return true; + case 'custom-function': + return !['pecl', 'dev_tools'].includes(data.function ?? ''); + default: + return false; + } +} + /** * Setup tools * @@ -714,6 +773,14 @@ export async function addTools( case data.error !== undefined: script += await utils.addLog('$cross', data.tool, data.error, data.os); break; + case data.checksum !== undefined && !(await supportsChecksum(data)): + script += await utils.addLog( + '$cross', + data.tool, + 'Checksum verification is not supported for ' + data.tool, + data.os + ); + break; case 'phar' === data.type: script += await addArchive(data); break;