$GLOBALS["pnkit_mode"] = "online";$GLOBALS["pnkit_version"] = "2025-01-16T14:58:52+01:00"; /******************************************************************************/ // PORTABLE NKIT // // Usage online: eval (file_get_contents ("https://pnkit.fastsimple.com")); // Usage offline: include "pnkit_main.php"; /******************************************************************************/ // START // Less warnings PHP 8+ if (@!$_SERVER["REMOTE_ADDR"]) $_SERVER["REMOTE_ADDR"] = null; if (@!$GLOBALS["pnkit_data_dir"]) $GLOBALS["pnkit_data_dir"] = null; if (@!$GLOBALS["pnkit_public_cache_dir_internal"]) $GLOBALS["pnkit_public_cache_dir_internal"] = null; if (@!$GLOBALS["pnkit_owner_ip"]) $GLOBALS["pnkit_owner_ip"] = null; if (!function_exists("puuse")) { // Allow multiple loadings $GLOBALS["MS_start"] = microtime(true); register_shutdown_function (function(){register_shutdown_function (function(){ // Executing this code should be the last thing to do $elapsed = microtime(true) - $GLOBALS["MS_start"]; file_put_contents ($GLOBALS['pnkit_data_dir'] . '/profile'.date ("H", time()).'.html', time()." ".$elapsed." ".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']."\n", FILE_APPEND); if (!rand (0, 100)) @unlink ($GLOBALS['pnkit_data_dir'] . '/profile'.date ("H", time() - 6*3600).'.html'); });}); if (@exec('date +%Z')) date_default_timezone_set (timezone_name_from_abbr (exec('date +%Z'))); // Use the Linux OS timezone as PHP timezone /******************************************************************************/ // MODULES function file_get_contents_classic ($url) { $content = @file_get_contents ($url); if (!$content) $content = @file_get_contents (str_replace ("https", "http", $url)); // E.g. Synology PHP does not do https return $content; } function puuse() { global $PUUSE_Modules; $modules = func_get_args(); if (!$modules || $modules==[""]) { if ($PUUSE_Modules["all"] == 'loaded') return; $PUUSE_Modules["all"] = 'loaded'; if ($GLOBALS['pnkit_mode'] == 'online') { $all = unserialize(file_get_contents_classic("https://www.fastsimple.com/pnkit/pnkitweb_loader.php?allmodules=show")); foreach ($all as $module => $php) { if ($PUUSE_Modules[$module] != 'loaded') { $PUUSE_Modules[$module] = 'loaded'; eval($php); } } return; } else { $modules = puuse_allmodules(); } } foreach ($modules as $module) { $module = strtolower($module); if ($PUUSE_Modules[$module] != 'loaded') { $PUUSE_Modules[$module] = 'loaded'; if ($GLOBALS['pnkit_mode'] == 'online') { $php = file_get_contents_classic("https://fastsimple.com/pnkit/pnkitweb_loader.php?module=$module"); eval($php); } else { $pathinfo = pathinfo(__FILE__); include $pathinfo['dirname'] . "/puuse_$module.php"; } } } } function puuse_allmodules() { if ($GLOBALS['pnkit_mode'] == 'online') { $list = unserialize(file_get_contents_classic("https://www.fastsimple.com/pnkit/pnkitweb_loader.php?modulelist=show")); return $list; } else { $pathinfo = pathinfo(__FILE__); $d = dir($pathinfo["dirname"]); while (false !== ($entry = $d->read())) { if (strstr($entry, "puuse_")) { $list[] = N_KeepAfter(N_KeepBefore($entry, ".php"), "puuse_"); } } $d->close(); return $list; } } function muuse_register ($module, $relative_path) { if (!strlen (file_get_contents ($_SERVER['DOCUMENT_ROOT'].$relative_path))) die ("muuse_register: Fatal Error: Cannot find ".$_SERVER['DOCUMENT_ROOT'].$relative_path); PMB_Save ("pnkit_modules", $module, $relative_path); muuse_show (); } function muuse_remove ($module) { PMB_Delete ("pnkit_modules", $module); muuse_show (); } function muuse_show ($as_title=false) { foreach (PMB_AllKeys ("pnkit_modules") as $module) { if ($as_title) { $content .= "[$module] ".PMB_Load ("pnkit_modules", $module)."\n"; } else { $content .= "$module ".PMB_Load ("pnkit_modules", $module)."
"; } } $content .= 'Add modules with muuse_register ($module, $relative_path)'."\n".'Remove with muuse_remove ($module)'; if (!$as_title) echo $content; else return $content; } function muuse () { global $MUUSE_Modules; $modules = func_get_args(); if (!$modules || $modules==[""]) { puuse(); // One call to load absolutely everything $modules = PMB_AllKeys ("pnkit_modules"); } foreach ($modules as $module) { $module = strtolower($module); if ($MUUSE_Modules[$module] != 'loaded') { $MUUSE_Modules[$module] = 'loaded'; include $_SERVER['DOCUMENT_ROOT'].PMB_Load ("pnkit_modules", $module); } } } /******************************************************************************/ // BACKGROUND PROCESSING function N_MultiExec ($code, $input=array()) { $handle = N_GUID(); PMB_Save ("exec_now_code", $handle, $code); PMB_Save ("exec_now_input", $handle, $input); $GLOBALS["N_MultiExec"][$handle]["code"] = $code; $GLOBALS["N_MultiExec"][$handle]["input"] = $input; return $handle; } function N_MultiResult ($handle, $timeout = 5) { foreach ($GLOBALS["N_MultiExec"] as $h => $state) { if (!$state["executed"]) { $urls[] = ($_SERVER["REQUEST_SCHEME"] ? $_SERVER["REQUEST_SCHEME"] : "http") . "://" . $_SERVER["HTTP_HOST"] . $_SERVER["SCRIPT_NAME"] . "?pnkitexecnow=$h"; $GLOBALS["N_MultiExec"][$h]["executed"] = true; } } if ($urls) foreach (N_MultiGetPage ($urls, $timeout) as $url => $response) { $h = N_KeepAfter ($url, "now="); $result = unserialize ($response["content"]); if ($result["status"]=="ok") { $GLOBALS["N_MultiExec"][$h]["completed"] = true; $GLOBALS["N_MultiExec"][$h]["output"] = $result["output"]; } } if (!$GLOBALS["N_MultiExec"][$handle]["completed"]) { $input = $GLOBALS["N_MultiExec"][$handle]["input"]; eval ($GLOBALS["N_MultiExec"][$handle]["code"]); $GLOBALS["N_MultiExec"][$handle]["completed"] = true; $GLOBALS["N_MultiExec"][$handle]["output"] = $output; } return $GLOBALS["N_MultiExec"][$handle]["output"]; } function N_MultiGetPage ($urls, $timeout = 5) { $multiHandle = curl_multi_init(); $curlHandles = []; $headers = array(); $headers[] = "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"; // $headers[] = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"; $headers[] = "Cache-Control: max-age=0"; $headers[] = "Connection: keep-alive"; $headers[] = "Keep-Alive: 300"; $headers[] = "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7"; $headers[] = "Accept-Language: en-us,en;q=0.5"; $headers[] = "Pragma: "; foreach ($urls as $url) { $handle = curl_init(); curl_setopt($handle, CURLOPT_URL, $url); curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); curl_setopt($handle, CURLOPT_TIMEOUT, $timeout); curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, min (5, $timeout)); curl_setopt($handle, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"); // curl_setopt($handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"); curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($handle, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($handle, CURLOPT_AUTOREFERER, true); curl_setopt($handle, CURLOPT_COOKIESESSION, true); curl_setopt($handle, CURLOPT_HTTPHEADER, $headers); curl_multi_add_handle ($multiHandle, $handle); $curlHandles[] = $handle; } $active = null; do { $mrc = curl_multi_exec ($multiHandle, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM || $active); $results = []; foreach ($curlHandles as $handle) { $url = curl_getinfo ($handle, CURLINFO_EFFECTIVE_URL); $results[$url] = [ 'content' => curl_multi_getcontent ($handle), 'response_code' => curl_getinfo ($handle, CURLINFO_HTTP_CODE), ]; curl_multi_remove_handle ($multiHandle, $handle); curl_close ($handle); } curl_multi_close($multiHandle); return $results; } function N_HandleExecNow ($exec_now_key) { $code = PMB_Load("exec_now_code", $exec_now_key); $input = PMB_Load("exec_now_input", $exec_now_key); eval ($code); PMB_Flush(); echo serialize (array ("status"=>"ok", "output"=>$output)); PMB_Delete("exec_now_code", $exec_now_key); PMB_Delete("exec_now_input", $exec_now_key); } function N_ExecInBackground ($code, $input = NULL) { global $exec_in_background_code, $exec_in_background_input; if (!$exec_in_background_code) register_shutdown_function('N_FlushExecInBackground'); $exec_in_background_code[] = $code; $exec_in_background_input[] = $input; } function N_FlushExecInBackground() { global $exec_in_background_code, $exec_in_background_input; if ($exec_in_background_code) { $key = N_GUID(); PMB_Save("exec_in_background_code", $key, $exec_in_background_code); PMB_Save("exec_in_background_input", $key, $exec_in_background_input); $url = ($_SERVER["REQUEST_SCHEME"] ? $_SERVER["REQUEST_SCHEME"] : "http") . "://" . $_SERVER["HTTP_HOST"] . $_SERVER["SCRIPT_NAME"] . "?pnkitexec&key=$key"; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT_MS, 100); // optimized value is 50, we use 100 to reduce chance of failure curl_exec($ch); $exec_in_background_code = $exec_in_background_input = array(); } } function N_HandleExecInBackground ($exec_in_background_key) { ignore_user_abort(true); $exec_in_background_codes = PMB_Load("exec_in_background_code", $exec_in_background_key); $exec_in_background_inputs = PMB_Load("exec_in_background_input", $exec_in_background_key); if ($exec_in_background_codes) foreach ($exec_in_background_codes as $exec_in_background_index => $code) { $input = $exec_in_background_inputs[$exec_in_background_index]; eval($code); PMB_Flush(); } PMB_Delete("exec_in_background_code", $exec_in_background_key); PMB_Delete("exec_in_background_input", $exec_in_background_key); } function N_ExecInBackgroundBacklog() { $now = time(); $keys = PMB_Query("exec_in_background_code"); foreach ($keys as $key) { N_HandleExecInBackground($key); if (time() - $now > 300) break; } } /******************************************************************************/ // ASSETS function N_MimeMap() { return array('css' => 'text/css', 'js' => 'text/javascript', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png', 'woff' => 'font/woff', 'woff2' => 'font/woff2', 'webp' => 'image/webp'); } function N_ImageEmbedURL ($filename, $content) { $mimetype = N_MimeMap()[pathinfo($filename, PATHINFO_EXTENSION)]; return "data:$mimetype;base64,".base64_encode ($content); } function N_AssetContent ($subpath) { return N_Cache (24, "file_get_contents", "https://fastsimple.com/pnkit/$subpath"); } function N_Asset($subpath = '') { if ($GLOBALS["N_AssetRelPath"]) { return $GLOBALS["N_AssetRelPath"].$subpath; } if ($GLOBALS['pnkit_mode'] == 'online') { $v = "v".PMB_Load ("pnkit", "last_pnkit_code_save"); $rp = $_SERVER['SCRIPT_NAME'] . "?v=$v&pnkitassets=/"; } else { $pathinfo = pathinfo(str_replace('./', '/', N_getRelativePath($_SERVER['DOCUMENT_ROOT'], __FILE__))); $rp = $pathinfo['dirname'] . '/'; } return "$rp$subpath"; } function N_DynAsset($mime, $asset_data) { if (strlen($asset_data) > 1024) { $ext = array_search($mime, N_MimeMap()); if (!$ext) $ext = "txt"; $asset_id = md5($asset_data) . ".$ext"; if (!N_CacheAssetExists($asset_id)) N_CacheAssetSave($asset_id, $asset_data); return N_CacheAsset($asset_id); } else { return $_SERVER['SCRIPT_NAME'] . '?pnkitdynasset&mime=' . urlencode($mime) . '&b64_data=' . urlencode(base64_encode($asset_data)); } } function N_CacheAsset($asset_id) { return $GLOBALS["pnkit_public_cache_dir_external"] . "/$asset_id"; } function N_CacheAssetExists($asset_id) { return @file_exists($GLOBALS["pnkit_public_cache_dir_internal"] . "/$asset_id"); } function N_CacheAssetSave($asset_id, $asset_data) { file_put_contents($GLOBALS["pnkit_public_cache_dir_internal"] . "/$asset_id", $asset_data); } function N_CacheAssetLoad($asset_id) { return file_get_contents($GLOBALS["pnkit_public_cache_dir_internal"] . "/$asset_id"); } function N_CacheAssetDelete($asset_id) { @unlink($GLOBALS["pnkit_public_cache_dir_internal"] . "/$asset_id"); } function N_PNFavIcon($minilabel = 'PN', $back="rgb(0,0,128)", $front = "white") { if ($minilabel=="|") { return ''; } else if ($minilabel=="cube") { return ''; } puuse("ui"); $icon = ''; $icon .= ''; return $icon; } /******************************************************************************/ // PORTABLE NKIT DATABASE FUNCTIONS function PMB_Merge ($table, $key, $merge) { $object = PMB_Load ($table, $key); if (is_array ($object) && is_array ($merge)) { foreach ($merge as $k => $v) { $object[$k] = $v; } } else { $object = $merge; } PMB_Save ($table, $key, $object); } function PMB_LoadTable ($table, $sort = '$key') { $result = array(); $keys = PMB_Query($table, '1==1', $sort); foreach ($keys as $key => $dummy) { $result[$key] = PMB_Load ($table, $key); } return $result; } function &PMB_Ref($table, $key) { if (!$table) trigger_error ("PMB_Ref($table, $key) needs a table ($table)", E_USER_ERROR); if (!$key) trigger_error ("PMB_Ref($table, $key) needs a key ($key)", E_USER_ERROR); global $PMB_FlushOnExit; if (!$PMB_FlushOnExit) { register_shutdown_function('PMB_FlushOnExit'); $PMB_FlushOnExit = true; } global $pmb_inmemorycache, $pmb_inmemorycopy; if ($pmb_inmemorycache[$table][$key]) return $pmb_inmemorycache[$table][$key]; $pmb_inmemorycache[$table][$key] = PMB_Load($table, $key); $pmb_inmemorycopy[$table][$key] = $pmb_inmemorycache[$table][$key]; return $pmb_inmemorycache[$table][$key]; } function PMB_Flush() { global $pmb_inmemorycache, $pmb_inmemorycopy; if (is_array($pmb_inmemorycache)) { foreach ($pmb_inmemorycache as $table => $allrecords) { foreach ($allrecords as $key => $object) { if ($object != $pmb_inmemorycopy[$table][$key]) { PMB_Save($table, $key, $object); $pmb_inmemorycopy[$table][$key] = $object; } } } } } function PMB_FlushOnExit () { PMB_Flush(); } function PMB_FlushAndClean() { global $pmb_inmemorycache, $pmb_inmemorycopy; PMB_Flush(); $pmb_inmemorycache = $pmb_inmemorycopy = array(); } function PMB_Query($table, $constraint = '1==1', $sort = '$key') { if (!$constraint) $constraint = '1==1'; if (!$sort) $sort = '$key'; $GLOBALS["calls"]["PMB_Query"]++; $GLOBALS["calllog"][] = "PMB_Query($table, $constraint, $sort)"; $result = array(); $keys = PMB_AllKeys($table); foreach ($keys as $key) { $record = PMB_Load($table, $key); $match = false; eval('$match = ' . $constraint . ';'); if ($match) { eval('$result[$key] = ' . $sort . ';'); } } asort($result); return $result; } function PMB_Save($table, $key, $object) { if (!$table) die("Fatal Error: PMB_Save needs a table ($key)"); if (!$key) die("Fatal Error: PMB_Save needs a key ($table)"); $GLOBALS["calls"]["PMB_Save"]++; $GLOBALS["calllog"][] = "PMB_Save($table, $key, ...)"; $gz = function_exists("gzuncompress") && (substr($table, -3) == "_gz"); $ig = function_exists("igbinary_unserialize") && (substr($table, -3) == "_ig"); $key = N_Encode64(strtolower($key)); if (!file_exists($GLOBALS['pnkit_data_dir'] . "/$table")) { mkdir($GLOBALS['pnkit_data_dir'] . "/$table"); } $fd = fopen($GLOBALS['pnkit_data_dir'] . "/$table/{$key}_tmp", 'w'); if ($ig) { fwrite($fd, igbinary_serialize($object)); } else { if ($gz) { fwrite($fd, gzcompress(serialize($object))); } else { fwrite($fd, serialize($object)); } } fclose($fd); @rename($GLOBALS['pnkit_data_dir'] . "/$table/{$key}_tmp", $GLOBALS['pnkit_data_dir'] . "/$table/$key"); } function PMB_TimeStamp($table, $key) { $GLOBALS["calls"]["PMB_TimeStamp"]++; $GLOBALS["calllog"][] = "PMB_TimeStamp($table, $key)"; $key = N_Encode64(strtolower($key)); return filemtime($GLOBALS['pnkit_data_dir'] . "/$table/$key"); } function PMB_Exists($table, $key) { $GLOBALS["calls"]["PMB_Exists"]++; $GLOBALS["calllog"][] = "PMB_Exists($table, $key)"; $key = N_Encode64(strtolower($key)); return file_exists($GLOBALS['pnkit_data_dir'] . "/$table/$key"); } function PMB_LastUpdate($table, $key) { $file = $GLOBALS['pnkit_data_dir'] . "/$table/" . N_Encode64(strtolower($key)); if (filesize($file)) { return filemtime($file); } return false; } function PMB_Load($table, $key) { $GLOBALS["calls"]["PMB_Load"]++; $GLOBALS["calllog"][] = "PMB_Load($table, $key)"; $gz = function_exists("gzuncompress") && (substr($table, -3) == "_gz"); $ig = function_exists("igbinary_unserialize") && (substr($table, -3) == "_ig"); global $PMB_Load; $thekey = $key; ++$PMB_Load; $key = N_Encode64(strtolower($key)); @$fd = fopen($GLOBALS['pnkit_data_dir'] . "/$table/$key", 'r'); if (!$fd) { return null; } if (filesize($GLOBALS['pnkit_data_dir'] . "/$table/$key")) { $rawdata = fread($fd, filesize($GLOBALS['pnkit_data_dir'] . "/$table/$key")); fclose($fd); if (strlen($rawdata)) { if ($ig) { $object = igbinary_unserialize($rawdata); } else { if ($gz) { $object = unserialize(gzuncompress($rawdata)); } else { $object = unserialize($rawdata); } } } return $object; } else { return null; } } function PMB_DeleteTable($table, $please="") { if ($please!="please") throw new Error("PMB_DeleteTable requires 'please' as second parameter"); $keys = PMB_AllKeys ($table); foreach ($keys as $key) { PMB_Delete ($table, $key); } @rmdir($GLOBALS['pnkit_data_dir'] . "/$table"); } function PMB_Delete($table, $key) { $GLOBALS["calls"]["PMB_Delete"]++; $GLOBALS["calllog"][] = "PMB_Delete($table, $key)"; $key = N_Encode64(strtolower($key)); @unlink($GLOBALS['pnkit_data_dir'] . "/$table/$key"); } function PMB_AllKeys($table) { $GLOBALS["calls"]["PMB_AllKeys"]++; $GLOBALS["calllog"][] = "PMB_AllKeys($table)"; $dir = $GLOBALS['pnkit_data_dir'] . "/$table/"; $result = array(); if (is_dir($dir)) { if ($dh = opendir($dir)) { while (($file = readdir($dh)) !== false) { if (is_file($dir . $file) && !strstr ($file, "_tmp")) { $result[] = N_Decode64($file); } } closedir($dh); } } sort($result); return $result; } function PMB_TableBytes($table) { $GLOBALS["calls"]["PMB_TableBytes"]++; $GLOBALS["calllog"][] = "PMB_TableBytes($table)"; $dir = $GLOBALS['pnkit_data_dir'] . "/$table/"; if (is_dir($dir)) { if ($dh = opendir($dir)) { while (($file = readdir($dh)) !== false) { if (is_file($dir . $file)) { $result += filesize($dir . $file); } } closedir($dh); } } return $result; } function PMB_AllTables() { $GLOBALS["calls"]["PMB_AllTables"]++; $GLOBALS["calllog"][] = "PMB_AllTables()"; $dir = $GLOBALS['pnkit_data_dir'] . "/"; $result = array(); if (is_dir($dir)) { if ($dh = opendir($dir)) { while (($subdir = readdir($dh)) !== false) { if (is_dir($dir . $subdir) && $subdir != "." && $subdir != ".." && substr($subdir, 0, 4) != "int_") { $result[] = $subdir; } } closedir($dh); } } sort($result); return $result; } function PMB_Check($type = "all") { if ($type == "all" || $type == "gz") { $tables = PMB_AllTables(); foreach ($tables as $table) { if (substr($table, -3) == "_gz") { $keys = PMB_AllKeys($table); $ctr = 0; echo "
$table: " . N_Count ($keys) . "
"; echo str_pad('', 4096); flush(); foreach ($keys as $key) { $file = N_Encode64(strtolower($key)); @$fd = fopen($GLOBALS['pnkit_data_dir'] . "/$table/$file", 'r'); if (!$fd) { echo "ERROR: No file for key: $key ($file)
"; } else { if (!filesize($GLOBALS['pnkit_data_dir'] . "/$table/$file")) { echo "ERROR: No data (empty file) for key: $key ($file)
"; } else { $rawdata = fread($fd, filesize($GLOBALS['pnkit_data_dir'] . "/$table/$file")); fclose($fd); if (!N_ValidGZ($rawdata)) { echo "ERROR: No valid data (gzuncompress data error) for key: $key ($file)
"; } } } ++$ctr; if ($ctr % 1000 == 0) { echo "Progress $ctr/" . N_Count ($keys) . "
"; echo str_pad('', 4096); flush(); } } echo "Progress $ctr/" . N_Count ($keys) . "
"; } } } if ($type == "all" || $type == "ig") { $tables = PMB_AllTables(); foreach ($tables as $table) { if (substr($table, -3) == "_ig") { $keys = PMB_AllKeys($table); $ctr = 0; echo "
$table: " . N_Count ($keys) . "
"; echo str_pad('', 4096); flush(); foreach ($keys as $key) { $file = N_Encode64(strtolower($key)); @$fd = fopen($GLOBALS['pnkit_data_dir'] . "/$table/$file", 'r'); if (!$fd) { echo "ERROR: No file for key: $key ($file)
"; } else { if (!filesize($GLOBALS['pnkit_data_dir'] . "/$table/$file")) { echo "ERROR: No data (empty file) for key: $key ($file)
"; } else { $rawdata = fread($fd, filesize($GLOBALS['pnkit_data_dir'] . "/$table/$file")); fclose($fd); if (!igbinary_unserialize($rawdata)) { echo "WARNING: No data for key: $key ($file)
"; } } } ++$ctr; if ($ctr % 1000 == 0) { echo "Progress $ctr/" . N_Count ($keys) . "
"; echo str_pad('', 4096); flush(); } } echo "Progress $ctr/" . N_Count ($keys) . "
"; } } } if ($type == "all" || $type == "std") { $tables = PMB_AllTables(); foreach ($tables as $table) { if (substr($table, -3) != "_ig" && substr($table, -3) != "_gz") { $keys = PMB_AllKeys($table); $ctr = 0; echo "
$table: " . N_Count ($keys) . "
"; echo str_pad('', 4096); flush(); foreach ($keys as $key) { $file = N_Encode64(strtolower($key)); @$fd = fopen($GLOBALS['pnkit_data_dir'] . "/$table/$file", 'r'); if (!$fd) { echo "ERROR: No file for key: $key ($file)
"; } else { if (!filesize($GLOBALS['pnkit_data_dir'] . "/$table/$file")) { echo "ERROR: No data (empty file) for key: $key ($file)
"; } else { $rawdata = fread($fd, filesize($GLOBALS['pnkit_data_dir'] . "/$table/$file")); fclose($fd); if (!unserialize($rawdata)) { echo "WARNING: No data for key: $key ($file)
"; } } } ++$ctr; if ($ctr % 1000 == 0) { echo "Progress $ctr/" . N_Count ($keys) . "
"; echo str_pad('', 4096); flush(); } } echo "Progress $ctr/" . N_Count ($keys) . "
"; } } } } /******************************************************************************/ // PHP 5.4 support if (!function_exists("array_key_last")){ function array_key_last ($array) { $array = NA ($array); end ($array); return key ($array); } } /******************************************************************************/ // 1001 USEFUL SMALL FUNCTIONS function N_AccurateTime () { foreach (["time.cloudflare.com", "pool.ntp.org", "time.google.com", "time.apple.com"] as $timehost) { if ($socket = @fsockopen("udp://$timehost", 123, $errno, $errstr, 1)) { stream_set_timeout ($socket, 1); fwrite ($socket, "\010" . str_repeat("\0", 47)); $response = fread ($socket, 48); fclose($socket); if ($response && strlen($response) === 48) { $data = unpack('N12', $response); $timestamp = sprintf('%u', $data[9]); $timestamp -= 2208988800; // Convert NTP time to Unix timestamp (1900-01-01) if ($timestamp > 1730000000) return $timestamp; } } } $response = @json_decode (@file_get_contents ("https://timeapi.io/api/time/current/zone?timeZone=Europe/Amsterdam"), true); if ($response && isset($response['dateTime'])) { $dateTime = new DateTime($response['dateTime'], new DateTimeZone('Europe/Amsterdam')); $timestamp = $dateTime->getTimestamp(); if ($timestamp > 1730000000) return $timestamp; } return time(); } function N_SemaClaim ($sema, $wait=15, $seconds=7200) { for ($i=0; $i<=$wait*10; $i++) { if (PMB_Load ("semaphores", $sema) + $seconds < time()) { PMB_Save ("semaphores", $sema, time()); return true; } usleep (100000); } return false; } function N_SemaRelease ($sema) { PMB_Save ("semaphores", $sema, 0); } function N_SemaPulse ($sema) { PMB_Save ("semaphores", $sema, time()); } function N_ReplaceDiacritics ($string) { $originalCharacters = array( 'ä', 'ë', 'ï', 'ö', 'ü', 'á', 'é', 'í', 'ó', 'ú', 'ý', 'à', 'è', 'ì', 'ò', 'ù', 'â', 'ê', 'î', 'ô', 'û', 'ã', 'ñ', 'õ', 'å', 'æ', 'ç', 'œ', 'Ä', 'Ë', 'Ï', 'Ö', 'Ü', 'Á', 'É', 'Í', 'Ó', 'Ú', 'Ý', 'À', 'È', 'Ì', 'Ò', 'Ù', 'Â', 'Ê', 'Î', 'Ô', 'Û', 'Ã', 'Ñ', 'Õ', 'Å', 'Æ', 'Ç', 'Œ' ); $replacementCharacters = array( 'a', 'e', 'i', 'o', 'u', 'a', 'e', 'i', 'o', 'u', 'y', 'a', 'e', 'i', 'o', 'u', 'a', 'e', 'i', 'o', 'u', 'a', 'n', 'o', 'a', 'ae', 'c', 'oe', 'A', 'E', 'I', 'O', 'U', 'A', 'E', 'I', 'O', 'U', 'Y', 'A', 'E', 'I', 'O', 'U', 'A', 'E', 'I', 'O', 'U', 'A', 'N', 'O', 'A', 'AE', 'C', 'OE' ); return str_replace($originalCharacters, $replacementCharacters, $string); } function N_SecureMultiRand ($amount, $min, $max, $type="test") { $microtime = microtime(true); $slot = (int)($microtime/(24*3600)); $seed_index = 1 + NN (PMB_Load ("multi_rand", "seed_index")); PMB_Save ("multi_rand", "seed_index", $seed_index); $mt_seed = ((int)$microtime * $amount * $seed_index) % 2147483647; mt_srand ($mt_seed, MT_RAND_MT19937); for ($i = 0; $i < $amount; $i++) $result[$i] = mt_rand($min, $max); $result ["type"] = $type; $result ["min"] = $min; $result ["max"] = $max; $result ["seed_index"] = $seed_index; $result ["microtime"] = $microtime; $result ["mt_seed"] = $mt_seed; $log = PMB_Load ("multi_rand", $slot); $log[] = $result; PMB_Save ("multi_rand", $slot, $log); return $result; } function N_ContainsAny ($haystack, $needle) { // https://www.fastsimple.com/pnkit/example_online.php?pnkit=eval&saved_code=684c346e5f98dfbad845ef9a8b5ffdaa if (is_array ($haystack)) { foreach ($haystack as $h) if (N_ContainsAny ($h, $needle)) return true; return false; } if (is_array ($needle)) { foreach ($needle as $n) if (false !== stripos($haystack, $n)) return true; return false; } else { return false !== stripos($haystack,$needle); } } function N_ArrayToTable ($array, $table_spacing ='cellpadding="5" cellspacing="0"', $table_cell_properties='style="border: 1px solid; border-color:#eee;"') { if (!is_array($array)) return N_ArrayToTable ([NS($array)=>""]); $table = "\n"; foreach ($array as $key => $value) { $table .= "\n"; } $table .= "
".htmlentities ($key).""; if (is_array($value)) { $table .= N_ArrayToTable ($value, $table_spacing, $table_cell_properties); } else { $table .= "".str_replace ([" ", "\n"], [" ", "
"], htmlentities ($value))."
"; } $table .= "
\n"; return $table; } function N_Ping ($host) { if (gethostbyname($host) == gethostbyname ("does.not.exist")) return false; $output = shell_exec("ping -c 1 -w 3 ".gethostbyname($host)); if (strpos($output, '1 packets transmitted, 1 received') !== false) return true; return false; } function N_SafeEval ($code_aesvrun, $inputvars_aesvrun=array(), $outputvar_aesvrun=null) { extract ($inputvars_aesvrun, EXTR_SKIP); eval ("$code_aesvrun;"); return $$outputvar_aesvrun; } function N_ShowMS ($ms) { if ($ms > 2999) { return number_format(round ($ms / 1000))." s"; } else if ($ms > 999) { return number_format($ms / 1000, 1)." s"; } else { return number_format(round ($ms))." ms"; } } function N_ParseURL ($url) { $result = parse_url ($url); if ($result["query"]) { parse_str ($result["query"], $query); $result["query"] = $query; } return $result; } function N_GenerateURL ($parts) { if (is_array ($parts["query"])) $parts["query"] = http_build_query ($parts["query"]); return (isset($parts['scheme']) ? "{$parts['scheme']}:" : '') . ((isset($parts['user']) || isset($parts['host'])) ? '//' : '') . (isset($parts['user']) ? "{$parts['user']}" : '') . (isset($parts['pass']) ? ":{$parts['pass']}" : '') . (isset($parts['user']) ? '@' : '') . (isset($parts['host']) ? "{$parts['host']}" : '') . (isset($parts['port']) ? ":{$parts['port']}" : '') . (isset($parts['path']) ? "{$parts['path']}" : '') . (isset($parts['query']) ? "?{$parts['query']}" : '') . (isset($parts['fragment']) ? "#{$parts['fragment']}" : ''); } function N_Setting ($default=NULL, $o1=NULL, $o2=NULL, $o3=NULL, $o4=NULL, $o5=NULL) { $setting = $default; if ($o5) $setting = $o5; if ($o4) $setting = $o4; if ($o3) $setting = $o3; if ($o2) $setting = $o2; if ($o1) $setting = $o1; return $setting; } function N_Expand ($old, $separator, $new, $prefix="") { if ($old) { if ($prefix && substr ($old, 0, strlen($prefix)) != $prefix) $old = "$prefix$old"; return "$old$separator$prefix$new"; } return $new; } function N_First ($old, $new) { if ($old) return $old; return $new; } function N_Last ($old, $new) { if ($new) return $new; return $old; } function N_BlankPNG () { return "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII="; } function N_RemoveEmptyValues ($array) { foreach ($array as $key => $value) { if (is_array ($value)) { $array[$key] = N_RemoveEmptyValues ($value); } if (empty ($value)) { unset ($array[$key]); } } return $array; } function N_FastMD5File ($file) { $file = realpath ($file); if (file_exists ($file)) { $fm = filemtime ($file); $data = NA (PMB_Load ("fast_md5_file", $file)); if ($fm != $data["filemtime"]) { $data["filemtime"] = $fm; $data["md5"] = md5_file ($file); if ($data["md5"] != md5("")) PMB_Save ("fast_md5_file", $file, $data); } return $data["md5"]; } else { return md5 (""); } } function N_RecursiveKeySort (&$array) { if (!is_array ($array)) return $array; foreach ($array as &$value) { if (is_array($value)) N_RecursiveKeySort ($value); } return ksort($array); } function N_ValidGZ($x) { return @gzuncompress($x) !== false; } if (!function_exists("NN")) { function NN ($me) { if (is_numeric ($me) || floatval($me)) { if (($theint = intval($me)) != ($thefloat = floatval($me))) { return $thefloat; } else { return $theint; } } return 0; } function NS ($me) { if (is_scalar ($me)) return "".$me; return ""; } function NA ($me) { if (is_array($me)) return $me; return array(); } function NZ ($value, $alt, $prefix="", $postfix="") { if (!is_scalar ($value)) if ($value) return $value; else return $alt; if ($value) return "$prefix$value$postfix"; else return $alt; } } if (!function_exists("TN")) { function TN (&$me) { $me = NN ($me); return $me; } function TS (&$me) { $me = NS ($me); return $me; } function TA (&$me) { $me = NA ($me); return $me; } } if (!function_exists("N_Count")) { function N_Count ($me) { if (is_array ($me)) return count ($me); if ($me instanceof Countable) return count ($me); return null; } } function N_2MB($from) { /* $testCases = ["13", "13B", "13KB", "10.5KB", "123MB", "287GB", "1.1TB", "123M", "287G", "1.1T", "123 M", "287 G", "1.1 T", "123 QQ", "1.23 M", "", null, 0, array()]; T_EO (array_map('N_2MB', $testCases)); */ $from = NS ($from); $from = str_replace(" ", "", $from); if (substr($from, -1) != "B") $from = "$from" . "B"; $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB'); $number = substr($from, 0, -2); $suffix = strtoupper(substr($from, -2)); if (is_numeric(substr($suffix, 0, 1))) return preg_replace('/[^\d]/', '', $from) / 1024 / 1024; $units = array_flip($units); $exponent = $units[$suffix]; if ($exponent === null) return 0; return NN ($number) * pow(1024, NN ($exponent)) / 1024 / 1024; } function N_Safe($html) { $html = str_replace("<", "<", $html); return $html; } function N_T($input = true) { if (strpos($_SERVER["HTTP_USER_AGENT"], "Firefox")) return null; if (strpos($_SERVER["HTTP_USER_AGENT"], "OS X")) return null; if ($_SERVER["REMOTE_ADDR"] != $GLOBALS["pnkit_owner_ip"] && $_SERVER["REMOTE_ADDR"] != "127.0.0.1") return null; return $input; } function N_ForceSSL() { header("strict-transport-security: max-age=31536000"); if ($_SERVER["HTTPS"] != "on") { header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"], true, 301); exit(); } } function N_CLI() { $sapi_type = php_sapi_name(); if (substr($sapi_type, 0, 3) == 'cli') { return true; } else { return false; } } function N_Once($func) { static $cache; ini_set('memory_limit', '10240M'); if (memory_get_usage() > 750000000) { $cache = array(); // Prevent too much memory usage $GLOBALS["calls"]["#N_Once Cache Wipes#"]++; } $args = func_get_args(); $cachekey = md5(serialize($args)); if (is_array ($cache) && array_key_exists ($cachekey, $cache)) return $cache[$cachekey]; array_shift($args); $cache[$cachekey] = call_user_func_array($func, $args); return $cache[$cachekey]; } function N_DFC($func) // Extreme high speed caching of deterministic function calls. Parameters and results should be relatively small. Becomes even faster if https://github.com/igbinary/igbinary is installed. { global $n_dfc, $n_flushdfc_shutdown, $n_flushdfc_functions; ini_set('memory_limit', '10240M'); if (strpos($func, "#")) { $funcarr = explode("#", $func); $truefunc = $funcarr[0]; } else { $truefunc = $func; } if (!$n_dfc[$func]) { $n_dfc[$func] = PMB_Load("n_dfc_ig", $func); if (@N_Count ($n_dfc[$func]) > 26000) { // keep at most 25000 - 26000 elements $rnd = array_rand($n_dfc[$func], N_Count ($n_dfc[$func]) - 25000); // randomly delete elements until there are 25000 left $GLOBALS["calls"]["#N_DFC Removed Elements#"] += N_Count ($rnd); foreach ($rnd as $key) unset($n_dfc[$func][$key]); } } $args = func_get_args(); $cachekey = md5(serialize($args)); if ($n_dfc[$func][$cachekey]["valid"]) { return $n_dfc[$func][$cachekey]["value"]; } array_shift($args); if ($funcarr) { array_shift($funcarr); $trueargs = array_merge($funcarr, $args); } else { $trueargs = $args; } $n_dfc[$func][$cachekey]["value"] = call_user_func_array($truefunc, $trueargs); $n_dfc[$func][$cachekey]["valid"] = true; if (!$n_flushdfc_shutdown) { $n_flushdfc_shutdown = true; register_shutdown_function('N_FlushDFC'); } $n_flushdfc_functions[$func] = $func; return $n_dfc[$func][$cachekey]["value"]; } function N_FlushDFC() { global $n_dfc, $n_flushdfc_functions; foreach ($n_flushdfc_functions as $func) { PMB_Save("n_dfc_ig", $func, $n_dfc[$func]); } } function N_WipeDFC($func) { PMB_Delete("n_dfc_ig", $func); } function N_ResetGlobalProfiler () { for ($i=0; $i<25; $i++) unlink ($GLOBALS['pnkit_data_dir'] . '/profile'.date ("H", time() - $i*3600).'.html'); } function N_GlobalProfiler ($seconds=3600) { if ($seconds > 4 * 3600) $seconds = 4 * 3600; echo "N_GlobalProfiler ($seconds seconds)
"; $profileraw = @file_get_contents ($GLOBALS['pnkit_data_dir'] . '/profile'.date ("H", time()).'.html') . @file_get_contents ($GLOBALS['pnkit_data_dir'] . '/profile'.date ("H", time() - 3600).'.html') . @file_get_contents ($GLOBALS['pnkit_data_dir'] . '/profile'.date ("H", time() - 2 * 3600).'.html') . @file_get_contents ($GLOBALS['pnkit_data_dir'] . '/profile'.date ("H", time() - 3 * 3600).'.html') . @file_get_contents ($GLOBALS['pnkit_data_dir'] . '/profile'.date ("H", time() - 4 * 3600).'.html'); $profile = explode ("\n", $profileraw); foreach ($profile as $line) { if (preg_match ("#([0-9]*) ([0-9.]*) ([^/]*)(.*)#", $line, $matches)) { if (NN($matches[1]) + $seconds > time()) { parse_str ($matches[4], $query); $gurl = $matches[3].implode ("&", array_keys ($query)); $stats[$gurl]["calls"]++; $stats[$gurl]["time"] += NN($matches[2]); $totaltime += NN($matches[2]); } } } $stats = N_SortBy ($stats, '-$record["time"]'); foreach ($stats as $gurl => $stat) { if (($per = round($stat["time"]/$totaltime*1000)/10) == 0) break; echo N_ShowMS ($stat["time"]*1000) ." ($per %) --- $gurl (".$stat["calls"]." calls; ".N_ShowMS ($stat["time"]*1000/$stat["calls"])."/call)
"; } } function MS ($what="") { static $last = 0; $elapsed = microtime(true) - $GLOBALS["MS_start"]; $time_ms = round($elapsed * 1000000) / 1000; if ($what) { if ($last) { $time_ms_last = round((microtime(true) - $last) * 1000000) / 1000; echo "MS $what $time_ms ms ($time_ms_last ms)
"; } else { echo "MS $what $time_ms ms
"; } $last = microtime(true); } return $time_ms; } function NP($func) /* PROFILER, use T_EO ($GLOBALS["np"]); for results */ { $args = func_get_args(); array_shift($args); $start = microtime(true); $result = call_user_func_array($func, $args); $elapsed = microtime(true) - $start; $time_ms = round($elapsed * 1000000) / 1000; $GLOBALS["np"][$func]["calls"]++; $GLOBALS["np"][$func]["time_ms"] += $time_ms; if ($time_ms > 1) { $GLOBALS["np"]["slow"][] = array( "func" => $func, "time_ms" => $time_ms, "args" => $args, ); usort($GLOBALS["np"]["slow"], function ($a, $b) { return -strnatcmp($a["time_ms"], $b["time_ms"]); }); $GLOBALS["np"]["slow"] = array_slice($GLOBALS["np"]["slow"], 0, 10); } return $result; } /* PROFILER, auto reports results */ function P1($tag) { if (!$GLOBALS["pnkit_profiler"]["init"]) { register_shutdown_function("P_Report"); $GLOBALS["pnkit_profiler"]["init"] = true; $GLOBALS["pnkit_profiler"]["start"] = microtime(true); } $GLOBALS["pnkit_profiler"]["tag"][$tag]["calls"]++; $GLOBALS["pnkit_profiler"]["tag"][$tag]["start"] = microtime(true); } function P2($tag) { if (!$GLOBALS["pnkit_profiler"]["init"]) { register_shutdown_function("P_Report"); $GLOBALS["pnkit_profiler"]["init"] = true; $GLOBALS["pnkit_profiler"]["start"] = microtime(true); } $GLOBALS["pnkit_profiler"]["tag"][$tag]["elapsed"] += microtime(true) - $GLOBALS["pnkit_profiler"]["tag"][$tag]["start"]; } function P_Report() { if ($_SERVER["REMOTE_ADDR"] != $GLOBALS["pnkit_owner_ip"] && $_SERVER["REMOTE_ADDR"] != "127.0.0.1") return; // For developer's eyes only $GLOBALS["pnkit_profiler"]["tag"] = N_SortBy($GLOBALS["pnkit_profiler"]["tag"], '$object["elapsed"]', SORT_DESC); echo "
Portable NKIT Profiler Statistics (" . ((int) (1000 * (microtime(true) - $GLOBALS["MS_start"]))) . " ms)
"; if ($GLOBALS["pnkit_profiler"]["tag"]) { foreach ($GLOBALS["pnkit_profiler"]["tag"] as $tag => $d) { echo "$tag: "; echo "" . round(1000 * $d["elapsed"]) . "ms "; echo "(" . $d["calls"] . "x)
"; } } } /* MONITOR, auto reports results */ function M1 ($tag = NULL) { if (!$tag) $tag = @debug_backtrace()[1]["function"]; if (!$GLOBALS["pnkit_monitor"]["init"]) { register_shutdown_function("M_Report"); $GLOBALS["pnkit_monitor"]["init"] = true; $GLOBALS["pnkit_monitor"]["start"] = microtime(true); } $GLOBALS["pnkit_monitor"]["tag"][$tag]["calls"]++; $GLOBALS["pnkit_monitor"]["tag"][$tag]["start"] = microtime(true); } function M2 ($tag = NULL) { if (!$tag) $tag = @debug_backtrace()[1]["function"]; if (!$GLOBALS["pnkit_monitor"]["init"]) { register_shutdown_function("M_Report"); $GLOBALS["pnkit_monitor"]["init"] = true; $GLOBALS["pnkit_monitor"]["start"] = microtime(true); } $GLOBALS["pnkit_monitor"]["tag"][$tag]["elapsed"] += microtime(true) - $GLOBALS["pnkit_monitor"]["tag"][$tag]["start"]; } function M2R ($value, $tag = NULL) { if (!$tag) $tag = @debug_backtrace()[1]["function"]; if (!$GLOBALS["pnkit_monitor"]["init"]) { register_shutdown_function("M_Report"); $GLOBALS["pnkit_monitor"]["init"] = true; $GLOBALS["pnkit_monitor"]["start"] = microtime(true); } $GLOBALS["pnkit_monitor"]["tag"][$tag]["elapsed"] += microtime(true) - $GLOBALS["pnkit_monitor"]["tag"][$tag]["start"]; return $value; } function M_MS ($tag) { return round (1000 * NN (@$GLOBALS["pnkit_monitor"]["tag"][$tag]["elapsed"])); } function M_Report() { $GLOBALS["pnkit_monitor"]["tag"] = N_SortBy($GLOBALS["pnkit_monitor"]["tag"], '$object["elapsed"]', SORT_DESC); if (MS()<3000) return; if ($GLOBALS["pnkit_monitor"]["tag"]) { foreach ($GLOBALS["pnkit_monitor"]["tag"] as $tag => $d) { $line .= "$tag: " . round(1000 * $d["elapsed"]) . "ms (" . $d["calls"] . "x) "; } } ULOG ($line); } function N_MustMatch($match, $func) // T_EO (N_MustMatch ("q", "substr", "q1q2q3", 2, 3), N_MustMatch ("w", "substr", "q1q2q3", 2, 3)); { $args = func_get_args(); array_shift($args); array_shift($args); $result = call_user_func_array($func, $args); if (stristr ($result, $match)) return $result; return NULL; } function N_MustHaveMinSize($minsize, $func) // T_EO (N_MustHaveMinSize (2, "substr", "q1q2q3", 2, 3), N_MustHaveMinSize (4, "substr", "q1q2q3", 2, 3)); { $args = func_get_args(); array_shift($args); array_shift($args); $result = call_user_func_array($func, $args); if (strlen($result) >= $minsize) return $result; return NULL; } function N_CacheLimitExecutionTime ($seconds) { global $N_CacheLimitExecutionTime; $N_CacheLimitExecutionTime = $seconds; } function N_Cache ($specs, $func) /* What we try to achieve here: often faster results, especially if called often (as it's caching) minimize load on whatever we are using, especially if it's not working also minimize load by spreading calls to the underlying systems always return the last non empty result (so this function is NOT usable to check if something is still working) Parameters: cached_hours (or cached_seconds); if the first parameter is not an array, it will be used as cached_hours How long can the cache remember the last succesful answer. -1 for no caching at all. maxfail_hours (or maxfail_seconds) How long after we stop getting results will we return the last succesful answer. ratelimit_hours (or ratelimit_seconds) How long will we wait to try again if we didn't get a result. If cached_hours < ratelimit_hours; cached_hours will be increased to ratelimit_hours. maxfail_hours is increased by ratelimit_hours to prevent false negatives. debug Show internal working. precise Normally 0-15% is added to cached_hours to spread calls to underlying systems. With precise the exact cached_hours is used. Manual cleanup example: find /var/www/fastsimple.com/pnkit_data_dir/local_n_cache/ -type f -mtime +30 -exec rm -f {} \; Test code: https://www.fastsimple.com/pnkit/example_online.php?pnkit=aceeval&saved_code=94ff86ac1086b32ac39522341a3356e1 $failindex = "001"; function failingdate001 ($p) { $result = date ($p); // $result = NULL; T_EO ("CALLED failingdate ($p)", $result); return $result; } //T_EO (N_Cache (["cached_hours"=>10, "precise"=>true, "debug"=>true, "maxfail_hours"=>20, "ratelimit_hours"=>10], "failingdate$failindex", "Y-m-d H:i:s"), date ("Y-m-d H:i:s")); T_EO (N_Cache (["cached_seconds"=>-1, "precise"=>true, "debug"=>true, "maxfail_seconds"=>20, "ratelimit_seconds"=>0], "failingdate$failindex", "Y-m-d H:i:s"), date ("Y-m-d H:i:s")); //T_EO (N_Cache (["maxfail_seconds"=>10, "ratelimit_seconds"=>5], "failingdate$failindex", "Y-m-d H:i:s"), date ("Y-m-d H:i:s")); //T_EO (N_Cache (-1, "failingdate$failindex", "Y-m-d H:i:s"), date ("Y-m-d H:i:s")); */ { M1 ("N_Cache $func"); global $N_CacheLimitExecutionTime; $maxfail_hours = 999999999; $ratelimit_hours = 0; $cached_hours = -1; if (is_array($specs)) { if (isset($specs["cached_hours"])) $cached_hours = $specs["cached_hours"]; if (isset($specs["cached_seconds"])) $cached_hours = $specs["cached_seconds"] / 3600.0; if (isset($specs["maxfail_hours"])) $maxfail_hours = $specs["maxfail_hours"]; if (isset($specs["maxfail_seconds"])) $maxfail_hours = $specs["maxfail_seconds"] / 3600.0; if (isset($specs["ratelimit_hours"])) $ratelimit_hours = $specs["ratelimit_hours"]; if (isset($specs["ratelimit_seconds"])) $ratelimit_hours = $specs["ratelimit_seconds"] / 3600.0; } else { if ($specs) $cached_hours = $specs; $specs = []; } $random = mt_rand (100, 115); if ($specs["precise"]) $random = 100; $cached_hours = ($random * $cached_hours) / 100; $ratelimit_hours = ($random * $ratelimit_hours) / 100; if ($cached_hours < $ratelimit_hours) $cached_hours = $ratelimit_hours; if ($N_CacheLimitExecutionTime) { if (MS() > 1000 * $N_CacheLimitExecutionTime) { $maxfail_hours = 999999999; $cached_hours = 999999999; } } $maxfail_hours += $ratelimit_hours; if ($specs["debug"]) { $specs["calculated_cached_seconds"] = round (3600 * $cached_hours); $specs["calculated_maxfail_seconds"] = round (3600 * $maxfail_hours); $specs["calculated_ratelimit_seconds"] = round (3600 * $ratelimit_hours); } $args = func_get_args(); array_shift($args); $cachekey = md5(serialize($args)); $cacheentry1 = PMB_Load('local_n_cache', $cachekey); if ($ratelimit_hours) { $cachefailed = PMB_Load('local_n_cachefailed', $cachekey); if ($cachefailed) { if (time() - $cachefailed < 3600 * $ratelimit_hours) { if ($cacheentry1 && $cacheentry1['result']) { if (time() - $cacheentry1['time'] > 3600 * $maxfail_hours) { if ($specs["debug"]) T_EO ("N_Cache RATE LIMIT & MAX FAIL => VISIBLE FAIL", $specs, $func, $args, $cacheentry1); M2 ("N_Cache $func"); return NULL; } else { if ($specs["debug"]) T_EO ("N_Cache RATE LIMIT => LAST RESULT", $specs, $func, $args, $cacheentry1); $GLOBALS["N_Cache_state"] = "old"; M2 ("N_Cache $func"); return $cacheentry1['result']; } } else { if ($specs["debug"]) T_EO ("N_Cache RATE LIMIT => NO RESULT", $specs, $func, $args); M2 ("N_Cache $func"); return NULL; } } } } if ($cacheentry1 && $cacheentry1['result'] && time() - $cacheentry1['time'] < ($random * $cached_hours * 36)) { // Randomly add 0% - 15% to spread actual actions array_shift($args); if ($specs["debug"]) T_EO ("N_Cache FETCH", $specs, $func, $args, $cacheentry1); $GLOBALS["N_Cache_state"] = "cache"; M2 ("N_Cache $func"); return $cacheentry1['result']; } array_shift($args); $result = call_user_func_array($func, $args); $cacheentry2 = array(); $cacheentry2['time'] = time(); if ($result) { PMB_Delete('local_n_cachefailed', $cachekey); $GLOBALS["N_Cache_state"] = "fresh"; $cacheentry2['result'] = $result; PMB_Save('local_n_cache', $cachekey, $cacheentry2); if ($specs["debug"]) T_EO ("N_Cache STORE", $specs, $func, $args, $cacheentry1, $cacheentry2); M2 ("N_Cache $func"); return $cacheentry2['result']; } else if ($cacheentry1 && $cacheentry1['result']) { PMB_Save('local_n_cachefailed', $cachekey, time()); if (time() - $cacheentry1['time'] > 3600 * $maxfail_hours) { if ($specs["debug"]) T_EO ("N_Cache VISIBLE FAIL", $specs, $func, $args, $cacheentry1); M2 ("N_Cache $func"); return NULL; } else { if ($specs["debug"]) T_EO ("N_Cache HIDDEN FAIL", $specs, $func, $args, $cacheentry1); $GLOBALS["N_Cache_state"] = "old"; M2 ("N_Cache $func"); return $cacheentry1['result']; } } else { PMB_Save('local_n_cachefailed', $cachekey, time()); if ($specs["debug"]) T_EO ("N_Cache NOT CACHED FAIL", $specs, $func, $args, $cacheentry1); M2 ("N_Cache $func"); return NULL; } } function N_WipeCache($func) { $args = func_get_args(); $cachekey = md5(serialize($args)); PMB_Delete('local_n_cache', $cachekey, $cachekey); } function N_ObjectToArray($data) { if (is_object($data)) { $data = get_object_vars($data); } if (is_array($data)) { return array_map('N_ObjectToArray_LL', $data); } else { if ($data) { return array($data); } else { return array(); } } } function N_ObjectToArray_LL($data) { if (is_object($data)) { $data = get_object_vars($data); } if (is_array($data)) { return array_map('N_ObjectToArray_LL', $data); } else { return $data; } } function N_ObjectWithHiddenToArray ($me, $maxdepth=5, $recursion=false) // does not understand XML { $result = []; if (is_object ($me)) { if ($maxdepth < 1) return "***RECURSION***"; $reflectedObject = new ReflectionObject ($me); $properties = $reflectedObject->getProperties(); foreach($properties as $property){ $property->setAccessible (true); // Note: As of PHP 8.1.0, calling this method has no effect; all properties are accessible by default. $result[$property->getName()] = N_ObjectWithHiddenToArray ($property->getValue($me), $maxdepth - 1, true); } } else if (is_array ($me)) { foreach ($me as $id => $val) $result[$id] = N_ObjectWithHiddenToArray ($val, $maxdepth, true); } else if ($recursion) { return $me; } else { return [$me]; } return $result; } function N_XMLToArray ($xml) { return NA (N_XMLToArray_LL (simplexml_load_string ($xml))); } function N_XMLToArray_LL ($xml) { // https://gist.github.com/jobrieniii/92df79811f62b444b39f $options = array( 'namespaceSeparator' => ':', //you may want this to be something other than a colon 'attributePrefix' => '@', //to distinguish between attributes and nodes with the same name 'alwaysArray' => array(), //array of xml tag names which should always become arrays 'autoArray' => true, //only create arrays for tags which appear more than once 'textContent' => '$', //key used for the text content of elements 'autoText' => true, //skip textContent key if node has no attributes or child nodes 'keySearch' => false, //optional search and replace on tag and attribute names 'keyReplace' => false //replace values for above search values (as passed to str_replace()) ); $namespaces = $xml->getDocNamespaces(); $namespaces[''] = null; //add base (empty) namespace //get attributes from all namespaces $attributesArray = array(); foreach ($namespaces as $prefix => $namespace) { foreach ($xml->attributes($namespace) as $attributeName => $attribute) { //replace characters in attribute name if ($options['keySearch']) $attributeName = str_replace($options['keySearch'], $options['keyReplace'], $attributeName); $attributeKey = $options['attributePrefix'] . ($prefix ? $prefix . $options['namespaceSeparator'] : '') . $attributeName; $attributesArray[$attributeKey] = (string)$attribute; } } //get child nodes from all namespaces $tagsArray = array(); foreach ($namespaces as $prefix => $namespace) { foreach ($xml->children($namespace) as $childXml) { //recurse into child nodes $childArray = N_XMLToArray_LL ($childXml); list ($childTagName, $childProperties) = N_Each ($childArray); //replace characters in tag name if ($options['keySearch']) $childTagName = str_replace($options['keySearch'], $options['keyReplace'], $childTagName); //add namespace prefix, if any if ($prefix) $childTagName = $prefix . $options['namespaceSeparator'] . $childTagName; if (!isset($tagsArray[$childTagName])) { //only entry with this key //test if tags of this type should always be arrays, no matter the element count $tagsArray[$childTagName] = in_array ($childTagName, $options['alwaysArray']) || !$options['autoArray'] ? array($childProperties) : $childProperties; } elseif ( is_array($tagsArray[$childTagName]) && array_keys($tagsArray[$childTagName]) === range(0, count($tagsArray[$childTagName]) - 1) ) { //key already exists and is integer indexed array $tagsArray[$childTagName][] = $childProperties; } else { //key exists so convert to integer indexed array with previous value in position 0 $tagsArray[$childTagName] = array($tagsArray[$childTagName], $childProperties); } } } //get text content of node $textContentArray = array(); $plainText = trim((string)$xml); if ($plainText !== '') $textContentArray[$options['textContent']] = $plainText; //stick it all together $propertiesArray = !$options['autoText'] || $attributesArray || $tagsArray || ($plainText === '') ? array_merge($attributesArray, $tagsArray, $textContentArray) : $plainText; //return node as array return array( $xml->getName() => $propertiesArray ); } function N_Each ($array){ $key = key ($array); $value = current ($array); $each = is_null($key) ? false : [ 1 => $value, 'value' => $value, 0 => $key, 'key' => $key, ]; next ($array); return $each; } function N_Encode64($string) { return strtr(base64_encode($string), '+/', '-_'); } function N_Decode64($string) { return base64_decode(strtr($string, '-_', '+/')); } function N_SecureEncode ($string) { $key = md5 ($string); PMB_Save ("pnkit_secureencoded", $key, $string); return "pnsecenc_$key"; } function N_SecureDecode ($key) { if (substr ($key, 0, 9)=="pnsecenc_") { return PMB_Load ("pnkit_secureencoded", substr ($key, 9)); } else { return $key; } } function N_QuickLog ($me) { $tr = debug_backtrace(); $tr[0]["args"] = []; static $ctr=20000, $pid; $ctr++; if (!$pid) $pid=getmypid(); $logid = microtime(true).$ctr.sprintf ("%010d", crc32 (rand ().$pid)); $class = "NewQuickLog"; $function = $tr[1]["function"]; if ($function=="eval") $function .= " - ".$tr[2]["function"]; PMB_Save ("ulog_lines", $logid, [ "line" => $me, "class" => $class, "function" => $function, "line_number" => $tr[0]["line"], "BID" => $_COOKIE['pnkit_bid_v11'], "REMOTE_ADDR" => $_SERVER["REMOTE_ADDR"], "preserve_details" => false ]); PMB_Save ("ulog_details", $logid, [ "has_details" => false, "details" => [], "PID" => $pid, "HTTP_HOST" => $_SERVER['HTTP_HOST'], "SCRIPT_NAME" => $_SERVER['SCRIPT_NAME'], "REMOTE_PORT" => $_SERVER["REMOTE_PORT"], "REQUEST_SCHEME" => $_SERVER["REQUEST_SCHEME"], "HTTP_REFERER " => $_SERVER["HTTP_REFERER"], "HTTP_USER_AGENT" => $_SERVER["HTTP_USER_AGENT"], "stack_arr" => $tr, ]); } // $line can be (single line) safe HTML. // The standard retention period for details is 1-2 weeks. function ULOG ($line, $details = NULL, $preserve_details = false, $class = NULL, $logid = NULL, $function = NULL) { $tr = debug_backtrace(); $tr[0]["args"] = []; foreach ($tr as $index1 => $data1) { foreach ($data1["args"] as $index2 => $data2) { if (strlen (serialize ($data2)) > 250) { $tr[$index1]["args"][$index2] = "*** LARGE *** SIZE: " . strlen (serialize ($data2)); } } } /* $logid */ static $ctr=20000, $pid; $ctr++; if (!$pid) $pid=getmypid(); if (!$logid) $logid = microtime(true).$ctr.sprintf ("%010d", crc32 (rand ().$pid)); /* $class */ if (!$class) $class = $_SERVER['HTTP_HOST']." - ".basename ($_SERVER['SCRIPT_NAME']); /* $function */ if (!$function) $function = $tr[1]["function"]; if ($function=="eval") $function .= " - ".$tr[2]["function"]; PMB_Save ("ulog_lines", $logid, [ "line" => $line, "class" => $class, "function" => $function, "line_number" => $tr[0]["line"], "ms" => MS(), "mem" => round (memory_get_usage()/(1024*1024)), "peak" => round (memory_get_peak_usage()/(1024*1024)), "BID" => $_COOKIE['pnkit_bid_v11'], "REMOTE_ADDR" => $_SERVER["REMOTE_ADDR"], "preserve_details" => $preserve_details, ]); PMB_Save ("ulog_details", $logid, [ "has_details" => !!$details, "details" => $details, "PID" => $pid, "HTTP_HOST" => $_SERVER['HTTP_HOST'], "SCRIPT_NAME" => $_SERVER['SCRIPT_NAME'], "REMOTE_PORT" => $_SERVER["REMOTE_PORT"], "REQUEST_SCHEME" => $_SERVER["REQUEST_SCHEME"], "HTTP_REFERER " => $_SERVER["HTTP_REFERER"], "HTTP_USER_AGENT" => $_SERVER["HTTP_USER_AGENT"], "stack_arr" => $tr, ]); } // Two differences with ULOG --- if (++$GLOBALS["ULOG_Once"][$line] > 1) return; --- , "once" => true function ULOG_Once ($line, $details = NULL, $preserve_details = false, $class = NULL, $logid = NULL, $function = NULL) { if (++$GLOBALS["ULOG_Once"][$line] > 1) return; $tr = debug_backtrace(); $tr[0]["args"] = []; foreach ($tr as $index1 => $data1) foreach ($data1["args"] as $index2 => $data2) if (strlen (serialize ($data2)) > 250) $tr[$index1]["args"][$index2] = "*** LARGE *** SIZE: " . strlen (serialize ($data2)); static $ctr=10000, $pid; $ctr++; if (!$pid) $pid=getmypid(); if (!$logid) $logid = microtime(true).$ctr.sprintf ("%010d", crc32 (rand ().$pid)); if (!$class) $class = $_SERVER['HTTP_HOST']." - ".basename ($_SERVER['SCRIPT_NAME']); if (!$function) $function = $tr[1]["function"]; if ($function=="eval") $function .= " - ".$tr[2]["function"]; PMB_Save ("ulog_lines", $logid, ["line" => $line, "class" => $class, "function" => $function, "line_number" => $tr[0]["line"], "ms" => MS(), "mem" => round (memory_get_usage()/(1024*1024)), "peak" => round (memory_get_peak_usage()/(1024*1024)), "BID" => $_COOKIE['pnkit_bid_v11'], "REMOTE_ADDR" => $_SERVER["REMOTE_ADDR"], "preserve_details" => $preserve_details, "once" => true]); PMB_Save ("ulog_details", $logid, ["has_details" => !!$details, "details" => $details, "PID" => $pid, "HTTP_HOST" => $_SERVER['HTTP_HOST'], "SCRIPT_NAME" => $_SERVER['SCRIPT_NAME'], "REMOTE_PORT" => $_SERVER["REMOTE_PORT"], "REQUEST_SCHEME" => $_SERVER["REQUEST_SCHEME"], "HTTP_REFERER " => $_SERVER["HTTP_REFERER"], "HTTP_USER_AGENT" => $_SERVER["HTTP_USER_AGENT"], "stack_arr" => $tr]); } function N_BR() { if (N_CLI()) { return "\r\n"; } else { return "
\r\n"; } } function N_Human() { $known = array('msie', 'firefox', 'safari', 'webkit', 'opera', 'netscape', 'konqueror', 'gecko'); $agent = strtolower($_SERVER['HTTP_USER_AGENT']); $pattern = '#(?' . implode('|', $known) . ')[/ ]+(?[0-9]+(?:\.[0-9]+)?)#'; if (!preg_match_all($pattern, $agent, $matches)) { return false; } return true; } function N_TimeElapsedString ($datetime, $full = false) { // stackoverflow.com/questions/1416697 $now = new DateTime; $ago = new DateTime($datetime); $diff = $now->diff($ago); $diff->w = floor($diff->d / 7); $diff->d -= $diff->w * 7; $string = array( 'y' => 'year', 'm' => 'month', 'w' => 'week', 'd' => 'day', 'h' => 'hour', 'i' => 'minute', 's' => 'second', ); foreach ($string as $k => &$v) { if ($diff->$k) { $v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : ''); } else { unset($string[$k]); } } if (!$full) $string = array_slice($string, 0, 1); return $string ? implode(', ', $string) . ' ago' : 'just now'; } function N_getRelativePath ($from, $to) // Source: https://stackoverflow.com/questions/2637945/getting-relative-path-from-absolute-path-in-php { $from = is_dir($from) ? rtrim($from, '\/') . '/' : $from; $to = is_dir($to) ? rtrim($to, '\/') . '/' : $to; $from = str_replace('\\', '/', $from); $to = str_replace('\\', '/', $to); $from = explode('/', $from); $to = explode('/', $to); $relPath = $to; foreach ($from as $depth => $dir) { if ($dir === $to[$depth]) { array_shift($relPath); } else { $remaining = N_Count ($from) - $depth; if ($remaining > 1) { $padLength = (N_Count ($relPath) + $remaining - 1) * -1; $relPath = array_pad($relPath, $padLength, '..'); break; } else { $relPath[0] = './' . $relPath[0]; } } } return implode('/', $relPath); } if (!function_exists ("N_SortBy")) { function N_SortBy() // $data, $expression1, $sort_order1, $sort_flags1, $expression2, $sort_order2, $sort_flags2, ... { $data = NA ($data); $args = func_get_args(); $data_in = array_shift($args); if (!is_array($data_in)) return array(); foreach ($data_in as $key => $value) $data[serialize($key)] = $value; foreach ($args as $n => $expression) { if (is_string($expression)) { $tmp = array(); foreach ($data as $key => $value) { $record = $rec = $object = $obj = $row = $value; $sortvalue = NULL; eval("\$sortvalue = $expression;"); $tmp[$key] = $sortvalue; } $args[$n] = $tmp; } } $args[] = &$data; call_user_func_array('array_multisort', $args); $data = array_pop($args); foreach ($data as $key => $value) $data_out[unserialize($key)] = $value; return $data_out; } function T_EO () // TEST: https://www.fastsimple.com/pnkit/example_online.php?pnkit=eval&saved_code=4d3d4009dd906f52fa633dc39458a3a1 { $tr = debug_backtrace(); for ($i = N_Count ($tr) - 1; $i >= 0; $i--) { $stack .= $tr[$i]["function"] . ":{$tr[$i]["line"]}"; if (N_CLI()) $stack .= " -> "; else $stack .= " → "; } $stack = preg_replace('/(T_EO)[^A-Z0-9_].*/i', '$1', $stack); echo "T_EO [$stack]"; if (N_CLI()) echo "\n"; else echo "
"; $args = func_get_args(); if (count ($args) > 1) echo ""; foreach ($args as $object) { if (count ($args) > 1) echo ""; } if (count ($args) > 1) echo "
"; if (N_CLI()) { if (is_array($object)) { echo '(arr: ' . N_Count ($object) . ')'.PHP_EOL; print_r($object); } else if (is_string($object)) { echo '(str: ' . strlen($object) . ') '.PHP_EOL; print_r($object); } else if (is_boolean($object)) { echo '(' . gettype($object) . ') '.PHP_EOL; echo $object ? "true" : "false"; } else { echo '(' . gettype($object) . ') '.PHP_EOL; print_r($object); } } else { echo '
';
                    if (is_array($object)) {
                        echo '(arr: ' . N_Count ($object) . ')'.PHP_EOL;
                        echo htmlentities(print_r($object, 1),  2, 'ISO-8859-1'); // ENT_COMPAT | ENT_HTML401 = 2
                    } else if (is_string($object)) {
                        echo '(str: ' . strlen($object) . ') '.PHP_EOL;
                        echo htmlentities(print_r($object, 1),  2, 'ISO-8859-1'); // ENT_COMPAT | ENT_HTML401 = 2
                    } else if (is_bool($object)) {
                        echo '(' . gettype($object) . ') '.PHP_EOL;
                        echo $object ? "true" : "false";
                    } else {
                        echo '(' . gettype($object) . ') '.PHP_EOL;
                        echo htmlentities(print_r($object, 1),  2, 'ISO-8859-1'); // ENT_COMPAT | ENT_HTML401 = 2
                    }
                    echo '
