403Webshell
Server IP : 188.114.96.3  /  Your IP : 216.73.216.143
Web Server : Apache
System : Linux sv058.home.net.pl 6.8.2 husak_dirty_pages_fix #1 SMP PREEMPT_DYNAMIC Tue Apr 2 22:06:51 CEST 2024 x86_64
User :  ( 3194769)
PHP Version : 8.5.12
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : ON  |  Pkexec : OFF
Directory :  /polana/includes/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /polana/includes/tklm_menu_core.php
<?php
declare(strict_types=1);
/** TKLM Polana Menu EN V2 - safe additive module */
require_once __DIR__ . '/functions.php';

function tm_host(): string {
    $host = strtolower((string)($_SERVER['HTTP_HOST'] ?? ''));
    $host = preg_replace('/:\d+$/', '', $host) ?? '';
    if (str_starts_with($host, 'www.')) $host = substr($host, 4);
    if (!in_array($host, ['polanasmakow.pl', 'mojapolanasmakow.pl'], true)) {
        throw new RuntimeException('Nieznany host Polany: sprawdź domenę.');
    }
    return $host;
}
function tm_api_key(): string {
    $root = dirname(__DIR__);
    $places = [
        $root . '/tklm-translate-private/keys.php',
        $root . '/_tklm_translate/keys.php',
        dirname($root) . '/tklm-translate-private/keys.php',
    ];
    $host = tm_host();
    foreach ($places as $place) {
        if (!is_file($place) || !is_readable($place)) continue;
        $keys = require $place;
        if (!is_array($keys)) continue;
        $key = $keys[$host] ?? null;
        if (!is_string($key) && $host === 'mojapolanasmakow.pl') $key = $keys['MOJA_POLANA_KEY'] ?? null;
        if (!is_string($key) && $host === 'polanasmakow.pl') $key = $keys['POLANA_KEY'] ?? null;
        if (is_string($key) && preg_match('/^[a-f0-9]{48}$/', $key)) return $key;
    }
    throw new RuntimeException('Brak poprawnego klucza tej domeny w keys.php. Sprawdź instrukcję lokalizacji.');
}
function tm_translate_text(string $source): string {
    $source = trim($source);
    if ($source === '' || strlen($source) > 4500) throw new RuntimeException('Tekst pusty lub za długi do automatycznego tłumaczenia.');
    if ($source !== strip_tags($source)) throw new RuntimeException('Automatyczne tłumaczenie HTML wymaga przeglądu ręcznego.');
    if (!extension_loaded('curl')) throw new RuntimeException('PHP cURL nie jest aktywne.');
    $ch = curl_init('https://translate.tklm.pl/translate');
    if ($ch === false) throw new RuntimeException('Nie można uruchomić cURL.');
    $opts = [
        CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query(['q'=>$source,'source'=>'pl','target'=>'en','format'=>'text'],'','&',PHP_QUERY_RFC3986),
        CURLOPT_HTTPHEADER => ['X-TKLM-Translate-Key: ' . tm_api_key(), 'Accept: application/json', 'Content-Type: application/x-www-form-urlencoded'],
        CURLOPT_CONNECTTIMEOUT => 8, CURLOPT_TIMEOUT => 65,
        CURLOPT_FOLLOWLOCATION => false, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_SSL_VERIFYHOST => 2,
    ];
    if (defined('CURLOPT_PROTOCOLS_STR')) $opts[CURLOPT_PROTOCOLS_STR]='https';
    elseif (defined('CURLOPT_PROTOCOLS')) $opts[CURLOPT_PROTOCOLS]=CURLPROTO_HTTPS;
    curl_setopt_array($ch,$opts);
    $raw=curl_exec($ch); $status=(int)curl_getinfo($ch,CURLINFO_RESPONSE_CODE);
    $err=$raw===false?curl_error($ch):''; curl_close($ch);
    if ($raw === false) throw new RuntimeException('Połączenie API nieudane: ' . $err);
    if ($status !== 200) throw new RuntimeException('API zwróciło HTTP ' . $status . ($status===429?' — poczekaj 2 sekundy.':''));
    $obj=json_decode($raw,true);
    if (!is_array($obj) || !is_string($obj['translatedText'] ?? null) || trim($obj['translatedText'])==='') {
        throw new RuntimeException('API nie zwróciło poprawnego translatedText.');
    }
    return trim($obj['translatedText']);
}
function tm_schema(): void {
    db()->exec("CREATE TABLE IF NOT EXISTS tklm_menu_i18n (
        entity VARCHAR(32) NOT NULL, entity_id BIGINT UNSIGNED NOT NULL,
        field_name VARCHAR(40) NOT NULL, lang CHAR(2) NOT NULL DEFAULT 'en',
        source_sha CHAR(64) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
        translated_text MEDIUMTEXT NOT NULL,
        origin ENUM('auto','manual') NOT NULL DEFAULT 'auto',
        updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY(entity,entity_id,field_name,lang)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
}
function tm_entities(): array {
    return [
        'menu_items' => ['name'=>'name_en','description'=>'description_en','allergens'=>'allergens_en'],
        'menu_categories' => ['name'=>'name_en'],
        'menus' => ['intro'=>null,'seo_title'=>null,'seo_description'=>null],
        'pages' => ['title'=>null,'heading'=>null,'seo_title'=>null,'seo_description'=>null],
        'blog_posts' => ['title'=>'title_en','excerpt'=>'excerpt_en'],
    ];
}
function tm_one(string $entity,int $id): array {
    if ($id < 1 || !array_key_exists($entity,tm_entities())) throw new RuntimeException('Nieprawidłowy rekord.');
    // Entity and table names are server-side whitelisted, never interpolated from unchecked input.
    $sql = "SELECT * FROM `$entity` WHERE id=? LIMIT 1";
    $st=db()->prepare($sql); $st->execute([$id]); $row=$st->fetch();
    if (!$row) throw new RuntimeException('Nie znaleziono rekordu.');
    return $row;
}
function tm_i18n_row(string $entity,int $id,string $field): ?array {
    $q=db()->prepare('SELECT * FROM tklm_menu_i18n WHERE entity=? AND entity_id=? AND field_name=? AND lang="en"');
    $q->execute([$entity,$id,$field]);return $q->fetch() ?: null;
}
function tm_task(string $entity,int $id,string $field): array {
    $schema=tm_entities();
    if (!isset($schema[$entity]) || !array_key_exists($field,$schema[$entity])) throw new RuntimeException('Nieznane pole tłumaczenia.');
    $row=tm_one($entity,$id); $dest=$schema[$entity][$field];
    if ($dest!==null && !array_key_exists($dest,$row)) throw new RuntimeException('Brak kolumny EN w aktualnej bazie: '.$dest);
    $source=trim((string)($row[$field] ?? ''));
    $audit=tm_i18n_row($entity,$id,$field);
    $translated=$dest!==null?trim((string)($row[$dest]??'')):trim((string)($audit['translated_text']??''));
    $stale=$audit && $audit['source_sha']!==hash('sha256',$source);
    return compact('entity','id','field','dest','source','translated','stale','audit');
}
function tm_track(string $entity,int $id,string $field,string $source,string $translated,string $origin): void {
    $q=db()->prepare('INSERT INTO tklm_menu_i18n(entity,entity_id,field_name,lang,source_sha,translated_text,origin) VALUES(?,?,?,"en",?,?,?) ON DUPLICATE KEY UPDATE source_sha=VALUES(source_sha),translated_text=VALUES(translated_text),origin=VALUES(origin)');
    $q->execute([$entity,$id,$field,hash('sha256',$source),$translated,$origin]);
}
function tm_auto_one(string $entity,int $id,string $field): array {
    $t=tm_task($entity,$id,$field);
    if ($t['source']==='') return ['skipped'=>true,'why'=>'Puste pole PL'];
    if ($t['translated']!=='') return ['skipped'=>true,'why'=>'Tłumaczenie EN istnieje — nie nadpisuję'];
    $trans=tm_translate_text($t['source']);
    $now=tm_task($entity,$id,$field);
    if ($now['source']!==$t['source'] || $now['translated']!=='') return ['skipped'=>true,'why'=>'Dane zmieniły się podczas tłumaczenia'];
    $dest=$t['dest'];
    db()->beginTransaction();
    try {
        if ($dest!==null) {
            $u=db()->prepare("UPDATE `$entity` SET `$dest`=? WHERE id=? AND `$field`=? AND (`$dest` IS NULL OR TRIM(`$dest` )='')");
            $u->execute([$trans,$id,$t['source']]);
            if ($u->rowCount() !== 1) { db()->rollBack(); return ['skipped'=>true,'why'=>'Zapis anulowany — pole już edytowane']; }
        }
        tm_track($entity,$id,$field,$t['source'],$trans,'auto');
        db()->commit();
    } catch(Throwable $e) {if(db()->inTransaction())db()->rollBack();throw $e;}
    return ['ok'=>true,'translation'=>$trans];
}
function tm_save_en(string $entity,int $id,string $field,string $english): void {
    $t=tm_task($entity,$id,$field);
    $english=trim($english);
    if (strlen($english)>5000) throw new RuntimeException('Wpis jest za długi.');
    if ($t['dest']!==null) {
        $dest=$t['dest'];$u=db()->prepare("UPDATE `$entity` SET `$dest`=? WHERE id=?");$u->execute([$english,$id]);
    }
    tm_track($entity,$id,$field,$t['source'],$english,'manual');
}
function tm_active_menus(): array {
    return db()->query("SELECT id,name,status,menu_type,valid_from,valid_to FROM menus ORDER BY (status='published') DESC,id DESC LIMIT 45")->fetchAll();
}
function tm_menu_rows(int $menuId): array {
    $one=tm_one('menus',$menuId);
    $q=db()->prepare('SELECT * FROM menu_categories WHERE menu_id=? ORDER BY sort_order,id');$q->execute([$menuId]);$categories=$q->fetchAll();
    $q=db()->prepare('SELECT i.* FROM menu_items i JOIN menu_categories c ON c.id=i.category_id WHERE c.menu_id=? ORDER BY c.sort_order,c.id,i.sort_order,i.id');$q->execute([$menuId]);
    $by=[];foreach($q->fetchAll() as $item){$by[(int)$item['category_id']][]=$item;}
    foreach($categories as &$cat) $cat['items']=$by[(int)$cat['id']]??[];
    unset($cat);
    return [$one,$categories];
}
function tm_json(array $data,int $code=200): never {
    http_response_code($code);header('Content-Type: application/json; charset=utf-8');header('Cache-Control: no-store');
    echo json_encode($data,JSON_UNESCAPED_UNICODE|JSON_INVALID_UTF8_SUBSTITUTE);exit;
}

Youez - 2016 - github.com/yon3zu
LinuXploit