join($path); } public static function setHeaderNoCache() { if (!headers_sent()) { header('Expires: Wed, 01 Jan 2014 00:00:00 GMT'); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header('Cache-Control: no-store, no-cache, must-revalidate'); header('Cache-Control: post-check=0, pre-check=0', false); header('Pragma: no-cache'); } } public static function isAJAX() { return strtolower($_SERVER['HTTP_X_REQUESTED_WITH'] ?? null) === 'xmlhttprequest'; } public static function requireAJAX(): void { if (!static::isAJAX()) { Json::die([ 'result' => false, 'reason' => 'no ajax' ]); } } /** * @return mixed|mixed[] */ public static function parseJsonPost() { // http://thisinterestsme.com/receiving-json-post-data-via-php/ // http://thisinterestsme.com/php-json-error-handling/ if (strcasecmp($_SERVER['REQUEST_METHOD'], 'POST') != 0) { throw new \Exception('Request method must be POST!'); } //Make sure that the content type of the POST request has been set to application/json $contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : ''; if (strcasecmp($contentType, 'application/json') != 0) { throw new \Exception('Content type must be: application/json'); } //Receive the RAW post data. $content = trim(file_get_contents("php://input")); //Attempt to decode the incoming RAW post data from JSON. $decoded = Json::decode($content); $jsonError = json_last_error(); //In some cases, this will happen. if (is_null($decoded) && $jsonError == JSON_ERROR_NONE) { throw new \Exception('Could not decode JSON!'); } //If an error exists. if ($jsonError != JSON_ERROR_NONE) { $error = 'Could not decode JSON! '; //Use a switch statement to figure out the exact error. switch ($jsonError) { case JSON_ERROR_DEPTH: $error .= 'Maximum depth exceeded! : ' . $content; break; case JSON_ERROR_STATE_MISMATCH: $error .= 'Underflow or the modes mismatch! : ' . $content; break; case JSON_ERROR_CTRL_CHAR: $error .= 'Unexpected control character found : ' . $content; break; case JSON_ERROR_SYNTAX: $error .= 'Malformed JSON : ' . $content; break; case JSON_ERROR_UTF8: $error .= 'Malformed UTF-8 characters found! : ' . $content; break; default: $error .= 'Unknown error! : ' . $content; break; } throw new \Exception($error); } return $decoded; } public static function preloadAsset(string $path, string $type) { $upath = \phpUri::parse($path); $path = $upath->join(''); if (!$upath->scheme) { if (!file_exists($upath->path)) { return "\n"; } $mtime = filemtime($upath->path); if ($upath->query) { $tail = '&' . $mtime; } else { $tail = '?' . $mtime; } } else { $tail = ''; } return "\n"; } public static function preloadCSS(string $path) { return static::preloadAsset($path, 'style'); } public static function preloadJS(string $path) { return static::preloadAsset($path, 'script'); } public static function printDist(string $type, string|array $entryName, bool $isDefer = false) { if (is_string($entryName)) { $entryName = [$entryName]; } $serverBasePath = \phpUri::parse(ServConfig::$serverWebPath)->path; if ($type == 'gateway') { $serverBasePath .= "/dist_js/{$type}"; $basePath = dirname(__DIR__, 2) . "/dist_js/{$type}"; } else { if (!class_exists('\\sammo\\VersionGit') || is_subclass_of('\\sammo\\VersionGit', '\\sammo\\VersionGitDynamic')) { $version = DB::prefix() . '_dynamic'; } else { $version = VersionGit::getVersion(); } $serverBasePath .= "/dist_js/{$version}/{$type}"; $basePath = dirname(__DIR__, 2) . "/dist_js/{$version}/{$type}"; } $outputs = ["\n"]; foreach (["vendors", "common_ts", ...$entryName] as $moduleName) { foreach (['js', 'css'] as $ext) { $checkPath = $basePath . "/{$moduleName}.{$ext}"; if (!file_exists($checkPath)) { $outputs[] = "\n"; continue; } $mtime = filemtime($checkPath); if ($ext == 'css') { $outputs[] = "\n"; } else if ($ext == 'js') { $typeText = $isDefer ? 'defer' : ''; $outputs[] = "\n"; } } } return join("", $outputs); } public static function printJS(string $path, bool $isDefer = false) { //async 옵션 고려? $upath = \phpUri::parse($path); $path = $upath->join(''); if (!$upath->scheme) { if (!file_exists($upath->path)) { return "\n"; } $mtime = filemtime($upath->path); if ($upath->query) { $tail = '&' . $mtime; } else { $tail = '?' . $mtime; } } else { $tail = ''; } $typeText = $isDefer ? 'defer' : ''; return "\n"; } public static function printCSS(string $path) { $upath = \phpUri::parse($path); $path = $upath->join(''); if (!$upath->scheme) { if (!file_exists($upath->path)) { return "\n"; } $mtime = filemtime($upath->path); if ($upath->query) { $tail = '&' . $mtime; } else { $tail = '?' . $mtime; } } else { $tail = ''; } return "\n"; } public static function printStaticValues(array $values, bool $pretty = true) { if (!count($values)) { return; } $lines = ["\n"; return join("\n", $lines); } public static function htmlPurify(?string $text): string { if (!$text) { return ''; } $config = \HTMLPurifier_HTML5Config::createDefault(); $config->set('Filter.Custom', array(new \HTMLPurifier_Filter_YouTube())); $config->set('HTML.SafeIframe', true); $config->set('URI.SafeIframeRegexp', '%^(https?:)?//(www\.youtube(?:-nocookie)?\.com/embed/|player\.vimeo\.com/video/)%'); //allow YouTube and Vimeo $def = $config->getHTMLDefinition(); $def->info_global_attr['data-flip'] = new \HTMLPurifier_AttrDef_Text; $purifier = new \HTMLPurifier($config); return $purifier->purify($text); } public static function errorBackMsg(string $msg, ?string $target = null): string { $jmsg = Json::encode($msg); if (!$target) { $moveNext = 'history.go(-1);'; } else { $moveNext = "location.replace('{$target}');"; } return "
"; } public static function drawMenu(string $path): string { if (!file_exists($path)) { return ''; } $json = Json::decode(file_get_contents($path)); $result = []; foreach ($json as $menuItem) { if (count($menuItem) == 2) { [$url, $title] = $menuItem; $targetAttr = ''; } else { [$url, $title, $target] = $menuItem; $target = htmlspecialchars($target); $targetAttr = "target='$target' "; } $title = htmlspecialchars($title); $url = htmlspecialchars($url); $result[] = "$title"; } return join("\n", $result); } }