<?php 

// Quick diagnostics to find why PHP cannot create files/folders when served by a webserver.

function kv($k, $v) { echo str_pad($k . ':', 25) . $v . PHP_EOL; }

kv('PHP SAPI', php_sapi_name());
kv('PHP version', phpversion());
kv('Current working dir', getcwd());
kv('__DIR__', __DIR__);
kv('Script owner (get_current_user)', get_current_user());

// Current PHP process user (who PHP is running as)
if (function_exists('posix_geteuid') && function_exists('posix_getpwuid')) {
    $processUser = posix_getpwuid(posix_geteuid());
    kv('PHP process user', '"' . $processUser['name'] . '"' ?? 'unknown');
    kv('PHP process uid', posix_geteuid());
    kv('PHP process gid', posix_getegid());
    if (function_exists('posix_getgroups')) {
        kv('PHP process groups', implode(', ', posix_getgroups()));
    }
} elseif (PHP_OS_FAMILY === 'Windows') {
    // On Windows, try whoami command
    $whoami = @shell_exec('whoami');
    kv('PHP process user (whoami)', $whoami ? trim($whoami) : 'n/a');
} else {
    // Fallback: try shell command
    $whoami = @shell_exec('whoami 2>/dev/null') ?: @shell_exec('id -un 2>/dev/null');
    kv('PHP process user', $whoami ? trim($whoami) : 'n/a (posix not available)');
}

$scriptPath = realpath(__DIR__ . DIRECTORY_SEPARATOR . basename(__FILE__));
kv('Script path', $scriptPath ?: 'unknown');

$ownerId = @fileowner($scriptPath);
kv('Script owner id', $ownerId === false ? 'n/a' : $ownerId);

if ($ownerId !== false && function_exists('posix_getpwuid')) {
    $pw = posix_getpwuid($ownerId);
    kv('Script owner name (posix)', $pw['name'] ?? json_encode($pw));
}

$dir = __DIR__;

// perms formatting
function human_perms($file) {
    $p = @fileperms($file);
    if ($p === false) return 'n/a';
    $info = '';
    // owner
    $info .= (($p & 0x0100) ? 'r' : '-') . (($p & 0x0080) ? 'w' : '-') . (($p & 0x0040) ?
        (($p & 0x0800) ? 's' : 'x') : (($p & 0x0800) ? 'S' : '-'));
    // group
    $info .= (($p & 0x0020) ? 'r' : '-') . (($p & 0x0010) ? 'w' : '-') . (($p & 0x0008) ?
        (($p & 0x0400) ? 's' : 'x') : (($p & 0x0400) ? 'S' : '-'));
    // world
    $info .= (($p & 0x0004) ? 'r' : '-') . (($p & 0x0002) ? 'w' : '-') . (($p & 0x0001) ?
        (($p & 0x0200) ? 't' : 'x') : (($p & 0x0200) ? 'T' : '-'));
    return $info . ' (' . decoct($p & 0777) . ')';
}

kv('Directory perms', human_perms($dir));
kv('is_readable(dir)', is_readable($dir) ? 'yes' : 'no');
kv('is_writable(dir)', is_writable($dir) ? 'yes' : 'no');

kv('open_basedir', ini_get('open_basedir') ?: '(none)');
kv('disable_functions', ini_get('disable_functions') ?: '(none)');
kv('upload_tmp_dir', ini_get('upload_tmp_dir') ?: sys_get_temp_dir());
kv('sys_get_temp_dir', sys_get_temp_dir());

// Check SELinux/AppArmor availability
if (PHP_OS_FAMILY === 'Linux') {
    $sestatus = trim(@shell_exec('which getenforce >/dev/null 2>&1 && getenforce || true'));
    if ($sestatus !== '') kv('SELinux mode', $sestatus);
}

// Try to actually create a directory and file to see exact failure
$testDir = $dir . DIRECTORY_SEPARATOR . 'php_write_test_' . bin2hex(random_bytes(4));
$createdDir = false;
$createdFile = false;

clearstatcache(true, $testDir);
$errorBefore = error_get_last();

$mk = @mkdir($testDir, 0777);
$err = error_get_last();
if ($mk) {
    $createdDir = true;
    kv('mkdir', 'success: ' . $testDir);
} else {
    kv('mkdir', 'failed');
    if ($err && $err !== $errorBefore) kv('mkdir error', $err['message']);
}

if ($createdDir) {
    $testFile = $testDir . DIRECTORY_SEPARATOR . 'test.txt';
    $w = @file_put_contents($testFile, "test\n");
    $err2 = error_get_last();
    if ($w !== false) {
        $createdFile = true;
        kv('file_put_contents', 'success: ' . $testFile);
        kv('file perms', human_perms($testFile));
    } else {
        kv('file_put_contents', 'failed');
        if ($err2 && $err2 !== $err) kv('write error', $err2['message']);
    }
}

// Cleanup if created
if ($createdFile) @unlink($testFile);
if ($createdDir) @rmdir($testDir);

// Suggestions
echo PHP_EOL . "Suggestions:" . PHP_EOL;
echo "- Ensure the webserver user (www-data, apache, IIS_IUSRS, etc.) can write to the target directory." . PHP_EOL;
echo "- Check open_basedir restrictions and disabled functions in php.ini." . PHP_EOL;
echo "- On Windows, ensure NTFS ACLs grant write permission to the application pool identity." . PHP_EOL;
echo "- On Linux, check SELinux/AppArmor enforced policies and filesystem mount options (noexec/nosuid/remount)." . PHP_EOL;
echo "- If functions are disabled, restart PHP/Apache after changing php.ini and verify using phpinfo()." . PHP_EOL;