File Manager
Upload
Current Directory: /home/lartcid/public_html/journal.lartc.id
[Back]
..
[Open]
Hapus
Rename
.htaccess
[Edit]
Hapus
Rename
.well-known
[Open]
Hapus
Rename
README.md
[Edit]
Hapus
Rename
api
[Open]
Hapus
Rename
cache
[Open]
Hapus
Rename
cgi-bin
[Open]
Hapus
Rename
classes
[Open]
Hapus
Rename
config.TEMPLATE.inc.php
[Edit]
Hapus
Rename
config.inc.php
[Edit]
Hapus
Rename
controllers
[Open]
Hapus
Rename
cypress.json
[Edit]
Hapus
Rename
dbscripts
[Open]
Hapus
Rename
docs
[Open]
Hapus
Rename
error_log
[Edit]
Hapus
Rename
favicon.ico
[Edit]
Hapus
Rename
index.php
[Edit]
Hapus
Rename
js
[Open]
Hapus
Rename
lib
[Open]
Hapus
Rename
locale
[Open]
Hapus
Rename
mini.php
[Edit]
Hapus
Rename
pages
[Open]
Hapus
Rename
php.ini
[Edit]
Hapus
Rename
plugins
[Open]
Hapus
Rename
public
[Open]
Hapus
Rename
registry
[Open]
Hapus
Rename
scheduledTaskLogs
[Open]
Hapus
Rename
schemas
[Open]
Hapus
Rename
styles
[Open]
Hapus
Rename
templates
[Open]
Hapus
Rename
tools
[Open]
Hapus
Rename
Edit File
<?php /** * @file classes/core/PKPComponentRouter.inc.php * * Copyright (c) 2014-2021 Simon Fraser University * Copyright (c) 2000-2021 John Willinsky * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. * * @class PKPComponentRouter * @ingroup core * * @brief Class mapping an HTTP request to a component handler operation. * * We are using an RPC style URL-to-endpoint mapping. Our approach follows * a simple "convention-over-configuration" paradigm. If necessary the * router can be subclassed to implement more complex URL-to-endpoint mappings. * * For servers with path info enabled the component URL has the following elements: * * .../index.php/context1/context2/$$$call$$$/path/to/handler-class/operation-name?arg1=...&arg2=... * * where "$$$call$$$" is a non-mutable literal string and "path/to" is * by convention the directory path below the "controllers" folder leading to the * component. The next element ("handler-class" in this example) will be mapped to a * component class file by "camelizing" the string to "HandlerClassHandler" and adding * ".inc.php" to the end. The "operation-name" is transformed to "operationName" * and represents the name of the handler method to be called. Finally "arg1", "arg2", * etc. are parameters to be passed along to the handler method. * * For servers with path info disabled the component URL looks like this: * * .../index.php?component=path.to.handler-class&op=operation-name&arg1=...&arg2=... * * The router will sanitize the request URL to a certain amount to make sure that * random code inclusions are prevented. User authorization and parameter validation * are however not the router's concern. These must be implemented on handler level. * * NB: Component and operation names may only contain a-z, 0-9 and hyphens. Numbers * are not allowed at the beginning of a name or after a hyphen. * * NB: Component handlers must implement an initialize() method that will be called * before the request is routed. The initialization method must enforce authorization * and request validation. */ // The string to be found in the URL to mark this request as a component request define('COMPONENT_ROUTER_PATHINFO_MARKER', '$$$call$$$'); // The parameter to be found in the query string for servers with path info disabled define('COMPONENT_ROUTER_PARAMETER_MARKER', 'component'); // This is the maximum directory depth allowed within the component directory. Set // it to something reasonable to avoid DoS or overflow attacks define ('COMPONENT_ROUTER_PARTS_MAXDEPTH', 9); // This is the maximum/minimum length of the name of a sub-directory or // handler class name. define ('COMPONENT_ROUTER_PARTS_MAXLENGTH', 50); define ('COMPONENT_ROUTER_PARTS_MINLENGTH', 2); import('lib.pkp.classes.core.PKPRouter'); import('classes.core.Request'); class PKPComponentRouter extends PKPRouter { // // Internal state cache variables // NB: Please do not access directly but // only via their respective getters/setters // /** @var string the requested component handler */ var $_component; /** @var string the requested operation */ var $_op; /** @var array the rpc service endpoint parts from the request */ var $_rpcServiceEndpointParts = false; /** @var callable the rpc service endpoint the request was routed to */ var $_rpcServiceEndpoint = false; /** * Determines whether this router can route the given request. * @param $request PKPRequest * @return boolean true, if the router supports this request, otherwise false */ function supports($request) { // See whether this looks like a component router request. // NOTE: this is prone to false positives i.e. when a class // name cannot be matched, but this laxity permits plugins to // extend the system by registering against the // LoadComponentHandler hook. return $this->_retrieveServiceEndpointParts($request) !== null; } /** * Retrieve the requested component from the request. * * NB: This can be a component that not actually exists * in the code base. * * @param $request PKPRequest * @return string the requested component or an empty string * if none can be found. */ function getRequestedComponent($request) { if (is_null($this->_component)) { $this->_component = ''; // Retrieve the service endpoint parts from the request. if (is_null($rpcServiceEndpointParts = $this->_getValidatedServiceEndpointParts($request))) { // Endpoint parts cannot be found in the request return ''; } // Pop off the operation part array_pop($rpcServiceEndpointParts); // Construct the fully qualified component class name from the rest of it. $handlerClassName = PKPString::camelize(array_pop($rpcServiceEndpointParts), CAMEL_CASE_HEAD_UP).'Handler'; // camelize remaining endpoint parts $camelizedRpcServiceEndpointParts = array(); foreach ( $rpcServiceEndpointParts as $part) { $camelizedRpcServiceEndpointParts[] = PKPString::camelize($part, CAMEL_CASE_HEAD_DOWN); } $handlerPackage = implode('.', $camelizedRpcServiceEndpointParts); $this->_component = $handlerPackage.'.'.$handlerClassName; } return $this->_component; } /** * Retrieve the requested operation from the request * * NB: This can be an operation that not actually * exists in the requested component. * * @param $request PKPRequest * @return string the requested operation or an empty string * if none can be found. */ function getRequestedOp($request) { if (is_null($this->_op)) { $this->_op = ''; // Retrieve the service endpoint parts from the request. if (is_null($rpcServiceEndpointParts = $this->_getValidatedServiceEndpointParts($request))) { // Endpoint parts cannot be found in the request return ''; } // Pop off the operation part $this->_op = PKPString::camelize(array_pop($rpcServiceEndpointParts), CAMEL_CASE_HEAD_DOWN); } return $this->_op; } /** * Get the (validated) RPC service endpoint from the request. * If no such RPC service endpoint can be constructed then the method * returns null. * @param $request PKPRequest the request to be routed * @return callable an array with the handler instance * and the handler operation to be called by call_user_func(). */ function &getRpcServiceEndpoint($request) { if ($this->_rpcServiceEndpoint === false) { // We have not yet resolved this request. Mark the // state variable so that we don't try again next // time. $this->_rpcServiceEndpoint = $nullVar = null; // Retrieve requested component operation $op = $this->getRequestedOp($request); assert(!empty($op)); // // Component Handler // // Retrieve requested component handler $component = $this->getRequestedComponent($request); $allowedPackages = null; // Give plugins a chance to intervene if (!HookRegistry::call('LoadComponentHandler', array(&$component, &$op))) { if (empty($component)) return $nullVar; // Construct the component handler file name and test its existence. $component = 'controllers.'.$component; $componentFileName = str_replace('.', DIRECTORY_SEPARATOR, $component).'.inc.php'; switch (true) { case file_exists($componentFileName): break; case file_exists(PKP_LIB_PATH . DIRECTORY_SEPARATOR . $componentFileName): $component = 'lib.pkp.'.$component; break; default: // Request to non-existent handler return $nullVar; } // We expect the handler to be part of one // of the following packages: $allowedPackages = array( 'controllers', 'lib.pkp.controllers' ); } // A handler at least needs to implement the // following methods: $requiredMethods = array( $op, 'authorize', 'validate', 'initialize' ); $componentInstance =& instantiate($component, 'PKPHandler', $allowedPackages, $requiredMethods); if (!is_object($componentInstance)) return $nullVar; $this->setHandler($componentInstance); // // Callable service endpoint // // Construct the callable array $this->_rpcServiceEndpoint = array($componentInstance, $op); } return $this->_rpcServiceEndpoint; } // // Implement template methods from PKPRouter // /** * @copydoc PKPRouter::route() */ function route($request) { // Determine the requested service endpoint. $rpcServiceEndpoint =& $this->getRpcServiceEndpoint($request); // Retrieve RPC arguments from the request. $args = $request->getUserVars(); assert(is_array($args)); // Remove the caller-parameter (if present) if (isset($args[COMPONENT_ROUTER_PARAMETER_MARKER])) unset($args[COMPONENT_ROUTER_PARAMETER_MARKER]); // Authorize, validate and initialize the request $this->_authorizeInitializeAndCallRequest($rpcServiceEndpoint, $request, $args); } /** * @copydoc PKPRouter::url() */ function url($request, $newContext = null, $component = null, $op = null, $path = null, $params = null, $anchor = null, $escape = false) { if (!is_null($path)) { throw new Exception('Path must be null when calling PKPComponentRouter::url()'); } $pathInfoEnabled = $request->isPathInfoEnabled(); // // Base URL and Context // $baseUrlAndContext = $this->_urlGetBaseAndContext( $request, $this->_urlCanonicalizeNewContext($newContext)); $baseUrl = array_shift($baseUrlAndContext); $context = $baseUrlAndContext; // // Component and Operation // // We only support component/op retrieval from the request // if this request is a component request. $currentRequestIsAComponentRequest = is_a($request->getRouter(), 'PKPComponentRouter'); if($currentRequestIsAComponentRequest) { if (empty($component)) $component = $this->getRequestedComponent($request); if (empty($op)) $op = $this->getRequestedOp($request); } assert(!empty($component) && !empty($op)); // Encode the component and operation $componentParts = explode('.', $component); $componentName = array_pop($componentParts); assert(substr($componentName, -7) == 'Handler'); $componentName = PKPString::uncamelize(substr($componentName, 0, -7)); // uncamelize the component parts $uncamelizedComponentParts = array(); foreach ($componentParts as $part) { $uncamelizedComponentParts[] = PKPString::uncamelize($part); } array_push($uncamelizedComponentParts, $componentName); $opName = PKPString::uncamelize($op); // // Additional query parameters // $additionalParameters = $this->_urlGetAdditionalParameters($request, $params, $escape); // // Anchor // $anchor = (empty($anchor) ? '' : '#'.rawurlencode($anchor)); // // Assemble URL // if ($pathInfoEnabled) { // If path info is enabled then context, page, // operation and additional path go into the // path info. $pathInfoArray = array_merge( $context, array(COMPONENT_ROUTER_PATHINFO_MARKER), $uncamelizedComponentParts, array($opName) ); // Query parameters $queryParametersArray = $additionalParameters; } else { // If path info is disabled then context, page, // operation and additional path are encoded as // query parameters. $pathInfoArray = array(); // Query parameters $queryParametersArray = array_merge( $context, array( COMPONENT_ROUTER_PARAMETER_MARKER.'='.implode('.', $uncamelizedComponentParts), "op=$opName" ), $additionalParameters ); } return $this->_urlFromParts($baseUrl, $pathInfoArray, $queryParametersArray, $anchor, $escape); } /** * @copydoc PKPRouter::handleAuthorizationFailure() */ function handleAuthorizationFailure( $request, $authorizationMessage, array $messageParams = [] ) { // Translate the authorization error message. if (defined('LOCALE_COMPONENT_APP_COMMON')) { AppLocale::requireComponents(LOCALE_COMPONENT_APP_COMMON); } AppLocale::requireComponents(LOCALE_COMPONENT_PKP_USER); $translatedAuthorizationMessage = __($authorizationMessage, $messageParams); // Add the router name and operation if show_stacktrace is enabled. if (Config::getVar('debug', 'show_stacktrace')) { $url = $request->getRequestUrl(); $queryString = $request->getQueryString(); if ($queryString) $queryString = '?'.$queryString; $translatedAuthorizationMessage .= ' ['.$url.$queryString.']'; } // Return a JSON error message. import('lib.pkp.classes.core.JSONMessage'); return new JSONMessage(false, $translatedAuthorizationMessage); } // // Private helper methods // /** * Get the (validated) RPC service endpoint parts from the request. * If no such RPC service endpoint parts can be retrieved * then the method returns null. * @param $request PKPRequest the request to be routed * @return array a string array with the RPC service endpoint * parts as values. */ function _getValidatedServiceEndpointParts($request) { if ($this->_rpcServiceEndpointParts === false) { // Mark the internal state variable so this // will not be called again. $this->_rpcServiceEndpointParts = null; // Retrieve service endpoint parts from the request. if (is_null($rpcServiceEndpointParts = $this->_retrieveServiceEndpointParts($request))) { // This is not an RPC request return null; } // Validate the service endpoint parts. if (is_null($rpcServiceEndpointParts = $this->_validateServiceEndpointParts($rpcServiceEndpointParts))) { // Invalid request return null; } // Assign the validated service endpoint parts $this->_rpcServiceEndpointParts = $rpcServiceEndpointParts; } return $this->_rpcServiceEndpointParts; } /** * Try to retrieve a (non-validated) array with the service * endpoint parts from the request. See the classdoc for the * URL patterns supported here. * @param $request PKPRequest the request to be routed * @return array an array of (non-validated) service endpoint * parts or null if the request is not an RPC request. */ function _retrieveServiceEndpointParts($request) { // URL pattern depends on whether the server has path info // enabled or not. See classdoc for details. if ($request->isPathInfoEnabled()) { if (!isset($_SERVER['PATH_INFO'])) return null; $pathInfoParts = explode('/', trim($_SERVER['PATH_INFO'], '/')); // We expect at least the context + the component // router marker + 3 component parts (path, handler, operation) $application = $this->getApplication(); $contextDepth = $application->getContextDepth(); if (count($pathInfoParts) < $contextDepth + 4) { // This path info is too short to be an RPC request return null; } // Check the component router marker if ($pathInfoParts[$contextDepth] != COMPONENT_ROUTER_PATHINFO_MARKER) { // This is not an RPC request return null; } // Remove context and component marker from the array $rpcServiceEndpointParts = array_slice($pathInfoParts, $contextDepth + 1); } else { $componentParameter = $request->getUserVar(COMPONENT_ROUTER_PARAMETER_MARKER); $operationParameter = $request->getUserVar('op'); if (is_null($componentParameter) || is_null($operationParameter)) { // This is not an RPC request return null; } // Expand the router parameter $rpcServiceEndpointParts = explode('.', $componentParameter); // Add the operation array_push($rpcServiceEndpointParts, $operationParameter); } return $rpcServiceEndpointParts; } /** * This method pre-validates the service endpoint parts before * we try to convert them to a file/method name. This also * converts all parts to lower case. * @param $rpcServiceEndpointParts array * @return array the validated service endpoint parts or null if validation * does not succeed. */ function _validateServiceEndpointParts($rpcServiceEndpointParts) { // Do we have data at all? if (is_null($rpcServiceEndpointParts) || empty($rpcServiceEndpointParts) || !is_array($rpcServiceEndpointParts)) return null; // We require at least three parts: component directory, handler // and method name. if (count($rpcServiceEndpointParts) < 3) return null; // Check that the array dimensions remain within sane limits. if (count($rpcServiceEndpointParts) > COMPONENT_ROUTER_PARTS_MAXDEPTH) return null; // Validate the individual endpoint parts. foreach($rpcServiceEndpointParts as $key => $rpcServiceEndpointPart) { // Make sure that none of the elements exceeds the length limit. $partLen = strlen($rpcServiceEndpointPart); if ($partLen > COMPONENT_ROUTER_PARTS_MAXLENGTH || $partLen < COMPONENT_ROUTER_PARTS_MINLENGTH) return null; // Service endpoint URLs are case insensitive. $rpcServiceEndpointParts[$key] = strtolower_codesafe($rpcServiceEndpointPart); // We only allow letters, numbers and the hyphen. if (!PKPString::regexp_match('/^[a-z0-9-]*$/', $rpcServiceEndpointPart)) return null; } return $rpcServiceEndpointParts; } }
Simpan