fileoptimizer-bin
MEDIUM
maintainer lapsus
3 votes
scanned 2026-10-19 15:25:12.467407
Why flagged
curl/wget fetches a URL on a non-allowlisted host that is not part of source=(), so it is not checksum-verified by makepkg.
Triggered rules
Medium
External download from an untrusted host, not in source=()
external_download_not_in_source
curl/wget fetches a URL on a non-allowlisted host that is not part of source=(), so it is not checksum-verified by makepkg.
-
PKGBUILD:26
choco=$(curl -fsSL "https://community.chocolatey.org/api/v2/FindPackagesById()?id='fileoptimizer'" \ -
PKGBUILD:29
upstream_mm=$(curl -fsSL "https://nikkhokkho.sourceforge.io/?page=FileOptimizer" \
PKGBUILD
2 offending line(s) highlighted
1
# Maintainer: Yakov Till <yakov.till@gmail.com>
2
3
pkgname=fileoptimizer-bin
4
_pkgname=fileoptimizer
5
6
# manual-hint: FileOptimizer ships only on SourceForge, whose files listing
7
# and best_release.json are now Cloudflare-gated (curl gets a challenge page).
8
# Every downstream packager (Scoop, Chocolatey) scrapes that same listing, so
9
# none exposes a Cloudflare-free authoritative feed. If latestver() ever emits
10
# a bare MAJOR.MINOR (chocolatey mirror lagging upstream), read the build
11
# number from https://sourceforge.net/projects/nikkhokkho/files/FileOptimizer/
12
# in a browser (curl is challenged) and set pkgver to MAJOR.MINOR.BUILD.
13
pkgver=17.10.2857
14
15
# No Cloudflare-free authoritative source exists, so combine two:
16
# * Chocolatey's community feed re-publishes the full MAJOR.MINOR.BUILD over a
17
# non-Cloudflare API — the only machine-readable source for the build number.
18
# * The upstream FlatPress product page (not Cloudflare-gated) is authoritative
19
# for the newest MAJOR.MINOR.
20
# When chocolatey's minor matches upstream's, the mirror is current → return the
21
# full version. When upstream is strictly newer, chocolatey is stale/frozen →
22
# return the bare MAJOR.MINOR, which no asset exists for, so the stale mirror
23
# surfaces loudly instead of being trusted silently. See manual-hint for the build number.
24
latestver() {
25
local choco upstream_mm choco_mm newer_mm
26
choco=$(curl -fsSL "https://community.chocolatey.org/api/v2/FindPackagesById()?id='fileoptimizer'" \
27
| grep -oE '<d:Version>[0-9]+\.[0-9]+\.[0-9]+</d:Version>' \
28
| grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | sort -V | tail -1)
29
upstream_mm=$(curl -fsSL "https://nikkhokkho.sourceforge.io/?page=FileOptimizer" \
30
| grep -aoE '[0-9]+\.[0-9]+ - 20[0-9]{2}/[0-9]{2}/[0-9]{2}' \
31
| head -1 | grep -oE '^[0-9]+\.[0-9]+')
32
if [ -z "$choco" ]; then
33
[ -n "$upstream_mm" ] && printf '%s\n' "$upstream_mm"
34
return
35
fi
36
choco_mm=${choco%.*}
37
newer_mm=$(printf '%s\n%s\n' "$choco_mm" "$upstream_mm" | sort -V | tail -1)
38
if [ -n "$upstream_mm" ] && [ "$newer_mm" != "$choco_mm" ]; then
39
printf '%s\n' "$upstream_mm"
40
else
41
printf '%s\n' "$choco"
42
fi
43
}
44
45
pkgrel=5
46
pkgdesc="Lossless file size optimizer supporting multiple formats"
47
arch=('x86_64')
48
url="https://nikkhokkho.sourceforge.io/?page=FileOptimizer"
49
license=('AGPL-3.0-only OR AGPL-3.0-or-later')
50
depends=('wine' 'wine-mono' 'wine-gecko')
51
makedepends=('icoutils' 'imagemagick')
52
provides=("${_pkgname}")
53
conflicts=("${_pkgname}")
54
# downloads.sourceforge.net is now Cloudflare-gated; the master mirror serves
55
# the file directly. ?viasf=1 marks the request as SourceForge-originated.
56
source=("$_pkgname-$pkgver.7z.exe::https://master.dl.sourceforge.net/project/nikkhokkho/FileOptimizer/${pkgver}/FileOptimizerFull.7z.exe?viasf=1"
57
"$_pkgname.desktop")
58
sha256sums=('5fe38b7848fc5dac00aa063ce67cdd956c43913420cef8851aed846182ff3dce'
59
'a84498b533c5acff60d98cd413df3c63f4408fddd9eb235e6c25c58931655ff5')
60
options=(!strip !debug)
61
62
package() {
63
install -dm755 "$pkgdir/opt/$_pkgname"
64
65
install -Dm755 FileOptimizer64.exe "$pkgdir/opt/$_pkgname/FileOptimizer64.exe"
66
install -Dm755 WebView2Loader.dll "$pkgdir/opt/$_pkgname/WebView2Loader.dll"
67
68
cp -r Plugins64 "$pkgdir/opt/$_pkgname/"
69
70
install -Dm644 FileOptimizer.chm "$pkgdir/opt/$_pkgname/FileOptimizer.chm"
71
72
install -Dm644 *.po -t "$pkgdir/opt/$_pkgname/"
73
74
# Extract icon from executable
75
wrestool -x -t 14 FileOptimizer64.exe -o FileOptimizer.ico
76
77
# Convert ico to png files
78
magick FileOptimizer.ico fileoptimizer.png
79
80
# The above command creates files like fileoptimizer-0.png, fileoptimizer-1.png, etc.
81
# We need to identify which file corresponds to which size
82
83
# Create a directory to store the icon files
84
mkdir -p icons
85
86
# Move the generated PNG files to the icons directory
87
mv fileoptimizer-*.png icons/
88
89
# Install icons to appropriate directories based on their size
90
for icon in icons/fileoptimizer-*.png; do
91
size=$(identify -format "%wx%h" "$icon" | cut -d 'x' -f 1)
92
install -Dm644 "$icon" "$pkgdir/usr/share/icons/hicolor/${size}x${size}/apps/$_pkgname.png"
93
done
94
95
# Set the desktop file to use the installed icon
96
install -Dm644 "$_pkgname.desktop" "$pkgdir/usr/share/applications/$_pkgname.desktop"
97
98
# Create the wrapper script
99
install -Dm755 /dev/null "$pkgdir/usr/bin/$_pkgname"
100
cat << 'EOF' > "$pkgdir/usr/bin/$_pkgname"
101
#!/bin/bash
102
set -e
103
104
export WINEARCH=win64
105
export WINEDEBUG=-all
106
107
USER_CONFIG_DIR="$HOME/.config/fileoptimizer"
108
INSTALL_DIR="/opt/fileoptimizer"
109
110
# Create user config directory if it doesn't exist
111
mkdir -p "$USER_CONFIG_DIR"
112
113
# Create symlinks for program files if they don't exist
114
# This allows the app to be run from the user's config directory
115
# while the actual files remain in the system directory
116
create_symlink() {
117
local source="$1"
118
local target="$2"
119
if [ ! -e "$source" ]; then
120
echo "Warning: Source file $source does not exist" >&2
121
return 1
122
fi
123
if [ ! -e "$target" ]; then
124
ln -sf "$source" "$target"
125
fi
126
}
127
128
# Check if installation directory exists
129
if [ ! -d "$INSTALL_DIR" ]; then
130
echo "Error: Installation directory $INSTALL_DIR not found" >&2
131
exit 1
132
fi
133
134
# Create necessary symlinks
135
create_symlink "$INSTALL_DIR/FileOptimizer64.exe" "$USER_CONFIG_DIR/FileOptimizer64.exe" || exit 1
136
create_symlink "$INSTALL_DIR/WebView2Loader.dll" "$USER_CONFIG_DIR/WebView2Loader.dll" || exit 1
137
create_symlink "$INSTALL_DIR/Plugins64" "$USER_CONFIG_DIR/Plugins64" || exit 1
138
create_symlink "$INSTALL_DIR/FileOptimizer.chm" "$USER_CONFIG_DIR/FileOptimizer.chm" || exit 1
139
140
# Create default config if it doesn't exist (disable auto-updater)
141
if [ ! -f "$USER_CONFIG_DIR/FileOptimizer64.ini" ]; then
142
printf '[Options]\nCheckForUpdates=0\n' > "$USER_CONFIG_DIR/FileOptimizer64.ini"
143
fi
144
145
# Change to the config directory
146
cd "$USER_CONFIG_DIR" || { echo "Error: Cannot change to $USER_CONFIG_DIR" >&2; exit 1; }
147
148
# Run FileOptimizer with Wine, passing all arguments directly
149
wine "$USER_CONFIG_DIR/FileOptimizer64.exe" "$@"
150
EOF
151
152
}
153
Changes since previous scan
--- PKGBUILD @ 2026-06-20 16:03+++ PKGBUILD @ 2026-10-19 15:25@@ -19,8 +19,8 @@ # for the newest MAJOR.MINOR. # When chocolatey's minor matches upstream's, the mirror is current → return the # full version. When upstream is strictly newer, chocolatey is stale/frozen →-# return the bare MAJOR.MINOR so check-updates reports asset-missing (loud) rather-# than silently trusting a frozen mirror. See manual-hint for the build number.+# return the bare MAJOR.MINOR, which no asset exists for, so the stale mirror+# surfaces loudly instead of being trusted silently. See manual-hint for the build number. latestver() { local choco upstream_mm choco_mm newer_mm choco=$(curl -fsSL "https://community.chocolatey.org/api/v2/FindPackagesById()?id='fileoptimizer'" \Scan history
| Scanned at (UTC) | Severity | Rules |
|---|---|---|
| 2026-10-19 15:25:12 | Medium | 1 |
| 2026-06-20 16:03:41 | Clean | 2 |
| 2026-06-20 00:50:07 | Medium | 2 |
| 2026-06-20 00:18:46 | Medium | 1 |
| 2026-06-19 23:51:18 | Medium | 2 |
| 2026-06-19 19:07:35 | Low | 2 |
| 2026-06-18 18:55:24 | Medium | 1 |
| 2026-06-18 16:11:54 | Medium | 1 |