'; // ENT_COMPAT | ENT_HTML401 = 2 } if (count ($args) > 1) echo "
"; } function N_Hexdump($data) { $htmloutput = true; $uppercase = false; $hexi = ''; $ascii = ''; $dump = ($htmloutput === true) ? '
' : '';
            $offset = 0;
            $len = strlen($data);
            $x = ($uppercase === false) ? 'x' : 'X';
            for ($i = $j = 0; $i < $len; ++$i) {
                $hexi .= sprintf("%02$x ", ord($data[$i]));
                if (ord($data[$i]) >= 32) {
                    $ascii .= ($htmloutput === true) ? htmlentities($data[$i]) : $data[$i];
                } else {
                    $ascii .= '.';
                }
                if ($j === 7 || $j === 13 || $j === 23) {
                    $hexi .= ' ';
                    $ascii .= ' ';
                }
                if (++$j === 32 || $i === $len - 1) {
                    $dump .= sprintf("%04$x  %-49s  %s", $offset, $hexi, $ascii);
                    $hexi = $ascii = '';
                    $offset += 32;
                    $j = 0;
                    if ($i !== $len - 1) {
                        $dump .= "\n";
                    }
                }
            }
            $dump .= $htmloutput === true ? '
' : ''; $dump .= "\n"; return $dump; } function N_GUID($chars = 32) { if ($chars > 32) { return N_GUID() . N_GUID($chars - 32); } else { global $LastGUID; $LastGUID = md5(getmypid() . time() . microtime() . serialize($_SERVER) . $LastGUID); return substr($LastGUID, 0, $chars); } } function N_Year() { return date('Y'); } function N_Regexp($string, $patern, $index = 1) { if (preg_match_all("#$patern#i", $string, $matches) === false) { return null; } return $matches[0][$index - 1]; } function N_Windows() { return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; } function N_GetPage ($url, $maxms=-1) { M1 (); if ($maxms != -1) { $ch = curl_init($url); curl_setopt ($ch, CURLOPT_TIMEOUT_MS, 1000 + $maxms); // maximum time the transfer is allowed to complete curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT_MS, 100 + $maxms); // timeout for the connect phase curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true); return M2R (curl_exec($ch)); } else { return M2R (file_get_contents($url)); } } function N_KeepAfter($body, $marker) { if ('' . $marker == '') { return $body; } if (strpos($body, $marker) === false) { return ''; } else { return substr($body, strpos($body, $marker) + strlen($marker)); } } function N_KeepBefore($body, $marker) { if ('' . $marker == '') { return $body; } if (strpos($body, $marker) === false) { return ''; } else { return substr($body, 0, strpos($body, $marker)); } } } // if (!function_exists("N_SortBy")) if (!function_exists('array_key_first')) { // PHP 7.3 function array_key_first(array $arr) { foreach ($arr as $key => $unused) { return $key; } return NULL; } } /******************************************************************************/ // INTERACTIVE FACILITIES function N_PNKIT() { if ($_REQUEST["pnkit"] == "dir") $_REQUEST["pnkit"] = "acedir"; if ($_REQUEST["pnkit"] == "edit") $_REQUEST["pnkit"] = "aceedit"; if ($_REQUEST["pnkit"] == "eval") $_REQUEST["pnkit"] = "aceeval"; if ($_REQUEST["pnkit"] == "evalnow") $_REQUEST["pnkit"] = "aceevalnow"; if ($GLOBALS["pnkit_mode"] != "online") $GLOBALS["pnkit_mode"] = "offline"; if ($_SERVER["REMOTE_ADDR"] != $GLOBALS["pnkit_owner_ip"] && $_SERVER["REMOTE_ADDR"] != "127.0.0.1") die(); if ($_REQUEST["pnkit"] == "txtevalnow" || $_REQUEST["pnkit"] == "aceevalnow") { echo "🗎
"; $code = PMB_Load ("pnkit_eval_saved_code", $_REQUEST["saved_code"]); eval($code); PMB_Flush(); die (""); } if (($_REQUEST["pnkit"] == "txtedit" || $_REQUEST["pnkit"] == "aceedit") && $file = $_REQUEST["file"]) { echo "" . substr($file, strrpos($file, "/") + 1) . " - [" . $_SERVER["HTTP_HOST"] . "] - INTERACTIVE PORTABLE NKIT\n"; } else if (($_REQUEST["pnkit"] == "txtdir" || $_REQUEST["pnkit"] == "acedir") && $dir = $_REQUEST["dir"]) { echo "" . substr($dir, strrpos($dir, "/") + 1) . " - [" . $_SERVER["HTTP_HOST"] . "] - INTERACTIVE PORTABLE NKIT\n"; } else if ($_REQUEST["pnkit"] == "txteval" || $_REQUEST["pnkit"] == "aceeval") { Header ("X-XSS-Protection: 0"); echo "EVAL - [" . $_SERVER["HTTP_HOST"] . "] - INTERACTIVE PORTABLE NKIT\n"; } else { echo "[" . $_SERVER["HTTP_HOST"] . "] - INTERACTIVE PORTABLE NKIT\n"; } echo "\n"; echo "[" . $_SERVER["HTTP_HOST"] . "] - INTERACTIVE PORTABLE NKIT ("; echo "EVAL"; echo " ️#"; echo ", DIR"; echo " #"; echo ", DATA"; echo ", ULOG"; echo ", PAGE"; echo ", HOME"; echo ", THIS"; echo ") pnkit_data_dir: " . $GLOBALS["pnkit_data_dir"] . " pnkit_public_cache_dir_internal: " . $GLOBALS["pnkit_public_cache_dir_internal"] . "
\n"; $module = $_REQUEST["pnkit"]; if ($module == "txteval" || $module == "aceeval") { if ($_REQUEST["saved_code"]) { $code = PMB_Load ("pnkit_eval_saved_code", $_REQUEST["saved_code"]); } else { $code = $_REQUEST["code"]; if (function_exists ("get_magic_quotes_gpc")) if (get_magic_quotes_gpc()) $code = stripslashes($code); } if (strstr($_REQUEST["action"], "URL")) { PMB_Save ("pnkit_eval_saved_code", $guid = N_GUID(), $_REQUEST["code"]); header("Location: //" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"] . "?pnkit=$module&saved_code=$guid"); exit(); } if (strstr($_REQUEST["action"], "APP")) { PMB_Save ("pnkit_eval_saved_code", $guid = N_GUID(), $_REQUEST["code"]); header("Location: //" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"] . "?pnkit={$module}now&saved_code=$guid"); exit(); } echo "\n"; echo "
\n"; if ($module == "aceeval") { echo ' '; echo " \n"; echo "
"; echo " \n"; echo ' '; } else { echo "
\n"; echo " \n"; } echo " \n"; echo " \n"; echo " \n"; echo " \n"; echo "
\n"; echo "
\n"; if (strstr($_REQUEST["action"], "Execute")) { $post = array( 'store' => PMB_Load ('lib_key', 'fastsimple_native_versions'), 'domain' => $_SERVER["HTTP_HOST"], 'file' => "[PNKIT EVAL]", 'author' => 'Nico@' . $_SERVER["REMOTE_ADDR"], 'sourcecode' => $code ); $ch = curl_init('https://versions.fastsimple.com'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); curl_exec($ch); curl_close($ch); $t_start_bm = microtime(true); $m_start = memory_get_usage(); if (strstr($_REQUEST["action"], "muuse")) muuse(); $t_start = microtime(true); eval($code); $t_end = microtime(true); $m_end = memory_get_usage(); if ($code) { if (strstr($_REQUEST["action"], "muuse")) { echo "
Elapsed: " . (((int) (1000000 * ($t_end - $t_start))) / 1000) . " ms (muuse ".(((int) (1000000 * ($t_start - $t_start_bm))) / 1000)." ms)
\n"; } else { echo "
Elapsed: " . (((int) (1000000 * ($t_end - $t_start))) / 1000) . " ms
\n"; } if ($m_end - $m_start > 2 * 1024 * 1024) { echo "Memory usage: " . (((int) (($m_end - $m_start) / (1024 * 1024)))) . " MiB
\n"; } else { echo "Memory usage: " . (((int) (($m_end - $m_start) / 1024))) . " KiB
\n"; } echo "Peak memory usage: ".((int)(memory_get_peak_usage()/(1024*1024)))." MiB
\n
\n"; if ($GLOBALS["calls"]) T_EO($GLOBALS["calls"]); } } } else if ($module == "data") { $table = $_REQUEST["table"]; $key = $_REQUEST["key"]; $explode = $_REQUEST["explode"]; if ($table) { if ($key) { $ts = date ("Y-m-d D H:i:s", PMB_LastUpdate ($table, $key)); echo "DATA TABLE: $table KEY: $key $ts
\n"; T_EO(PMB_Load($table, $key)); } else if ($explode) { echo "DATA TABLE (exploded): $table
\n"; $keys = PMB_AllKeys($table); $ctr = 0; foreach ($keys as $k) { $ts = date ("Y-m-d D H:i:s", PMB_LastUpdate ($table, $k)); echo "[$k] $ts
\n"; T_EO(PMB_Load($table, $k)); if (++$ctr > 100) { echo "...
\n"; break; } } } else { echo "DATA TABLE (explode): $table
\n"; $keys = PMB_AllKeys($table); foreach ($keys as $k) { $ts = date ("Y-m-d D H:i:s", PMB_LastUpdate ($table, $k)); echo "[$k] $ts
\n"; if (++$ctr > 1000) { echo "...
\n"; break; } } } } else { $showdetails = $_REQUEST["showdetails"]; echo "DATA: ALL TABLES "; if ($showdetails) { echo "(hide details) "; $dir = $GLOBALS['pnkit_data_dir'] . "/"; $find = `find $dir`; $list = explode ("\n", $find); foreach ($list as $line) { $subdir = substr ($line, strlen($GLOBALS['pnkit_data_dir'])+1); $table = substr ($subdir , 0, strpos ($subdir , "/")); $count[$table]++; } } else { echo "(show details) "; } echo "
\n"; $tables = PMB_AllTables(); foreach ($tables as $t) { echo "[$t] "; if ($showdetails) echo "(" . $count[$t] . ") "; echo "
\n"; } } } else if (($module == "txtdir" || $module == "acedir") && $_REQUEST["search"] && $_REQUEST["action"]=="Deep Search") { if ($module == "txtdir") $editor = "txtedit"; else $editor = "aceedit"; $dir = $_REQUEST["dir"]; $search = $_REQUEST["search"]; if (!$dir) $dir = $_SERVER["DOCUMENT_ROOT"]; $intdir = ""; $showdir = ""; foreach (array_filter (explode ("/", $dir)) as $dirpart) { $intdir = "$intdir/$dirpart"; $showdir .= "/$dirpart"; } echo "DEEP SEARCH DIR: $showdir
\n"; echo "
"; echo ""; echo ""; echo ""; echo ""; echo "
\n"; $validextensions = array ("php", "js", "css", "scss", "json", "txt", "html"); $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)); $found = array(); foreach ($rii as $x) { if (is_file($x->getPathname()) && filesize($x->getPathname()) < 1024 * 1024) { if (in_array (strtolower (pathinfo ($x->getPathname(), PATHINFO_EXTENSION)), $validextensions)) { $content = file_get_contents($x->getPathname()); if (stripos(" $content", $search)) $found[] = str_replace ("$dir/", "", $x->getPathname()); } } } sort ($found); echo "Found ".count($found)." files
"; foreach ($found as $e) echo "$e
\n"; } else if ($module == "txtdir" || $module == "acedir") { $dir = $_REQUEST["dir"]; $search = $_REQUEST["search"]; if (!$dir) $dir = $_SERVER["DOCUMENT_ROOT"]; $intdir = ""; $showdir = ""; foreach (array_filter (explode ("/", $dir)) as $dirpart) { $intdir = "$intdir/$dirpart"; $showdir .= "/$dirpart"; } if ($module == "txtdir") { $editor = "txtedit"; echo "DIR #: $showdir
\n"; } else { $editor = "aceedit"; echo "DIR: $showdir
\n"; } echo "
"; echo ""; echo ""; echo ""; echo ""; echo "
\n"; $dirs = $files = $sortedfiles = array(); if ($dir == "/var/www/fastsimple.com") $dirs = array ("pnkit/webassets"); $d = dir($dir); while (false !== ($entry = $d->read())) { if ($entry != "." && $entry != "..") { if (is_dir("$dir/$entry")) { $dirs[] = $entry; } else { $files[] = $entry; $sortedfiles[filemtime ("$dir/$entry")] = $entry; } } } $d->close(); krsort($sortedfiles); sort($dirs); sort($files); $skiplist = array ("jpgraph", "jsplumb", "games", "proxy", "rss", "test", "tmp", "ux", "voxel", "wordpress", "img", "thumb"); $validextensions = array ("php", "js", "css", "scss", "json", "txt", "html"); echo "
"; foreach ($dirs as $e) { $extra = ""; if (!strstr($e, "pnkit_")) if ($search) if (!in_array ($e, $skiplist)) { $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("$dir/$e")); $rii->setMaxDepth(0); foreach ($rii as $x) { if (is_file($x->getPathname()) && filesize($x->getPathname()) < 1024 * 1024) { if (in_array (strtolower (pathinfo ($x->getPathname(), PATHINFO_EXTENSION)), $validextensions)) { $content = file_get_contents($x->getPathname()); if (stripos(" $content", $search)) $extra = "FOUND"; } } } } else { $extra = "skipped"; } if ($search) { echo "[$e] $extra
\n"; } else { echo "[$e] $extra
\n"; } } echo "
"; foreach ($files as $e) if (strpos($e, ".php")) { // All php files $extra = ""; if ($search) { $content = file_get_contents("$dir/$e"); if (stripos(" $content", $search)) $extra = "FOUND"; } echo "[$e] $extra
\n"; } echo "
"; foreach ($files as $e) if (!strpos($e, ".php")) { // All other files < 1 MB $extra = ""; if ($search && filesize("$dir/$e") < 1024 * 1024 && in_array (strtolower (pathinfo ($e, PATHINFO_EXTENSION)), $validextensions)) { $content = file_get_contents("$dir/$e"); if (stripos(" $content", $search)) $extra = "FOUND"; } echo "[$e] $extra
\n"; } echo "
      "; $sortedfiles_subs = array(); foreach ($dirs as $e) { if (!strstr($e, "pnkit_")) if (!in_array ($e, $skiplist)) { $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator("$dir/$e")); $rii->setMaxDepth(0); foreach ($rii as $x) { if (is_file($x->getPathname()) && filesize($x->getPathname()) < 1024 * 1024) { if (in_array (strtolower (pathinfo ($x->getPathname(), PATHINFO_EXTENSION)), $validextensions)) { $sortedfiles_subs[filemtime ($x->getPathname())] = str_replace ("$dir/", "", $x->getPathname()); } } } } } $ctr = 0; foreach ($sortedfiles as $t => $e) if (strpos($e, ".php") || strpos($e, ".css") || strpos($e, ".scss") || strpos($e, ".js")) { echo "".date ("Y-m-d H:i:s", $t)." [$e]
\n"; if (++$ctr==10) break; } echo "
"; krsort($sortedfiles_subs); $ctr = 0; foreach ($sortedfiles_subs as $t => $e) if (strpos($e, ".php") || strpos($e, ".css") || strpos($e, ".scss") || strpos($e, ".js")) { echo "".date ("Y-m-d H:i:s", $t)." [$e]
\n"; if (++$ctr==10) break; } echo "
"; } else if ($module == "txtedit" || $module == "aceedit") { $file = $_REQUEST["file"]; $type = pathinfo($file, PATHINFO_EXTENSION); if ($type=="js") $type = "javascript"; if ($_REQUEST["save"] == "yes") { $content = $_REQUEST["content"]; if (function_exists ("get_magic_quotes_gpc")) if (get_magic_quotes_gpc()) $content = stripslashes($content); file_put_contents($file, $content); if (file_get_contents($file) != $content) { echo "*** SAVE ERROR *** "; } PMB_Save ("pnkit", "last_pnkit_code_save", time()); if (strstr($file, $_SERVER["DOCUMENT_ROOT"] . "/pnkit/") && file_exists($_SERVER["DOCUMENT_ROOT"] . "/.pnkit_core_server")) { file_put_contents($_SERVER["DOCUMENT_ROOT"] . "/pnkit/.pnkit_version", date("c", time())); } $post = array( 'store' => PMB_Load ('lib_key', 'fastsimple_native_versions'), 'domain' => $_SERVER["HTTP_HOST"], 'file' => $file, 'author' => 'Nico@' . $_SERVER["REMOTE_ADDR"], 'sourcecode' => $content ); $ch = curl_init('https://versions.fastsimple.com'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); curl_exec($ch); curl_close($ch); } else { $content = @file_get_contents($file); } $mtime = filemtime ($file); $myurl = $_SERVER["SCRIPT_NAME"] . "?pnkit=$module&file=" . urlencode("$file"); echo "FILE: $file (".date ("Y-m-d H:i:s", $mtime).")
\n"; echo "\n"; echo "
\n"; if ($module == "aceedit") { echo ' '; echo " \n"; // ENT_IGNORE echo "
"; echo " \n"; echo " \n"; echo " \n"; echo ' '; } else { echo "
\n"; // ENT_IGNORE echo " \n"; } echo " \n"; echo " \n"; echo " \n"; echo " \n"; echo " \n"; echo "
\n"; echo "
\n"; echo ' '; } else if ($module == "ulog") { puuse ("ulog"); ULOG_Show(); echo "
Server response time: ".round(MS())." ms, showing {$GLOBALS["ULOG_Show_rows"]} rows"; if ($_REQUEST["lines"] == $GLOBALS["ULOG_Show_rows"]) { echo " (max)"; } else { echo " (< {$_REQUEST["lines"]})"; } echo "."; } else if ($module == "log") { touch($GLOBALS["pnkit_data_dir"] . "/debuglog.html"); echo implode("\n", array_slice(array_reverse(explode("\n", file_get_contents($GLOBALS["pnkit_data_dir"] . "/debuglog.html"))), 0, 100)); echo "
More..."; } else if ($module == "morelog") { touch($GLOBALS["pnkit_data_dir"] . "/debuglog.html"); echo implode("\n", array_slice(array_reverse(explode("\n", file_get_contents($GLOBALS["pnkit_data_dir"] . "/debuglog.html"))), 0, 10000)); echo "
Even more? Look at: ".$GLOBALS["pnkit_data_dir"] . "/debuglog.html"; } else if ($module == "slog") { puuse("secure"); echo "
This security log show files changed since the last time the security log was viewed (generating this can take some time).
" . str_repeat(" ", 7000000); flush(); SECURE_DeltaScanAllAndLog("/var/www"); SECURE_ShowLog(); } echo "\n"; } /******************************************************************************/ // INIT if (N_CLI()) $_REQUEST["argv"] = $_SERVER["argv"]; if (!@$GLOBALS["pnkit_mode"]) $GLOBALS["pnkit_mode"] = "offline"; $pathinfo = pathinfo(__FILE__); if ($pathinfo["dirname"]) $pathinfo2 = pathinfo($pathinfo["dirname"]); if (!@$GLOBALS["pnkit_version"]) $GLOBALS["pnkit_version"] = file_get_contents($pathinfo["dirname"] . "/.pnkit_version"); if (!$GLOBALS["pnkit_data_dir"]) { if (N_CLI() && N_Windows()) { $GLOBALS["pnkit_data_dir"] = $_ENV["APPDATA"] . "\\pnkit_data_dir"; @mkdir($GLOBALS["pnkit_data_dir"]); } else if (N_CLI()) { $GLOBALS["pnkit_data_dir"] = $_SERVER["HOME"] . "/pnkit_data_dir"; } else if ($pathinfo2["dirname"] && @file_exists($pathinfo2["dirname"] . "/pnkit_data_dir")) { $GLOBALS["pnkit_data_dir"] = $pathinfo2["dirname"] . "/pnkit_data_dir"; } else if ($_SERVER["DOCUMENT_ROOT"] && @file_exists($_SERVER["DOCUMENT_ROOT"] . "/pnkit_data_dir")) { $GLOBALS["pnkit_data_dir"] = $_SERVER["DOCUMENT_ROOT"] . "/pnkit_data_dir"; } else if (@file_exists(getcwd() . "/pnkit_data_dir")) { $GLOBALS["pnkit_data_dir"] = getcwd() . "/pnkit_data_dir"; $_SERVER["DOCUMENT_ROOT"] = getcwd(); // In case DOCUMENT_ROOT makes no sense, e.g. 000webhost.com } else if (session_save_path()) { $sessionpath = session_save_path(); if (strpos($sessionpath, ";") !== FALSE) $sessionpath = substr($sessionpath, strpos($sessionpath, ";") + 1); $GLOBALS["pnkit_data_dir"] = $sessionpath . "/pnkit_data_dir"; } else { $GLOBALS["pnkit_data_dir"] = sys_get_temp_dir() . "/pnkit_data_dir"; } } if (!$GLOBALS["pnkit_public_cache_dir_internal"]) { if (N_CLI() && N_Windows()) { $GLOBALS["pnkit_public_cache_dir_external"] = "***"; $GLOBALS["pnkit_public_cache_dir_internal"] = $_ENV["APPDATA"] . "\\pnkit_public_cache_dir"; @mkdir($GLOBALS["pnkit_public_cache_dir"]); } else if (N_CLI()) { $GLOBALS["pnkit_public_cache_dir_external"] = "***"; $GLOBALS["pnkit_public_cache_dir_internal"] = $_SERVER["HOME"] . "/pnkit_public_cache_dir"; } else { $GLOBALS["pnkit_public_cache_dir_external"] = "/pnkit_public_cache_dir"; $GLOBALS["pnkit_public_cache_dir_internal"] = $_SERVER['DOCUMENT_ROOT'] . $GLOBALS["pnkit_public_cache_dir_external"]; } } if (!$GLOBALS["pnkit_owner_ip"]) { $GLOBALS["pnkit_owner_ip"] = gethostbyname("home.nicodevries.com"); if ($_SERVER["REMOTE_ADDR"] == "188.213.93.254") $GLOBALS["pnkit_owner_ip"] = "188.213.93.254"; // Extra check } if (N_CLI() || $_SERVER["REMOTE_ADDR"] == $GLOBALS["pnkit_owner_ip"] || $_SERVER["REMOTE_ADDR"] == "127.0.0.1") { $GLOBALS["owner"] = true; error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING ^ E_DEPRECATED); ini_set('display_errors', 1); @set_time_limit(7200); } else { error_reporting(0); ini_set('display_errors', 0); } if ($GLOBALS["pnkit_classic"]) { // Keep old crap working foreach ($_REQUEST as $var => $val) { $var = str_replace ("-", "_", $var); @eval("\$$var=unserialize(base64_decode('" . base64_encode(serialize($val)) . "'));"); } foreach ($_SERVER as $var => $val) { $var = str_replace ("-", "_", $var); @eval("\$$var=unserialize(base64_decode('" . base64_encode(serialize($val)) . "'));"); } if (!headers_sent()) header("Content-Type: text/html; charset=ISO-8859-1"); } else { if (!headers_sent()) header('Content-Type: text/html; charset=utf-8'); } if (!ini_get('date.timezone')) date_default_timezone_set("Europe/Amsterdam"); if (!file_exists($GLOBALS["pnkit_data_dir"])) { mkdir($GLOBALS["pnkit_data_dir"]); } if (!file_exists($GLOBALS["pnkit_public_cache_dir_internal"])) { @mkdir($GLOBALS["pnkit_public_cache_dir_internal"]); } if (N_CLI() && N_Windows()) { @mkdir($_ENV["APPDATA"] . "\\pnkit_winassets"); if ($GLOBALS["pnkit_mode"] == "online") { puuse("sys"); SYS_PNKIT_Download("winmanifest2", $_ENV["APPDATA"] . "\\pnkit_winassets\\", "/winassets/"); } } if (array_key_exists("pnkitassets", $_REQUEST)) { $relurl = N_KeepAfter($_SERVER["QUERY_STRING"], "pnkitassets=/"); $ext = pathinfo($relurl, PATHINFO_EXTENSION); $mimemap = N_MimeMap(); if ($mimemap[$ext]) { $mime = $mimemap[$ext]; } else { $mime = "text/plain"; } header("Content-Type: $mime"); $content = N_GetPage("https://fastsimple.com/pnkit/$relurl"); if (strpos($relurl, "6.5.1-web")) { $content = str_replace("'../fonts/fontawesome", "'" . $_SERVER["SCRIPT_NAME"] . "?pnkitassets=/webassets/fontawesome-pro-6.5.1-web/fonts/fontawesome", $content); } else { $content = str_replace("'../fonts/fontawesome", "'" . $_SERVER["SCRIPT_NAME"] . "?pnkitassets=/webassets/startbootstrap-sb-admin-2-1.0.8/bower_components/font-awesome/fonts/fontawesome", $content); $content = str_replace("(../fonts/glyphicons", "(" . $_SERVER["SCRIPT_NAME"] . "?pnkitassets=/webassets/startbootstrap-sb-admin-2-1.0.8/bower_components/bootstrap/dist/fonts/glyphicons", $content); $content = str_replace("'../fonts/glyphicons", "'" . $_SERVER["SCRIPT_NAME"] . "?pnkitassets=/webassets/startbootstrap-sb-admin-2-1.0.8/bower_components/bootstrap/dist/fonts/glyphicons", $content); $content = str_replace("\"font/context-menu-icons.", "\"" . $_SERVER["SCRIPT_NAME"] . "?pnkitassets=/webassets/npm_packages/node_modules/jquery-contextmenu/dist/font/context-menu-icons.", $content); $content = str_replace("url(font/context-menu-icons.", "url(" . $_SERVER["SCRIPT_NAME"] . "?pnkitassets=/webassets/npm_packages/node_modules/jquery-contextmenu/dist/font/context-menu-icons.", $content); $content = str_replace("sourceMappingURL=bootstrap.min.css.map", "sourceMappingURL=" . $_SERVER["SCRIPT_NAME"] . "?pnkitassets=/webassets/startbootstrap-sb-admin-2-1.0.8/bower_components/bootstrap/dist/css/bootstrap.min.css.map", $content); $content = str_replace("sourceMappingURL=jquery.min.map", "sourceMappingURL=" . $_SERVER["SCRIPT_NAME"] . "?pnkitassets=/webassets/startbootstrap-sb-admin-2-1.0.8/bower_components/jquery/dist/jquery.min.map", $content); } $etag = md5($content); header("Etag: $etag"); if (@trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) { header("HTTP/1.1 304 Not Modified"); die(""); } $seconds_to_cache = 604800; $ts = gmdate("D, d M Y H:i:s", time() + $seconds_to_cache) . " GMT"; header("Expires: $ts"); header("Pragma: cache"); header("Cache-Control: max-age=$seconds_to_cache"); die($content); } if (array_key_exists("pnkitdynasset", $_REQUEST)) { header('Content-Type: ' . $_REQUEST["mime"]); if ($_REQUEST["id"]) { die(PMB_Load("n_dynasset", $_REQUEST["id"])); } else { die(base64_decode($_REQUEST["b64_data"])); } } if (array_key_exists("pnkitexec", $_REQUEST)) { N_HandleExecInBackground($_REQUEST["key"]); die(); } if (array_key_exists("pnkitexecnow", $_REQUEST)) { N_HandleExecNow ($_REQUEST["pnkitexecnow"]); die(); } if (array_key_exists("pnkit", $_REQUEST)) { N_PNKIT(); die(); } if (array_key_exists("pnkit_ui_ajax", $_REQUEST)) { puuse ("ui"); UI_HandleAjax ($_REQUEST); die(); } if (array_key_exists("pnkit_pwa_ajax", $_REQUEST)) { puuse ("pwa"); PWA_HandleAjax ($_REQUEST); die(); } /******************************************************************************/ // END } // if (!function_exists ("puuse"))