diff --git a/README.md b/README.md index 8abaff31..5d3bdc1e 100644 --- a/README.md +++ b/README.md @@ -972,7 +972,9 @@ interact with copyparty using non-browser clients * `var xhr = new XMLHttpRequest(); xhr.open('POST', '//127.0.0.1:3923/msgs?raw'); xhr.send('foo');` * curl/wget: upload some files (post=file, chunk=stdin) - * `post(){ curl -b cppwd=wark -F act=bput -F f=@"$1" http://127.0.0.1:3923/;}` + * `post(){ curl -F act=bput -F f=@"$1" http://127.0.0.1:3923/?pw=wark;}` + `post movie.mkv` + * `post(){ curl -b cppwd=wark -H rand:8 -T "$1" http://127.0.0.1:3923/;}` `post movie.mkv` * `post(){ wget --header='Cookie: cppwd=wark' --post-file="$1" -O- http://127.0.0.1:3923/?raw;}` `post movie.mkv` @@ -998,7 +1000,9 @@ copyparty returns a truncated sha512sum of your PUT/POST as base64; you can gene b512(){ printf "$((sha512sum||shasum -a512)|sed -E 's/ .*//;s/(..)/\\x\1/g')"|base64|tr '+/' '-_'|head -c44;} b512 $f) diff --git a/scripts/pyinstaller/README.md b/scripts/pyinstaller/README.md new file mode 100644 index 00000000..28c7490e --- /dev/null +++ b/scripts/pyinstaller/README.md @@ -0,0 +1,7 @@ +builds a fully standalone copyparty.exe compatible with 32bit win7-sp1 and later + +requires a win7 vm which has never been connected to the internet and a host-only network with the linux host at 192.168.123.1 + +first-time setup steps in notes.txt + +run build.sh in the vm to fetch src + compile + push a new exe to the linux host for manual publishing diff --git a/scripts/pyinstaller/build.sh b/scripts/pyinstaller/build.sh new file mode 100644 index 00000000..2436cb95 --- /dev/null +++ b/scripts/pyinstaller/build.sh @@ -0,0 +1,46 @@ +#!/bin/bash +set -e + +curl http://192.168.123.1:3923/cpp/scripts/pyinstaller/build.sh | +tee build2.sh | cmp build.sh || { + echo "new build script; upgrade y/n:" + while true; do read -u1 -n1 -r r; [[ $r =~ [yYnN] ]] && break; done + [[ $r =~ [yY] ]] && mv build{2,}.sh && exec ./build.sh +} + +dl() { curl -fkLO "$1"; } + +cd ~/Downloads + +dl https://192.168.123.1:3923/cpp/dist/copyparty-sfx.py +dl https://192.168.123.1:3923/cpp/scripts/pyinstaller/loader.ico +dl https://192.168.123.1:3923/cpp/scripts/pyinstaller/loader.py +dl https://192.168.123.1:3923/cpp/scripts/pyinstaller/loader.rc + +rm -rf $TEMP/pe-copyparty* +python copyparty-sfx.py --version + +rm -rf mods; mkdir mods +cp -pR $TEMP/pe-copyparty/copyparty/ $TEMP/pe-copyparty/{ftp,j2}/* mods/ + +rm -rf mods/magic/ +grep -lR 'import multiprocessing' | while read x; do + sed -ri 's/import multiprocessing/import fgsfds/' $x +done + +read a b c d _ < <( + grep -E '^VERSION =' mods/copyparty/__version__.py | + tail -n 1 | + sed -r 's/[^0-9]+//;s/[" )]//g;s/[-,]/ /g;s/$/ 0/' +) +sed -r 's/1,2,3,0/'$a,$b,$c,$d'/;s/1\.2\.3/'$a.$b.$c/ loader.rc2 + +$APPDATA/python/python37/scripts/pyinstaller \ + -y --clean -p mods --upx-dir=. \ + --version-file loader.rc2 -i loader.ico -n copyparty -c -F loader.py \ + --add-data 'mods/copyparty/res;copyparty/res' \ + --add-data 'mods/copyparty/web;copyparty/web' + +# ./upx.exe --best --ultra-brute --lzma -k dist/copyparty.exe + +curl -fkT dist/copyparty.exe -b cppwd=wark https://192.168.123.1:3923/ diff --git a/scripts/pyinstaller/icon.sh b/scripts/pyinstaller/icon.sh new file mode 100755 index 00000000..8877e143 --- /dev/null +++ b/scripts/pyinstaller/icon.sh @@ -0,0 +1,27 @@ +#!/bin/bash +set -e + +# imagemagick png compression is broken, use pillow instead +convert ~/AndroidStudioProjects/PartyUP/metadata/en-US/images/icon.png a.bmp + +#convert a.bmp -trim -resize '48x48!' -strip a.png +python3 <<'EOF' +from PIL import Image +i = Image.open('a.bmp') +i = i.crop(i.getbbox()) +i = i.resize((48,48), Image.BICUBIC) +i = Image.alpha_composite(i,i) +i.save('a.png') +EOF + +pngquant --strip --quality 30 a.png +mv a-*.png a.png + +python3 <<'EOF' +from PIL import Image +Image.open('a.png').save('loader.ico',sizes=[(48,48)]) +EOF + +rm a.{bmp,png} +ls -al +exit 0 diff --git a/scripts/pyinstaller/loader.py b/scripts/pyinstaller/loader.py new file mode 100644 index 00000000..954ebd29 --- /dev/null +++ b/scripts/pyinstaller/loader.py @@ -0,0 +1,72 @@ +# coding: utf-8 + +v = r""" + +this is the EXE edition of copyparty, compatible with Windows7-SP1 +and later. To make this possible, the EXE was compiled with Python +3.7.9, which is EOL and does not receive security patches anymore. + +it is strongly recommended to use the python sfx instead: +https://github.com/9001/copyparty/releases/latest/download/copyparty-sfx.py +""" + +print(v.replace("\n", "\nā–‘ā–Œ ")[1:] + "\n") + + +import re +import os +import sys +import shutil +import subprocess as sp + + +def meicln(mod, pids): + pdir, mine = os.path.split(mod) + dirs = os.listdir(pdir) + dirs = [x for x in dirs if x.startswith("_MEI") and x != mine] + dirs = [os.path.join(pdir, x) for x in dirs] + rm = [] + for d in dirs: + if os.path.isdir(os.path.join(d, "copyparty", "web")): + rm.append(d) + + if not rm: + return + + print("deleting abandoned SFX dirs:") + for d in rm: + print(d) + for _ in range(9): + try: + shutil.rmtree(d) + break + except: + pass + + print() + + +def meichk(): + filt = "copyparty" + if filt not in sys.executable: + filt = os.path.basename(sys.executable) + + pids = [] + ptn = re.compile(r"^([^\s]+)\s+([0-9]+)") + procs = sp.check_output("tasklist").decode("utf-8", "replace") + for ln in procs.splitlines(): + m = ptn.match(ln) + if m and filt in m.group(1).lower(): + pids.append(int(m.group(2))) + + mod = os.path.dirname(os.path.realpath(__file__)) + if os.path.basename(mod).startswith("_MEI") and len(pids) == 2: + meicln(mod, pids) + + +meichk() + + +from copyparty.__main__ import main + +main() diff --git a/scripts/pyinstaller/loader.rc b/scripts/pyinstaller/loader.rc new file mode 100644 index 00000000..59ae0ab7 --- /dev/null +++ b/scripts/pyinstaller/loader.rc @@ -0,0 +1,29 @@ +# UTF-8 +VSVersionInfo( + ffi=FixedFileInfo( + filevers=(1,2,3,0), + prodvers=(1,2,3,0), + mask=0x3f, + flags=0x0, + OS=0x4, + fileType=0x1, + subtype=0x0, + date=(0, 0) + ), + kids=[ + StringFileInfo( + [ + StringTable( + '000004b0', + [StringStruct('CompanyName', 'ocv.me'), + StringStruct('FileDescription', 'copyparty'), + StringStruct('FileVersion', '1.2.3'), + StringStruct('InternalName', 'copyparty'), + StringStruct('LegalCopyright', '2019, ed'), + StringStruct('OriginalFilename', 'copyparty.exe'), + StringStruct('ProductName', 'copyparty'), + StringStruct('ProductVersion', '1.2.3')]) + ]), + VarFileInfo([VarStruct('Translation', [0, 1200])]) + ] +) diff --git a/scripts/pyinstaller/notes.txt b/scripts/pyinstaller/notes.txt new file mode 100644 index 00000000..37d4fd4f --- /dev/null +++ b/scripts/pyinstaller/notes.txt @@ -0,0 +1,58 @@ +run ./build.sh in git-bash to build + upload the exe + + +## ============================================================ +## first-time setup on a stock win7x32sp1 vm: +## + +download + install git: +http://192.168.123.1:3923/ro/pyi/Git-2.37.3-32-bit.exe + + +dl() { curl -fkLOC- "$1"; } +cd ~/Downloads && +dl https://192.168.123.1:3923/ro/pyi/upx-3.96-win32.zip && +dl https://192.168.123.1:3923/ro/pyi/KB2533623/Windows6.1-KB2533623-x86.msu && +dl https://192.168.123.1:3923/ro/pyi/python-3.7.9.exe && +dl https://192.168.123.1:3923/ro/pyi/pip-22.2.2-py3-none-any.whl && +dl https://192.168.123.1:3923/ro/pyi/altgraph-0.17.2-py2.py3-none-any.whl && +dl https://192.168.123.1:3923/ro/pyi/future-0.18.2.tar.gz && +dl https://192.168.123.1:3923/ro/pyi/importlib_metadata-4.12.0-py3-none-any.whl && +dl https://192.168.123.1:3923/ro/pyi/pefile-2022.5.30.tar.gz && +dl https://192.168.123.1:3923/ro/pyi/pyinstaller-5.4.1-py3-none-win32.whl && +dl https://192.168.123.1:3923/ro/pyi/pyinstaller_hooks_contrib-2022.10-py2.py3-none-any.whl && +dl https://192.168.123.1:3923/ro/pyi/pywin32_ctypes-0.2.0-py2.py3-none-any.whl && +dl https://192.168.123.1:3923/ro/pyi/typing_extensions-4.3.0-py3-none-any.whl && +dl https://192.168.123.1:3923/ro/pyi/zipp-3.8.1-py3-none-any.whl && +echo ok + +manually install: + windows6.1-kb2533623-x86.msu + reboot + python-3.7.9.exe + + +cd ~/Downloads && +unzip -j upx-3.96-win32.zip upx-3.96-win32/upx.exe && +python -m ensurepip && +python -m pip install --user -U pip-22.2.2-py3-none-any.whl && +python -m pip install --user -U pyinstaller-5.4.1-py3-none-win32.whl pefile-2022.5.30.tar.gz pywin32_ctypes-0.2.0-py2.py3-none-any.whl pyinstaller_hooks_contrib-2022.10-py2.py3-none-any.whl altgraph-0.17.2-py2.py3-none-any.whl future-0.18.2.tar.gz importlib_metadata-4.12.0-py3-none-any.whl typing_extensions-4.3.0-py3-none-any.whl zipp-3.8.1-py3-none-any.whl && +echo ok +# python -m pip install --user -U Pillow-9.2.0-cp37-cp37m-win32.whl +# sed -ri 's/, bestopt, /]+bestopt+[/' $APPDATA/Python/Python37/site-packages/pyinstaller/building/utils.py +# sed -ri 's/(^\s+bestopt = ).*/\1["--best","--lzma","--ultra-brute"]/' $APPDATA/Python/Python37/site-packages/pyinstaller/building/utils.py + + +## ============================================================ +## notes +## + +size t-unpack virustotal cmnt +8059k 0m0.375s 5/70 generic-only, sandbox-ok no-upx +7095k 0m0.563s 4/70 generic-only, sandbox-ok standard-upx +6958k 0m0.578s 7/70 generic-only, sandbox-ok upx+upx + +use python 3.7 since 3.8 onwards requires KB2533623 on target + +generate loader.rc template: +%appdata%\python\python37\scripts\pyi-grab_version C:\Users\ed\AppData\Local\Programs\Python\Python37\python.exe +