secubox-openwrt/package/secubox/secubox-p2p/root/www/api/factory/packages
CyberMind-FR 304ac7b9a1 feat: P2P App Store, Remote Access & Mesh Media packages
P2P App Store Emancipation:
- secubox-p2p: Package distribution via mesh peers (CGI API, RPCD, CLI)
- packages.js: LuCI view with LOCAL/PEER badges, fetch/install actions
- devstatus.js: Dev Status widget with Gitea commits, v1.0 progress tracking
- secubox-feed: sync-content command for auto-installing content packages
- ACL fix for P2P feed RPCD methods

Remote Access:
- secubox-app-rustdesk: Native hbbs/hbbr relay server from GitHub releases
- secubox-app-guacamole: LXC Debian container with guacd + Tomcat (partial)

Content Distribution:
- secubox-content-pkg: Auto-package Metablogizer/Streamlit as IPKs
- Auto-publish hooks in metablogizerctl and streamlitctl

Mesh Media:
- secubox-app-ksmbd: In-kernel SMB3 server with ksmbdctl CLI
- Pre-configured shares for Jellyfin, Lyrion, Backup

UI Consistency:
- client-guardian: Ported to sh-page-header chip layout
- auth-guardian: Ported to sh-page-header chip layout

Fixes:
- services.js: RPC expect unwrapping bug fix
- metablogizer: Chunked upload for uhttpd 64KB limit

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 00:33:53 +01:00

181 lines
3.9 KiB
Bash

#!/bin/sh
# P2P Package Catalog API
# Returns local package feed as JSON for mesh distribution
echo "Content-Type: application/json"
echo "Access-Control-Allow-Origin: *"
echo "Access-Control-Allow-Methods: GET, OPTIONS"
echo ""
# Handle CORS preflight
if [ "$REQUEST_METHOD" = "OPTIONS" ]; then
exit 0
fi
# Load P2P feed library
. /usr/lib/secubox/p2p-feed.sh 2>/dev/null
# Parse query string
parse_query() {
local query="$QUERY_STRING"
local key value
# Initialize variables
INFO_ONLY=""
PACKAGE_FILTER=""
# Parse key=value pairs
while [ -n "$query" ]; do
key="${query%%=*}"
query="${query#*=}"
value="${query%%&*}"
query="${query#*&}"
[ "$query" = "$value" ] && query=""
case "$key" in
info_only) INFO_ONLY="$value" ;;
package) PACKAGE_FILTER="$value" ;;
esac
done
}
parse_query
# Get node info
NODE_ID=$(get_local_node_id)
NODE_NAME=$(get_local_node_name)
UPDATED=$(date -Iseconds 2>/dev/null || date '+%Y-%m-%dT%H:%M:%S')
# Check if feed sharing is enabled
if ! feed_sharing_enabled; then
cat << EOF
{
"error": "feed_sharing_disabled",
"message": "Package feed sharing is disabled on this node",
"node_id": "$NODE_ID",
"node_name": "$NODE_NAME"
}
EOF
exit 0
fi
# Check if feed exists
if ! feed_exists; then
cat << EOF
{
"error": "no_feed",
"message": "No package feed found",
"node_id": "$NODE_ID",
"node_name": "$NODE_NAME"
}
EOF
exit 0
fi
FEED_HASH=$(get_feed_hash)
PKG_COUNT=$(get_package_count)
# Info only mode - just return metadata
if [ "$INFO_ONLY" = "1" ]; then
cat << EOF
{
"node_id": "$NODE_ID",
"node_name": "$NODE_NAME",
"updated": "$UPDATED",
"feed_hash": "$FEED_HASH",
"package_count": $PKG_COUNT,
"feed_url": "http://$(uci -q get network.lan.ipaddr || echo '192.168.255.1')/secubox-feed/"
}
EOF
exit 0
fi
# Filter for specific package
if [ -n "$PACKAGE_FILTER" ]; then
# Search for specific package in Packages file
PACKAGES_JSON=$(awk -v pkg="$PACKAGE_FILTER" '
BEGIN {
found = 0
first = 1
printf "["
}
/^Package:/ {
current_pkg = $2
if (current_pkg == pkg) found = 1
else found = 0
}
found && /^$/ {
if (pkg_name != "") {
if (!first) printf ","
first = 0
printf "\n{"
printf "\"name\":\"%s\"", pkg_name
printf ",\"version\":\"%s\"", pkg_version
printf ",\"architecture\":\"%s\"", pkg_arch
printf ",\"size\":%s", (pkg_size != "" ? pkg_size : "0")
printf ",\"installed_size\":%s", (pkg_isize != "" ? pkg_isize : "0")
if (pkg_sha256 != "") printf ",\"sha256\":\"%s\"", pkg_sha256
if (pkg_depends != "") printf ",\"depends\":\"%s\"", pkg_depends
if (pkg_desc != "") {
gsub(/"/, "\\\"", pkg_desc)
printf ",\"description\":\"%s\"", pkg_desc
}
if (pkg_filename != "") printf ",\"filename\":\"%s\"", pkg_filename
printf "}"
}
pkg_name = pkg_version = pkg_arch = pkg_size = pkg_isize = ""
pkg_sha256 = pkg_depends = pkg_desc = pkg_filename = ""
found = 0
}
found && /^Package:/ { pkg_name = $2 }
found && /^Version:/ { pkg_version = $2 }
found && /^Architecture:/ { pkg_arch = $2 }
found && /^Size:/ { pkg_size = $2 }
found && /^Installed-Size:/ { pkg_isize = $2 }
found && /^SHA256sum:/ { pkg_sha256 = $2 }
found && /^Depends:/ {
pkg_depends = $0
sub(/^Depends: */, "", pkg_depends)
}
found && /^Description:/ {
pkg_desc = $0
sub(/^Description: */, "", pkg_desc)
}
found && /^Filename:/ { pkg_filename = $2 }
END {
printf "\n]"
}
' "$PACKAGES_FILE")
cat << EOF
{
"node_id": "$NODE_ID",
"node_name": "$NODE_NAME",
"updated": "$UPDATED",
"feed_hash": "$FEED_HASH",
"filter": "$PACKAGE_FILTER",
"packages": $PACKAGES_JSON
}
EOF
exit 0
fi
# Full package list
PACKAGES_JSON=$(packages_to_json)
cat << EOF
{
"node_id": "$NODE_ID",
"node_name": "$NODE_NAME",
"updated": "$UPDATED",
"feed_hash": "$FEED_HASH",
"package_count": $PKG_COUNT,
"feed_url": "http://$(uci -q get network.lan.ipaddr || echo '192.168.255.1')/secubox-feed/",
"packages": $PACKAGES_JSON
}
EOF