From: Vincent Vanwaelscappel Date: Wed, 19 Apr 2023 09:00:40 +0000 (+0200) Subject: wait #5867 @8 X-Git-Url: http://git.cubedesigners.com/?a=commitdiff_plain;h=0ce4446cfcdf97995cadd385cca8a0b75e95d858;p=fluidbook-toolbox.git wait #5867 @8 --- diff --git a/.docker/images/php/Dockerfile b/.docker/images/php/Dockerfile index 7f676742e..85aa13198 100644 --- a/.docker/images/php/Dockerfile +++ b/.docker/images/php/Dockerfile @@ -88,7 +88,7 @@ RUN curl -L https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -o RUN apt clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true -RUN npm install --unsafe-perm --global uglify-js less sass puppeteer favicons crx3 oslllo-svg-fixer terser nw-builder@^4 +RUN npm install --unsafe-perm --global uglify-js less sass puppeteer favicons crx3 oslllo-svg-fixer terser RUN pip3 install font-line RUN groupadd sudo;useradd -d /application -g 33 -G sudo -s /bin/bash -u 1001 toolbox @@ -96,7 +96,6 @@ RUN groupadd sudo;useradd -d /application -g 33 -G sudo -s /bin/bash -u 1001 too # PHP-FPM packages need a nudge to make them docker-friendly COPY overrides.conf /etc/php/8.1/fpm/pool.d/z-overrides.conf -#CMD ["/usr/sbin/php-fpm8.1", "-O" ] COPY startup /usr/bin/startup CMD exec /usr/bin/startup diff --git a/app/Console/Commands/UpdateNWJS.php b/app/Console/Commands/UpdateNWJS.php new file mode 100644 index 000000000..d193e0357 --- /dev/null +++ b/app/Console/Commands/UpdateNWJS.php @@ -0,0 +1,60 @@ +_update('win', 'x64'); + $this->_update('osx', 'x64'); + } + + protected function _update($platform, $arch = 'x64') + { + // Get NWJS + $path = Files::mkdir(resource_path('nwjs/' . $platform . '/' . $arch)); + $tmp = Files::tempnam() . '.zip'; + $tmpDir = Files::tmpdir(); + copy('https://dl.nwjs.io/v' . self::VERSION . '/nwjs-v' . self::VERSION . '-' . $platform . '-' . $arch . '.zip', $tmp); + Zip::extract($tmp, $tmpDir); + if ($platform === 'osx') { + $todelete = ['credits.html']; + } else { + $todelete = ['credits.html']; + } + $nwjs = $tmpDir . '/nwjs-v' . self::VERSION . '-' . $platform . '-' . $arch; + foreach ($todelete as $item) { + `rm -rf $nwjs/$item`; + } + $mv = 'rsync -av --delete ' . $nwjs . '/ ' . Files::mkdir($path); + `$mv`; + unlink($tmp); + + // Get FFMPEG + $destLib = Files::mkdir(resource_path('fluidbookpublication/packager/_ffmpeg')); + $tmp = Files::tempnam() . '.zip'; + $tmpDir = Files::tmpdir(); + copy('https://github.com/nwjs-ffmpeg-prebuilt/nwjs-ffmpeg-prebuilt/releases/download/' . self::FFMPEG_VERSION . '/' . self::FFMPEG_VERSION . '-' . $platform . '-' . $arch . '.zip', $tmp); + Zip::extract($tmp, $tmpDir); + if ($platform === 'win') { + $src = 'ffmpeg.dll'; + $dest = $platform . '-' . $arch . '.dll'; + } else { + $src = $dest = 'libffmpeg.dylib'; + } + copy($tmpDir . '/' . $src, $destLib . $dest); + + + } +} diff --git a/app/Fluidbook/Packager/MacOS.php b/app/Fluidbook/Packager/MacOS.php index e5f49680a..e91603266 100644 --- a/app/Fluidbook/Packager/MacOS.php +++ b/app/Fluidbook/Packager/MacOS.php @@ -2,14 +2,16 @@ namespace App\Fluidbook\Packager; +use CFPropertyList\CFPropertyList; +use Cubist\Net\SSH2; use Cubist\Util\CommandLine; +use Cubist\Util\Files\Files; +use Cubist\Util\Zip; class MacOS extends WindowsZIP { protected $nwplatform = 'osx'; protected $arch = 'x64'; - protected $nwversion = '0.72.0'; - protected $node_platform = 'mac'; protected $exenameMaxlength = 28; public $type = 'mac_exe_html'; protected $packageIconExt = 'icns'; @@ -18,20 +20,8 @@ class MacOS extends WindowsZIP public function makePackage($zip) { $this->preparePackage(); - $toDelete = ['chromedriver', 'credits.html', 'minidump_stackwalk', 'nwjc', 'payload', 'v8_context_snapshot.bin', 'natives_blob.bin', 'libffmpeg.dylib']; - foreach ($toDelete as $item) { - $p = $this->getFinalPackageDir() . '/' . $item; - `rm -rf "$p"`; - } - if ($zip) { - $res = $this->zip(null); - } else { - $res = $this->getFinalPackageDir(); - } $this->postPackage(); - $this->setFinalURL(null); - $this->setFinalPath($res); - return $res; + return $this->getFinalPath(); } public function getAppPath() @@ -52,10 +42,57 @@ class MacOS extends WindowsZIP return parent::getFinalPackageDir(); } + protected function _nwbuilder4() + { + $base = Files::mkdir(resource_path('nwjs/' . $this->nwplatform . '/' . $this->arch)); + $rsyncBase = "rsync -av --exclude nwjs.app/Contents/Resources/app.nw --delete $base $this->buildPath"; + `$rsyncBase`; + $package = Files::mkdir($this->buildPath . '/nwjs.app/Contents/Resources/app.nw'); + $rsyncFiles = "rsync -av --delete $this->vdir $package"; + `$rsyncFiles`; + rename($this->buildPath . 'nwjs.app', $this->getAppPath()); + + $f = $this->getAppPath() . '/Contents/Info.plist'; + file_put_contents($f, preg_replace('/\nwjs\<\/string\>/', '' . htmlentities($this->exeName) . '', file_get_contents($f), 1)); + } public function signExe() { - $this->signApp(); + + $appPath = $this->getAppPath(); + + //$ssh = new SSH2('paris.cubedesigners.com', 'vincent', 'atacama', 22022); + //$local_root = '/Users/vincent/Sign/'; + $ssh = new SSH2('paris.cubedesigners.com', 'macossign', 'rntj55bw', 22622); + $local_root = '/Users/macossign/Documents/Sign/'; + + // Zip app + Zip::archive($appPath . '/..', $appPath . ".zip", 1); + $signScripts = resource_path('macossign'); + // Copy zipped app and signing scripts to the remote mac server + $ssh->send($signScripts . '/toolbox/docodesign3', $local_root . 'docodesign3', 755); + $ssh->send($signScripts . '/toolbox/sign3', $local_root . 'sign3', 755); + $ssh->send($signScripts . '/toolbox/neededToRun3.entitlements', $local_root . 'neededToRun3.entitlements', 755); + $ssh->send($signScripts . '/workshop/docodesign', $local_root . 'docodesign', 755); + $ssh->send($signScripts . '/workshop/sign', $local_root . 'sign', 755); + $ssh->send($signScripts . '/workshop/neededToRun.entitlements', $local_root . 'neededToRun.entitlements', 755); + $ssh->send($appPath . ".zip", $local_root . $this->exeName . '.app.zip', 644); + + // Sign app + $cl = new CommandLine($local_root . 'sign3'); + $cl->setArg(null, $this->exeName); + $cl->execute($ssh); + $cl->debug(); + $res = $cl->output; + + $finalPath = $this->getPathBase('zip'); + // Copy back signed + $ssh->recv($local_root . '/' . $this->exeName . '.app.zip', $finalPath); + $this->setFinalPath($finalPath); + $this->setFinalURL($this->getDownloadURL('zip')); + + //`rm -rf $path`; + return $res; } public function setIcon() @@ -69,46 +106,5 @@ class MacOS extends WindowsZIP copy($this->resource_path('_ffmpeg/libffmpeg.dylib'), $this->getAppPath() . '/Contents/Frameworks/nwjs Framework.framework/Versions/Current/libffmpeg.dylib'); } - protected function signApp() - { - self::_signApp($this->getAppPath()); - } - - public static function _signApp($appPath, $back = true) - { - $local_root = '/Users/vincent/Sign/'; - $dist_root = '/mnt/sshfs/macparis' . $local_root; - $f = 'tmp_' . md5(rand(0, 1000000)) . ".app"; - $path = $dist_root . $f; - - // Copy app to mac - $cp = new CommandLine('cp'); - $cp->setArg('r'); - $cp->setArg(null, $appPath); - $cp->setArg(null, $path); - $cp->execute(); - - // Sign app - $cl = new CommandLine($local_root . 'sign'); - $cl->setSSH('paris.cubedesigners.com', 'vincent', 'atacama', 22022); - $cl->setArg(null, $local_root . $f); - $cl->execute(); - $res = $cl->output; - - if ($back) { - // Copy back signed - $cp = new CommandLine('rsync'); - $cp->setArg('r'); - $cp->setArg('l'); - $cp->setArg('p'); - $cp->setArg('D'); - $cp->setArg('v'); - $cp->setArg(null, $path . '/'); - $cp->setArg(null, $appPath . '/'); - $cp->execute(); - } - //`rm -rf $path`; - return $res; - } } diff --git a/app/Fluidbook/Packager/WindowsZIP.php b/app/Fluidbook/Packager/WindowsZIP.php index 8461481d1..bb40508a1 100644 --- a/app/Fluidbook/Packager/WindowsZIP.php +++ b/app/Fluidbook/Packager/WindowsZIP.php @@ -14,13 +14,13 @@ class WindowsZIP extends Packager protected $buildPath; protected $nwplatform = 'win'; protected $arch = 'x64'; - protected $nwversion = '0.72.0'; + protected $nwversion = 'stable'; protected $appversion = ''; protected $node_platform = 'win'; protected $exenameMaxlength = 30; protected $_compileOnConstruct = true; protected $packageIconExt = 'ico'; - protected $nwbuildVersion = '4.0.8'; + protected $nwbuildVersion = '4.2.0'; protected $nwCacheDir; protected $_ext = 'html'; @@ -79,7 +79,7 @@ class WindowsZIP extends Packager { $this->buildPath = Files::mkdir($this->packager_path('/nwbuild/' . $this->type . '/' . $this->book_id)); $this->makeJSON(); - `umask 0000;sudo rm -rf $this->buildPath;mkdir -p 0777 $this->buildPath;chmod -R 777 $this->vdir;mkdir -p 0777 /application/tmp;chmod -R 777 /application/tmp`; + //`umask 0000;sudo rm -rf $this->buildPath;mkdir -p 0777 $this->buildPath;chmod -R 777 $this->vdir;mkdir -p 0777 /application/tmp;chmod -R 777 /application/tmp`; $cl = $this->_nwbuilder4(); @@ -98,22 +98,19 @@ class WindowsZIP extends Packager return file_exists($this->buildPath); } + /** * @return CommandLine */ protected function _nwbuilder4() { - $cl = new CommandLine('nwbuild'); - $cl->cd($this->vdir); - $cl->setArg(null, 'package.json *'); - $cl->setArg('platform', $this->nwplatform); - $cl->setArg('outDir', $this->buildPath); - $cl->setArg('flavour', "normal"); - $cl->setArg('version', $this->nwversion); - $cl->setArg('arch', $this->arch); - $cl->execute(); - $cl->debug(); - return $cl; + $base = Files::mkdir(resource_path('nwjs/' . $this->nwplatform . '/' . $this->arch)); + $rsyncBase = "rsync -av --exclude package.nw --delete $base $this->buildPath"; + `$rsyncBase`; + $package = Files::mkdir($this->buildPath . '/package.nw'); + $rsyncFiles = "rsync -av --delete $this->vdir $package"; + `$rsyncFiles`; + rename($this->buildPath . 'nw.exe', $this->buildPath . $this->exeName . '.exe'); } protected function getNWBuilder3Platform() @@ -149,7 +146,7 @@ class WindowsZIP extends Packager } $cli = new CommandLine('C:/Program Files (x86)/Windows Kits/10/bin/10.0.18362.0/x64/signtool.exe'); - $cli->setManualArg("sign /f C:/Users/vince/Documents/Cubedesigners.cer /csp \"eToken Base Cryptographic Provider\" /k \"[SafeNet Token JC 0{{TYWjZacq%hAH98}}]=54C3F1B91759268A\" /tr http://timestamp.sectigo.com /td sha256 /fd sha256 /a $remote"); + $cli->setManualArg("sign /f C:/Users/vince/OneDrive/Documents/Cubedesigners.cer /csp \"eToken Base Cryptographic Provider\" /k \"[SafeNet Token JC 0{{TYWjZacq%hAH98}}]=54C3F1B91759268A\" /tr http://timestamp.sectigo.com /td sha256 /fd sha256 /a $remote"); $cli->execute($ssh); if (!stristr($cli->getOutput(), 'Successfully signed')) { $ssh->unlink($remote); @@ -197,15 +194,6 @@ class WindowsZIP extends Packager 'icon' => 'icon.png', ], 'app' => $app, - 'nwbuild' => [ - 'platform' => $this->nwplatform, - 'outDir' => $this->buildPath, - 'cacheDir' => $this->nwCacheDir, - 'flavour' => 'normal', - 'version' => $this->nwversion, - 'arch' => $this->arch, - 'app' => $app, - ], 'dependencies' => [ 'child_process' => "^1.0.2", @@ -223,7 +211,6 @@ class WindowsZIP extends Packager foreach (['png', 'ico', 'icns'] as $format) { $this->copy($this->theme->getFaviconPath($format), $this->vdir . '/icon.' . $format); } - file_put_contents($this->vdir . '/package.json', json_encode($data)); } diff --git a/resources/macossign/toolbox/docodesign3 b/resources/macossign/toolbox/docodesign3 new file mode 100644 index 000000000..5cf89ece4 --- /dev/null +++ b/resources/macossign/toolbox/docodesign3 @@ -0,0 +1,82 @@ +#!/usr/local/bin/node + +const APP = process.argv[2]; +const IDENTITY = process.argv[3]; + +/****************************************************************************/ + +console.log("### finding things to sign"); + +const fs = require('fs'); +const child_process = require('child_process'); + +const items = []; + +const frameworksDir = `${APP}/Contents/Frameworks/nwjs Framework.framework`; + +let currentVersionDir; +for (const dir of fs.readdirSync(`${frameworksDir}/Versions`)) { + if (fs.statSync(`${frameworksDir}/Versions/${dir}`).isDirectory) { + currentVersionDir = `${frameworksDir}/Versions/${dir}`; + break; + } +} +if (!currentVersionDir) { + console.error(`couldn't find "${frameworksDir}/Versions/[version]"`); + process.exit(1); +} +for (const file of fs.readdirSync(`${currentVersionDir}`)) { + if (file.endsWith('.dylib')) { + items.push(`${currentVersionDir}/${file}`); + } +} +for (const file of fs.readdirSync(`${currentVersionDir}/Helpers`)) { + if (/^[a-z0-9_]*$/.test(file) || file.endsWith('.app')) { + items.push(`${currentVersionDir}/Helpers/${file}`); + } +} + +for (const file of fs.readdirSync(`${currentVersionDir}/Libraries`)) { + if (file.endsWith('.dylib')) { + items.push(`${currentVersionDir}/Libraries/${file}`); + } +} + +for (const file of fs.readdirSync(`${APP}/Contents/Library/LaunchServices`)) { + items.push(`${APP}/Contents/Library/LaunchServices/${file}`); +} + +//for (const file of fs.readdirSync(`${currentVersionDir}/XPCServices`)) { +// if (file.endsWith('.xpc')) { +// items.push(`${currentVersionDir}/XPCServices/${file}`); +// } +// +items.push(frameworksDir); + +/****************************************************************************/ + +console.log(""); +console.log("### signing"); + +function exec(cmd) { + console.log(cmd); + const result = child_process.spawnSync(cmd, {shell: true, stdio: 'inherit'}); + if (result.status !== 0) { + console.log(`Command failed with status ${result.status}`); + if (result.error) console.log(result.error); + process.exit(1); + } +} + +for (const item of items) { + exec(`codesign --verbose --force --deep --strict --options runtime --timestamp --sign "${IDENTITY}" --entitlements ./neededToRun3.entitlements "${item}"`); +} + +exec(`codesign --verbose --force --deep --strict --options runtime --timestamp --sign "${IDENTITY}" --entitlements ./neededToRun3.entitlements "${APP}"`); + +/****************************************************************************/ + +console.log(""); +console.log("### verifying signature"); + +exec(`codesign --verify -vvvv "${APP}"`); diff --git a/resources/macossign/toolbox/neededToRun3.entitlements b/resources/macossign/toolbox/neededToRun3.entitlements new file mode 100644 index 000000000..b91ddfaa3 --- /dev/null +++ b/resources/macossign/toolbox/neededToRun3.entitlements @@ -0,0 +1,18 @@ + + + + + com.apple.security.automation.apple-events + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-executable-page-protection + + com.apple.security.cs.disable-library-validation + + + \ No newline at end of file diff --git a/resources/macossign/toolbox/sign3 b/resources/macossign/toolbox/sign3 new file mode 100644 index 000000000..fef6dba50 --- /dev/null +++ b/resources/macossign/toolbox/sign3 @@ -0,0 +1,22 @@ +#!/bin/sh +cd /Users/macossign/Documents/Sign +printf "Unlock keychain\n----\n\n" +security unlock-keychain -p "rntj55bw" /Users/macossign/Library/Keychains/Apple.keychain-db +printf "Unzip app file\n----\n\n" +rm -rf "$1.app" +unzip "$1.app.zip" +rm -f "$1.app.zip" +printf "Sign the app\n----\n\n" +./docodesign3 "$1.app" "Developer ID Application: Cubedesigners (82TNE4UQ7A)" +printf "Zip the app in order to be notarized\n----\n\n" +ditto -c -k --sequesterRsrc --keepParent "$1.app" "$1.app.zip" +printf "Notarize app and wait for confirmation\n----\n\n" +xcrun notarytool submit --wait --apple-id "contact@cubedesigners.com" --team-id "82TNE4UQ7A" --password "tqwj-saik-dtdl-yrpc" "$1.app.zip" +printf "Staple the app\n----\n\n" +xcrun stapler staple "$1.app" +printf "Rezip the app\n----\n\n" +rm -f "$1.app.zip" +ditto -c -k --sequesterRsrc --keepParent "$1.app" "$1.app.zip" +printf "Remove the app (keep only zip)\n----\n\n" +rm -rf "$1.app" +chmod 777 "$1.app.zip" diff --git a/resources/macossign/workshop/docodesign b/resources/macossign/workshop/docodesign new file mode 100644 index 000000000..9d12873e6 --- /dev/null +++ b/resources/macossign/workshop/docodesign @@ -0,0 +1,76 @@ +#!/usr/bin/env node + +const APP = process.argv[2]; +const IDENTITY = process.argv[3]; + +/****************************************************************************/ + +console.log("### finding things to sign"); + +const fs = require('fs'); +const child_process = require('child_process'); + +const items = []; + +const frameworksDir = `${APP}/Contents/Frameworks/nwjs Framework.framework`; + +let currentVersionDir; +for (const dir of fs.readdirSync(`${frameworksDir}/Versions`)) { + if (fs.statSync(`${frameworksDir}/Versions/${dir}`).isDirectory) { + currentVersionDir = `${frameworksDir}/Versions/${dir}`; + break; + } +} +if (!currentVersionDir) { + console.error(`couldn't find "${frameworksDir}/Versions/[version]"`); + process.exit(1); +} +for (const file of fs.readdirSync(`${currentVersionDir}`)) { + if (file.endsWith('.dylib')) { + items.push(`${currentVersionDir}/${file}`); + } +} +for (const file of fs.readdirSync(`${currentVersionDir}/Helpers`)) { + if (/^[a-z0-9_]*$/.test(file) || file.endsWith('.app')) { + items.push(`${currentVersionDir}/Helpers/${file}`); + } +} +for (const file of fs.readdirSync(`${currentVersionDir}/Libraries`)) { + if (file.endsWith('.dylib')) { + items.push(`${currentVersionDir}/Libraries/${file}`); + } +} +for (const file of fs.readdirSync(`${currentVersionDir}/XPCServices`)) { + if (file.endsWith('.xpc')) { + items.push(`${currentVersionDir}/XPCServices/${file}`); + } +} +items.push(frameworksDir); + +/****************************************************************************/ + +console.log(""); +console.log("### signing"); + +function exec(cmd) { + console.log(cmd); + const result = child_process.spawnSync(cmd, {shell: true, stdio: 'inherit'}); + if (result.status !== 0) { + console.log(`Command failed with status ${result.status}`); + if (result.error) console.log(result.error); + process.exit(1); + } +} + +for (const item of items) { + exec(`codesign --verbose --force --deep --strict --options runtime --timestamp --sign "${IDENTITY}" --entitlements neededToRun.entitlements "${item}"`); +} + +exec(`codesign --verbose --force --deep --strict --options runtime --timestamp --sign "${IDENTITY}" --entitlements neededToRun.entitlements "${APP}"`); + +/****************************************************************************/ + +console.log(""); +console.log("### verifying signature"); + +exec(`codesign --verify -vvvv "${APP}"`); \ No newline at end of file diff --git a/resources/macossign/workshop/neededToRun.entitlements b/resources/macossign/workshop/neededToRun.entitlements new file mode 100644 index 000000000..b91ddfaa3 --- /dev/null +++ b/resources/macossign/workshop/neededToRun.entitlements @@ -0,0 +1,18 @@ + + + + + com.apple.security.automation.apple-events + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-executable-page-protection + + com.apple.security.cs.disable-library-validation + + + \ No newline at end of file diff --git a/resources/macossign/workshop/sign b/resources/macossign/workshop/sign new file mode 100644 index 000000000..55a075bfb --- /dev/null +++ b/resources/macossign/workshop/sign @@ -0,0 +1,8 @@ +#!/bin/sh +printf "Unlock keychain\n----\n\n" +security unlock-keychain -p "atacama" /Users/macossign/Library/Keychains/Apple.keychain-db +/Users/vincent/Sign/docodesign "$1" "Developer ID Application: Cubedesigners (82TNE4UQ7A)" +ditto -c -k --sequesterRsrc --keepParent "$1" "$1.zip" +#xcode-select -s $1 +xcrun notarytool submit --wait --apple-id "contact@cubedesigners.com" --team-id "82TNE4UQ7A" --password "tqwj-saik-dtdl-yrpc" "$1.zip" +xcrun stapler staple $1