#!/bin/sh # Fix: dialogs (CodeGit, Macro, Market, Settings) rendered EMPTY. # # Root cause: the project was registered with a RELATIVE path, and the UI used it verbatim. # # 1. install/process.php stores a relative folder name: projects.db -> {"Blog": "blog"} # 2. common.php::loadState() does $projectPath = reset($projectList) -> "blog" # and persists it to the session, so the bad value STICKS. # 3. filetree puts it straight into the DOM: # 4. codegit sends repo="blog"; getWorkspacePath("blog") fails checkPath() -> 403 # 5. modal.js does `if (status !== 200) return;` -> SWALLOWS the error -> #content stays empty # # That last step is why it presents as an empty/black dialog rather than an error: the request # fails, nothing is rendered, and nothing is reported. # # Atheos's own project-creation code resolves relative -> WORKSPACE/, so a relative value in # the store is legitimate - loadState() simply fails to resolve it. Both fixes are needed: # A. resolve at load time (this also heals sessions already holding the relative value) # B. store absolute paths, so array_search() can still map path -> name for the tree label # # Usage: run ON the guest as root. Idempotent. set -e A=/var/www/atheos echo "=== A. resolve a relative projectPath in loadState() ===" S=$A/common.php if [ ! -f "$S" ]; then echo " !! $S not found"; exit 1; fi if grep -q 'isAbsPath($projectPath)' "$S"; then echo " already applied" else [ -f "$S.orig" ] || cp -a "$S" "$S.orig" php83 -r ' $f=$argv[1]; $s=file_get_contents($f); $old = " \$openFiles_db = Common::getObjStore(\"activeFiles\", \"users/\" . \$activeUser);"; if (strpos($s,$old) === false) { fwrite(STDERR," !! anchor not found in loadState\n"); exit(1); } $new = " // A project may be registered with a RELATIVE folder name (the installer stores it\n // that way). Handing that to the UI yields data-path=\"blog\", and every later\n // getWorkspacePath() call then fails its access check with 403 - which the modal\n // silently swallows, leaving the dialog empty. Resolve it once here, and re-store it\n // so sessions already holding the relative value heal on their next load.\n if (!Common::isAbsPath(\$projectPath)) {\n \$projectPath = Common::getWorkspacePath(\$projectPath, true);\n SESSION(\"projectPath\", \$projectPath);\n }\n\n" . $old; file_put_contents($f, str_replace($old,$new,$s)); echo " patched loadState\n";' "$S" php83 -l "$S" >/dev/null 2>&1 || { echo " !! SYNTAX ERROR - restore $S.orig"; exit 1; } fi echo "=== B. store absolute paths in the projects store ===" P=$A/data/projects.db.json.php if [ ! -f "$P" ]; then echo " !! $P not found" elif grep -q '"\/' "$P"; then echo " already absolute" else cp -a "$P" "$P.bak-$(date +%Y%m%d-%H%M%S)" php83 -r ' $f=$argv[1]; $ws="/var/www/atheos/workspace"; $raw=file_get_contents($f); preg_match("/<\?php\/\*\|(.*)\|\*\/\?>/s",$raw,$m); $d=json_decode($m[1],true); if(!is_array($d)){ fwrite(STDERR," !! store unreadable\n"); exit(1); } $c=false; foreach($d as $n=>$p){ if(!preg_match("#^(/|[A-Za-z]:)#",$p)){ $d[$n]=$ws."/".ltrim($p,"/"); $c=true; } } if(!$c){ echo " already absolute\n"; exit(0); } file_put_contents($f,""); echo " store rewritten -> ".json_encode($d)."\n";' "$P" chown atheos:atheos "$P" 2>/dev/null || true fi echo "=== verify ===" php83 -r ' $raw=file_get_contents("/var/www/atheos/data/projects.db.json.php"); preg_match("/<\?php\/\*\|(.*)\|\*\/\?>/s",$raw,$m); $d=json_decode($m[1],true); $p=reset($d); $n=array_search($p,$d); printf(" path=%s name=%s\n",$p,var_export($n,true)); printf(" absolute: %s\n", preg_match("#^(/|[A-Za-z]:)#",$p) ? "yes" : "NO");' 2>&1 echo "=== done ==="