diff --git a/fix-phpmyadmin.sh b/fix-phpmyadmin.sh new file mode 100644 index 000000000..8afd733c7 --- /dev/null +++ b/fix-phpmyadmin.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Fix phpMyAdmin 404 after upgrade. Run as root on the panel server. +# Usage: sudo bash fix-phpmyadmin.sh +# Then open https://YOUR_IP:2087/phpmyadmin/ (or from Databases -> phpMyAdmin in the panel). + +set -e +CP="${CP:-/usr/local/CyberCP}" +PUBLIC="$CP/public" +PYTHON="${PYTHON:-$CP/bin/python}" + +if [[ $(id -u) -ne 0 ]]; then + echo "Run as root: sudo bash $0" + exit 1 +fi + +echo "Ensuring $PUBLIC exists..." +mkdir -p "$PUBLIC" + +if [[ ! -x "$PYTHON" ]]; then + PYTHON=$(which python3 2>/dev/null || which python2 2>/dev/null || true) +fi +if [[ -z "$PYTHON" ]]; then + echo "ERROR: No Python found. Install phpMyAdmin manually or fix panel Python." + exit 1 +fi + +echo "Installing phpMyAdmin via panel upgrade module..." +export DJANGO_SETTINGS_MODULE=CyberCP.settings +"$PYTHON" -c " +import sys +sys.path.insert(0, '$CP') +from plogical.upgrade import Upgrade +Upgrade.download_install_phpmyadmin() +" 2>&1 || true + +if [[ -d "$PUBLIC/phpmyadmin" ]]; then + echo "Setting ownership to lscpd:lscpd..." + chown -R lscpd:lscpd "$PUBLIC/phpmyadmin" 2>/dev/null || true + chmod 755 "$PUBLIC/phpmyadmin" + chmod 755 "$PUBLIC/phpmyadmin/tmp" 2>/dev/null || true + echo "Done. phpMyAdmin is at $PUBLIC/phpmyadmin" + echo "Test: https://YOUR_IP:2087/phpmyadmin/ (or use the panel Databases -> phpMyAdmin link)" +else + echo "WARNING: $PUBLIC/phpmyadmin was not created. Check logs above." + exit 1 +fi diff --git a/install/install.py b/install/install.py index 745906b30..ce65ded54 100644 --- a/install/install.py +++ b/install/install.py @@ -3807,17 +3807,31 @@ class Migration(migrations.Migration): self.stdOut(f"Failed to fetch latest phpMyAdmin version, using fallback: {e}", 1) self.stdOut("Installing phpMyAdmin...", 1) + tarball = '/usr/local/CyberCP/public/phpmyadmin.tar.gz' command = ( - f'wget -q -O /usr/local/CyberCP/public/phpmyadmin.tar.gz ' + f'wget -q -O {tarball} ' f'https://files.phpmyadmin.net/phpMyAdmin/{phpmyadmin_version}/phpMyAdmin-{phpmyadmin_version}-all-languages.tar.gz' ) preFlightsChecks.call(command, self.distro, f'[download_install_phpmyadmin] {phpmyadmin_version}', command, 1, 0, os.EX_OSERR) + if not os.path.isfile(tarball) or os.path.getsize(tarball) < 1000000: + raise RuntimeError('phpMyAdmin download failed or file too small') command = 'tar -xzf /usr/local/CyberCP/public/phpmyadmin.tar.gz -C /usr/local/CyberCP/public/' preFlightsChecks.call(command, self.distro, '[download_install_phpmyadmin] extract', command, 1, 0, os.EX_OSERR) - command = 'mv /usr/local/CyberCP/public/phpMyAdmin-*-all-languages /usr/local/CyberCP/public/phpmyadmin' - subprocess.call(command, shell=True) + import glob + extracted = glob.glob('/usr/local/CyberCP/public/phpMyAdmin-*-all-languages') + if not extracted: + extracted = glob.glob('/usr/local/CyberCP/public/phpMyAdmin-*') + if extracted: + if os.path.exists('/usr/local/CyberCP/public/phpmyadmin'): + shutil.rmtree('/usr/local/CyberCP/public/phpmyadmin') + os.rename(extracted[0], '/usr/local/CyberCP/public/phpmyadmin') + else: + command = 'mv /usr/local/CyberCP/public/phpMyAdmin-*-all-languages /usr/local/CyberCP/public/phpmyadmin' + subprocess.call(command, shell=True) + if not os.path.isdir('/usr/local/CyberCP/public/phpmyadmin'): + raise RuntimeError('phpMyAdmin directory was not created after extract/mv') command = 'rm -f /usr/local/CyberCP/public/phpmyadmin.tar.gz' preFlightsChecks.call(command, self.distro, '[download_install_phpmyadmin] cleanup', command, 1, 0, os.EX_OSERR) diff --git a/plogical/upgrade.py b/plogical/upgrade.py index a2b9b7f68..e01bc1bbe 100644 --- a/plogical/upgrade.py +++ b/plogical/upgrade.py @@ -1217,19 +1217,33 @@ module cyberpanel_ols { Upgrade.stdOut(f"Failed to fetch latest phpMyAdmin version, using fallback: {e}", 0) Upgrade.stdOut("Installing phpMyAdmin...", 0) - - command = f'wget -q -O /usr/local/CyberCP/public/phpmyadmin.tar.gz https://files.phpmyadmin.net/phpMyAdmin/{phpmyadmin_version}/phpMyAdmin-{phpmyadmin_version}-all-languages.tar.gz' + + tarball = '/usr/local/CyberCP/public/phpmyadmin.tar.gz' + command = f'wget -q -O {tarball} https://files.phpmyadmin.net/phpMyAdmin/{phpmyadmin_version}/phpMyAdmin-{phpmyadmin_version}-all-languages.tar.gz' Upgrade.executioner_silent(command, f'Download phpMyAdmin {phpmyadmin_version}') + if not os.path.isfile(tarball) or os.path.getsize(tarball) < 1000000: + raise RuntimeError('phpMyAdmin download failed or file too small (check files.phpmyadmin.net)') command = 'tar -xzf /usr/local/CyberCP/public/phpmyadmin.tar.gz -C /usr/local/CyberCP/public/' Upgrade.executioner_silent(command, 'Extract phpMyAdmin') - command = 'mv /usr/local/CyberCP/public/phpMyAdmin-*-all-languages /usr/local/CyberCP/public/phpmyadmin' - subprocess.call(command, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + # Move extracted dir to phpmyadmin (support phpMyAdmin-X.Y.Z-all-languages or similar) + import glob + extracted = glob.glob('/usr/local/CyberCP/public/phpMyAdmin-*-all-languages') + if not extracted: + extracted = glob.glob('/usr/local/CyberCP/public/phpMyAdmin-*') + if extracted: + if os.path.exists('/usr/local/CyberCP/public/phpmyadmin'): + shutil.rmtree('/usr/local/CyberCP/public/phpmyadmin') + os.rename(extracted[0], '/usr/local/CyberCP/public/phpmyadmin') + else: + Upgrade.executioner('mv /usr/local/CyberCP/public/phpMyAdmin-*-all-languages /usr/local/CyberCP/public/phpmyadmin', 0) command = 'rm -f /usr/local/CyberCP/public/phpmyadmin.tar.gz' Upgrade.executioner_silent(command, 'Cleanup phpMyAdmin tar.gz') - + + if not os.path.isdir('/usr/local/CyberCP/public/phpmyadmin'): + raise RuntimeError('phpMyAdmin directory was not created after extract/mv') Upgrade.stdOut("phpMyAdmin installation completed.", 0) ## Write secret phrase @@ -1291,6 +1305,11 @@ $cfg['Servers'][$i]['LogoutURL'] = 'phpmyadminsignin.php?logout'; except: pass + command = 'chown -R lscpd:lscpd /usr/local/CyberCP/public/phpmyadmin' + Upgrade.executioner_silent(command, 'chown phpMyAdmin') + command = 'chown -R lscpd:lscpd /usr/local/CyberCP/public/phpmyadmin/tmp' + Upgrade.executioner_silent(command, 'chown phpMyAdmin tmp') + os.chdir(cwd) except Exception as e: diff --git a/plogical/versionFetcher.py b/plogical/versionFetcher.py index 43c1994d9..87aaf05a2 100644 --- a/plogical/versionFetcher.py +++ b/plogical/versionFetcher.py @@ -61,6 +61,8 @@ class VersionFetcher: # Clean version string (remove 'v' prefix if present) version = re.sub(r'^v', '', version) + # Normalize component-specific tag formats (e.g. phpMyAdmin uses RELEASE_5_2_3) + version = VersionFetcher._normalize_version(component, version) if version and VersionFetcher._is_valid_version(version): logging.info(f"Successfully fetched {component} version: {version}") @@ -89,6 +91,21 @@ class VersionFetcher: versions[component] = VersionFetcher.get_latest_version(component) return versions + @staticmethod + def _normalize_version(component: str, version: str) -> str: + """ + Normalize tag to x.y.z format. phpMyAdmin uses RELEASE_5_2_3 or 5_2_3. + """ + if not version: + return version + # RELEASE_5_2_3 or 5_2_3 -> 5.2.3 + if 'RELEASE_' in version.upper() or (component == 'phpmyadmin' and '_' in version and '.' not in version): + normalized = re.sub(r'^RELEASE_', '', version, flags=re.IGNORECASE) + normalized = normalized.replace('_', '.') + if re.match(r'^\d+\.\d+\.\d+', normalized): + return normalized + return version + @staticmethod def _is_valid_version(version: str) -> bool: """