Files
blackbird/aibox/skills/test-auto-appimage.sh
T
qing 9064750f33 fix(aibox/skills): Batch M 波次2 路径边界收口(S2/S3/S6/S9/S10/S11/S12/S13)
- gitclient: delete 限工作区内 .git 仓库(S2);分支名白名单防选项注入(S3)
- camera/screenshot: --filename 拒绝分隔符/绝对路径/父目录引用(S9/S10)
- facerec: person_name 白名单(兼容中文)接入 add/remove/get-info(S11)
- vision: 图片魔数白名单校验,data URL MIME 按实测类型(S12)
- sftp-transfer: listdir 条目名双向过滤防恶意服务端目录逃逸(S6)
- test-auto-appimage: exec_name 白名单防 sed 替换注入(S13)

测试 493 passed / 4 failed(既有平台环境项)/ 1 skipped,零回归
2026-08-20 13:11:07 +08:00

277 lines
8.6 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# appimage-packager.sh - 简单的AppImage打包工具
set -e
# 彩色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# 帮助信息
show_help() {
cat << EOF
${GREEN}AppImage 打包工具${NC}
${BLUE}════════════════════════════════${NC}
${YELLOW}用法:${NC}
$0 [选项] <可执行文件> [输出名称]
${YELLOW}选项:${NC}
-h, --help 显示帮助信息
-i, --icon <文件> 指定图标文件 (PNG格式)
-d, --data <目录> 包含数据文件目录
-n, --name <名称> 应用程序名称
-v, --version <版本> 设置版本号
-t, --terminal 在终端中运行
${YELLOW}示例:${NC}
$0 ./myapp # 基本打包
$0 -i icon.png ./myapp # 带图标
$0 -d data/ ./myapp MyApp # 包含数据文件
$0 -t ./cli-tool # 命令行工具
${BLUE}════════════════════════════════${NC}
EOF
}
# 创建默认图标
create_default_icon() {
local icon_path="$1"
mkdir -p "$(dirname "$icon_path")"
# 创建一个简单的1x1像素PNG图标
echo -ne '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\nIDATx\x9cc\xf8\x0f\x00\x00\x01\x00\x01\x05\x01\x00\x00\x00\x00IEND\xaeB`\x82' > "$icon_path"
}
# 创建AppRun脚本
create_apprun() {
local app_dir="$1"
local exec_name="$2"
local terminal="$3"
# S13(审计 2026-08-20):exec_name 进入 sed 替换串,含 / & 等字符会注入或破坏
# 替换表达式(如 "a/x" 使 s///g 错位、"&" 展开为匹配串)。白名单拦截,拒绝即退出。
if [[ ! "$exec_name" =~ ^[A-Za-z0-9._+-]+$ ]]; then
echo -e "${RED}错误: 可执行文件名含非法字符(仅允许 A-Za-z0-9._+-): $exec_name${NC}"
exit 1
fi
cat > "$app_dir/AppRun" << 'EOF'
#!/bin/bash
HERE="$(dirname "$(readlink -f "$0")")"
export PATH="$HERE/usr/bin:$PATH"
export LD_LIBRARY_PATH="$HERE/usr/lib:$LD_LIBRARY_PATH"
export XDG_DATA_DIRS="$HERE/usr/share:$XDG_DATA_DIRS"
exec "$HERE/usr/bin/EXEC_NAME" "$@"
EOF
# 替换可执行文件名
sed -i "s/EXEC_NAME/$exec_name/g" "$app_dir/AppRun"
chmod +x "$app_dir/AppRun"
}
# 收集动态库依赖
collect_dependencies() {
local executable="$1"
local lib_dir="$2"
echo -e "${YELLOW}收集动态库依赖...${NC}"
mkdir -p "$lib_dir"
local count=0
# 使用ldd获取依赖
ldd "$executable" 2>/dev/null | grep "=> /" | awk '{print $3}' | while read -r lib; do
if [ -f "$lib" ] && [ ! -f "$lib_dir/$(basename "$lib")" ]; then
cp -f "$lib" "$lib_dir/" 2>/dev/null && {
echo " ✓ $(basename "$lib")"
count=$((count + 1))
}
fi
done
echo -e "${GREEN}✓ 已收集 $count 个库${NC}"
}
# 主程序
main() {
# 默认参数
ICON_FILE=""
DATA_DIR=""
APP_NAME=""
APP_VERSION="1.0"
TERMINAL=false
# 解析参数
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-i|--icon)
ICON_FILE="$2"
shift 2
;;
-d|--data)
DATA_DIR="$2"
shift 2
;;
-n|--name)
APP_NAME="$2"
shift 2
;;
-v|--version)
APP_VERSION="$2"
shift 2
;;
-t|--terminal)
TERMINAL=true
shift
;;
-*)
echo -e "${RED}错误: 未知选项 $1${NC}"
show_help
exit 1
;;
*)
break
;;
esac
done
# 检查参数
if [[ $# -lt 1 ]]; then
show_help
exit 1
fi
EXECUTABLE="$1"
OUTPUT_NAME="${2:-$(basename "$EXECUTABLE" .AppImage)}"
# 检查可执行文件
if [[ ! -f "$EXECUTABLE" ]]; then
echo -e "${RED}错误: 文件不存在: $EXECUTABLE${NC}"
exit 1
fi
if [[ ! -x "$EXECUTABLE" ]]; then
echo -e "${YELLOW}添加执行权限...${NC}"
chmod +x "$EXECUTABLE"
fi
# 设置应用程序名称
if [[ -z "$APP_NAME" ]]; then
APP_NAME="$OUTPUT_NAME"
fi
echo -e "${BLUE}════════════════════════════════${NC}"
echo -e "${GREEN}AppImage 打包工具${NC}"
echo -e "${BLUE}════════════════════════════════${NC}"
echo "程序: $(basename "$EXECUTABLE")"
echo "输出: $OUTPUT_NAME.AppImage"
echo "名称: $APP_NAME"
echo "版本: $APP_VERSION"
echo ""
# 清理旧文件
rm -rf AppDir "${OUTPUT_NAME}.AppImage"
# 步骤1: 创建目录结构
echo -e "${YELLOW}[1/6] 创建目录结构...${NC}"
mkdir -p AppDir/usr/bin
mkdir -p AppDir/usr/lib
mkdir -p AppDir/usr/share/applications
mkdir -p AppDir/usr/share/icons/hicolor/256x256/apps
# 步骤2: 复制可执行文件
echo -e "${YELLOW}[2/6] 复制可执行文件...${NC}"
EXEC_NAME=$(basename "$EXECUTABLE")
cp "$EXECUTABLE" "AppDir/usr/bin/$EXEC_NAME"
echo -e "${GREEN}✓ 已复制: $EXEC_NAME${NC}"
# 步骤3: 收集动态库
collect_dependencies "$EXECUTABLE" "AppDir/usr/lib"
# 步骤4: 处理数据文件
if [[ -n "$DATA_DIR" ]] && [[ -d "$DATA_DIR" ]]; then
echo -e "${YELLOW}[3/6] 复制数据文件...${NC}"
cp -r "$DATA_DIR"/* "AppDir/usr/share/$APP_NAME/" 2>/dev/null || true
echo -e "${GREEN}✓ 已复制数据文件${NC}"
fi
# 步骤5: 处理图标
echo -e "${YELLOW}[4/6] 设置图标...${NC}"
if [[ -n "$ICON_FILE" ]] && [[ -f "$ICON_FILE" ]]; then
cp "$ICON_FILE" "AppDir/usr/share/icons/hicolor/256x256/apps/$APP_NAME.png"
cp "$ICON_FILE" "AppDir/$APP_NAME.png"
echo -e "${GREEN}✓ 使用自定义图标${NC}"
else
create_default_icon "AppDir/usr/share/icons/hicolor/256x256/apps/$APP_NAME.png"
create_default_icon "AppDir/$APP_NAME.png"
echo -e "${YELLOW}⚠ 使用默认图标${NC}"
fi
cp "AppDir/$APP_NAME.png" "AppDir/.DirIcon"
# 步骤6: 创建桌面文件
echo -e "${YELLOW}[5/6] 创建桌面文件...${NC}"
TERMINAL_FLAG="$([ "$TERMINAL" = true ] && echo "true" || echo "false")"
cat > "AppDir/usr/share/applications/$APP_NAME.desktop" << EOF
[Desktop Entry]
Version=$APP_VERSION
Type=Application
Name=$APP_NAME
Comment=$APP_NAME application
Exec=$EXEC_NAME
Icon=$APP_NAME
Terminal=$TERMINAL_FLAG
Categories=Utility;
StartupNotify=false
EOF
ln -sf usr/share/applications/$APP_NAME.desktop "AppDir/"
# 步骤7: 创建AppRun
echo -e "${YELLOW}[6/6] 创建AppRun...${NC}"
create_apprun "AppDir" "$EXEC_NAME" "$TERMINAL"
# 步骤8: 打包AppImage
echo -e "\n${YELLOW}打包AppImage...${NC}"
if command -v appimagetool >/dev/null 2>&1; then
OUTPUT_FILE="${OUTPUT_NAME}.AppImage"
appimagetool --no-appstream AppDir "$OUTPUT_FILE" 2>&1 | grep -v "WARNING" | grep -v "gpg" || true
if [[ -f "$OUTPUT_FILE" ]]; then
chmod +x "$OUTPUT_FILE"
echo -e "\n${GREEN}════════════════════════════════${NC}"
echo -e "${GREEN}✅ 打包成功!${NC}"
echo -e "${GREEN}════════════════════════════════${NC}"
echo "📦 输出: $(realpath "$OUTPUT_FILE")"
echo "📏 大小: $(du -h "$OUTPUT_FILE" | cut -f1)"
echo ""
echo "🚀 运行: ./$OUTPUT_FILE"
# 清理
rm -rf AppDir
else
echo -e "${RED}❌ 打包失败${NC}"
exit 1
fi
else
echo -e "${RED}错误: 未找到 appimagetool${NC}"
echo ""
echo "请下载 appimagetool:"
echo " wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
echo " chmod +x appimagetool-x86_64.AppImage"
echo " sudo mv appimagetool-x86_64.AppImage /usr/local/bin/appimagetool"
exit 1
fi
}
# 运行主程序
main "$@"