#!/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