function qualified_name(string $file, $node, string $namespace) { global $namespace_map; if (!$node instanceof \ast\Node && $node->kind != \ast\AST_NAME) { return var_name($node); } $name = $node->children[0]; $lname = strtolower($name); if ($node->flags & \ast\flags\NAME_NOT_FQ) { // is it a simple native type name? if (is_native_type($lname)) { return $name; } // Not fully qualified, check if we have an exact namespace alias for it if (!empty($namespace_map[T_CLASS][$file][$lname])) { return $namespace_map[T_CLASS][$file][$lname]; } // Check for a namespace-relative alias if (($pos = strpos($lname, '\\')) !== false) { $first_part = substr($lname, 0, $pos); if (!empty($namespace_map[T_CLASS][$file][$first_part])) { // Replace that first aliases part and return the full name return $namespace_map[T_CLASS][$file][$first_part] . '\\' . substr($name, $pos + 1); } } // No aliasing, just prepend the namespace return $namespace . $name; } else { // It is already fully qualified, just return it return $name; } }
function find_class($node, $namespace, $nmap) { global $classes; if (!$node instanceof \ast\Node || $node->kind != \ast\AST_NAME) { Log::err(Log::EFATAL, "BUG: Bad node passed to find_class"); return null; } $name = strtolower(var_name($node->children[0])); if ($node->flags & \ast\flags\NAME_NOT_FQ) { if (!empty($nmap[strtolower($name)])) { if (!empty($classes[strtolower($nmap[$name])])) { return $classes[strtolower($nmap[$name])]; } } if (!empty($classes[$namespace . $name])) { return $classes[$namespace . $name]; } } else { if (empty($classes[$name])) { return null; } else { return $classes[$name]; } } return null; }
function node_type($file, $node, $current_scope, &$taint = null, $check_var_exists = true) { global $classes, $functions, $namespace, $internal_arginfo; if (!$node instanceof \ast\Node) { return type_map(gettype($node)); } else { if ($node->kind == \ast\AST_ARRAY) { return 'array'; } else { if ($node->kind == \ast\AST_BINARY_OP) { $taint = var_taint_check($file, $node, $current_scope); switch ($node->flags) { // Always a string from a concat case \ast\flags\BINARY_CONCAT: $temp_taint = false; node_type($file, $node->children[0], $current_scope, $temp_taint); if ($temp_taint) { $taint = true; return 'string'; } node_type($file, $node->children[1], $current_scope, $temp_taint); if ($temp_taint) { $taint = true; } return 'string'; break; // Boolean unless invalid operands // Boolean unless invalid operands case \ast\flags\BINARY_IS_IDENTICAL: case \ast\flags\BINARY_IS_NOT_IDENTICAL: case \ast\flags\BINARY_IS_EQUAL: case \ast\flags\BINARY_IS_NOT_EQUAL: case \ast\flags\BINARY_IS_SMALLER: case \ast\flags\BINARY_IS_SMALLER_OR_EQUAL: $taint = false; return 'bool'; break; // Everything else should be an int/float // Everything else should be an int/float default: $left = type_map(node_type($file, $node->children[0], $current_scope)); $right = type_map(node_type($file, $node->children[1], $current_scope)); if ($left == 'array' && $right != 'array') { Log::err(Log::ETYPE, "invalid operator: left operand is array and right is not", $file, $node->lineno); return 'mixed'; } else { if ($right == 'array' && $left != 'array') { Log::err(Log::ETYPE, "invalid operator: right operand is array and left is not", $file, $node->lineno); return 'mixed'; } else { if ($left == 'int' && $right == 'int') { return 'int'; } else { if ($left == 'float' || $right == 'float') { return 'float'; } } } } $taint = false; return $left; break; } } else { if ($node->kind == \ast\AST_CAST) { $taint = var_taint_check($file, $node->children[0], $current_scope); switch ($node->flags) { case \ast\flags\TYPE_NULL: return 'null'; break; case \ast\flags\TYPE_BOOL: $taint = false; return 'bool'; break; case \ast\flags\TYPE_LONG: $taint = false; return 'int'; break; case \ast\flags\TYPE_DOUBLE: $taint = false; return 'float'; break; case \ast\flags\TYPE_STRING: return 'string'; break; case \ast\flags\TYPE_ARRAY: return 'array'; break; case \ast\flags\TYPE_OBJECT: return 'object:stdClass'; break; default: Log::err(Log::EFATAL, "Unknown type (" . $node->flags . ") in cast"); } } else { if ($node->kind == \ast\AST_NEW) { if ($node->children[0]->kind == \ast\AST_NAME) { $name = var_name($node->children[0]); if ($name == 'self' || $name == 'static') { list($class, ) = explode('::', $current_scope); $name = $class; } if (empty($classes[$namespace . strtolower($name)]) && empty($classes[strtolower($name)])) { Log::err(Log::EUNDEF, "Trying to instantiate undeclared class {$name}", $file, $node->lineno); } return 'object:' . $name; } return 'object'; } else { if ($node->kind == \ast\AST_DIM) { $taint = var_taint_check($file, $node->children[0], $current_scope); // TODO: Do something smart with array elements return 'mixed'; } else { if ($node->kind == \ast\AST_VAR) { return var_type($file, $node, $current_scope, $taint, $check_var_exists); } else { if ($node->kind == \ast\AST_ENCAPS_LIST) { foreach ($node->children as $encap) { if ($encap instanceof \ast\Node) { if (var_taint_check($file, $encap, $current_scope)) { $taint = true; } } } return "string"; } else { if ($node->kind == \ast\AST_CONST) { if ($node->children[0]->kind == \ast\AST_NAME) { if (defined($node->children[0]->children[0])) { return type_map(gettype(constant($node->children[0]->children[0]))); } else { // User-defined constant } } } else { if ($node->kind == \ast\AST_CALL) { if ($node->children[0]->kind == \ast\AST_NAME) { $func_name = $node->children[0]->children[0]; $func = $functions[strtolower($namespace . $func_name)] ?? $functions[strtolower($func_name)] ?? null; if ($func['file'] == 'internal' && empty($func['ret'])) { if (!empty($internal_arginfo[$func_name])) { return $internal_arginfo[$func_name][0] ?? 'mixed'; } } else { return $func['ret'] ?? 'mixed'; } } else { // TODO: Handle $func() and other cases that get here } } else { if ($node->kind == \ast\AST_STATIC_CALL) { // If the called static method has a return type defined, use that $call = $node->children[0]; if ($call->kind == \ast\AST_NAME) { // Simple static function call $class_name = $call->children[0]; $method_name = $node->children[1]; $method = find_method($namespace . $class_name, $method_name); if (!$method) { find_method($class_name, $method_name); } if ($method) { return $method['ret'] ?? 'mixed'; } } else { // Weird dynamic static call - give up return 'mixed'; } } } } } } } } } } } } return "mixed"; }
_session_start(); if (!$_SESSION["alogin"]) { header("Location: login.php"); exit; } if (isset($_GET['set']) && $_GET['set'] == 'set') { $db->update('setting', ['value' => $_POST["sitename"]], ['name' => "sitename"]); $db->ExecuteSQL(sprintf("UPDATE `setting` SET `value` = '%s' WHERE `setting`.`name` = 'sitetitle';", $db->databaseLink->real_escape_string($_POST["sitetitle"]))); $settingsToUpdate = ["size", "url", "total", "admin", "subtitle"]; foreach ($settingsToUpdate as $key => $value) { $db->update('setting', ['value' => $_POST[$value]], ['name' => var_name($value)]); } $settingsToUpdate = ["tos", "why", "reg"]; foreach ($settingsToUpdate as $key => $value) { ${$value} = !isset($_POST[$value]) || $_POST[$value] != "true" ? "false" : "true"; $db->update('setting', ['value' => $value], ['name' => var_name($value)]); } header("Location: setting.php?s=1"); exit; } $successMsg = isset($_GET['s']) && $_GET['s'] == "1" ? "<div class=\"alert alert-success\">設定修改完成。</div>" : ""; ?> <!DOCTYPE html> <html> <head> <title>管理員介面 - <?php echo $config["sitename"]; ?> </title>
function render_partial($action, $object = false, $collect = false, $controller = false) { #if the controller is an array, use it and ignore the rest if (is_array($action)) { if (array_key_exists('object', $action)) { $object = $action['object']; } if (array_key_exists('collect', $action)) { $collect = $action['collect']; } if (array_key_exists('controller', $action)) { $controller = $action['controller']; } if (array_key_exists('action', $action)) { $action = $action['action']; } } else { if ($controller == false) { $controller = params('controller'); } } # set the template and object name $slashloc = strrpos($action, '/'); if ($slashloc !== false) { $objectname = substr($action, $slashloc + 1); if ($action[0] == '/') { $template = substr(substr($action, 0, $slashloc) . '/_' . $objectname, 1); } else { $template = url_name($controller) . '/' . substr($action, 0, $slashloc) . '/_' . $objectname; } } else { $template = url_name($controller) . '/_' . $action; $objectname = $action; } $view = ViewFactory::make_view($template); # include the helpers if (file_exists(PROJECT_ROOT . '/app/helpers/app.php')) { include_once PROJECT_ROOT . '/app/helpers/app.php'; } if (file_exists(PROJECT_ROOT . '/app/helpers/' . $controller . '.php')) { include_once PROJECT_ROOT . '/app/helpers/' . $controller . '.php'; } # if it's a collection, call it for each item in the obj $objectname = var_name(class_name($objectname)); if ($collect === true) { foreach ($object as $k => $v) { echo $view->parse_partial($objectname, $v); } } else { echo $view->parse_partial($objectname, $object); } }