JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-}JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-}JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-}JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-}JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-}JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-}JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-}JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-}JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-}JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-}JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-}JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-}JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-}JFIFICC_PROFILElcmsmntrRGB XYZ  acspMSFTsawsctrl-hand=@=@t," desc_cprt wtptrXYZ,gXYZ@bXYZTrTRCh`gTRCh`bTRCh`descuRGBtextCC0XYZ TXYZ o8XYZ bXYZ $curv*|uN  bj. C$)j.~39?FWM6Tv\dluV~,6۾ewC    #%$""!&+7/&)4)!"0A149;>>>%.DIC;C  ;("(;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|WH?cS?Ne.r˿ޱ5\YYhFOejT7PZ[qs2c/$Ep[Gqo(Nù=QHci;OipX=Ģ8d^mQeӴm1OsL/x2];i6p!zU -/uX!=<-} .
LIBYA CYBER ARMY
Logo of a company Instagram@3g86    Server : Apache
System : Linux uta-edu.server.ly 4.18.0-513.11.1.el8_9.x86_64 #1 SMP Wed Jan 17 02:00:40 EST 2024 x86_64
User : utripoli ( 1001)
PHP Version : 7.4.33
Disable Function : NONE
Directory :  /home/utripoli/public_html/alqalam/lib/pkp/classes/core/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/utripoli/public_html/alqalam/lib/pkp/classes/core/PKPComponentRouter.php
<?php

/**
 * @file classes/core/PKPComponentRouter.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
 *  ".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.
 */

namespace PKP\core;

use Exception;
use PKP\config\Config;
use PKP\plugins\Hook;

// 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);

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 */
    public $_component;
    /** @var string the requested operation */
    public $_op;
    /** @var array the rpc service endpoint parts from the request */
    public $_rpcServiceEndpointParts = false;
    /** @var callable the rpc service endpoint the request was routed to */
    public $_rpcServiceEndpoint = false;


    /**
     * Determines whether this router can route the given request.
     *
     * @param PKPRequest $request
     *
     * @return bool true, if the router supports this request, otherwise false
     */
    public function supports($request): bool
    {
        // 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 PKPRequest $request
     *
     * @return string the requested component or an empty string
     *  if none can be found.
     */
    public 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), PKPString::CAMEL_CASE_HEAD_UP) . 'Handler';

            // camelize remaining endpoint parts
            $camelizedRpcServiceEndpointParts = [];
            foreach ($rpcServiceEndpointParts as $part) {
                $camelizedRpcServiceEndpointParts[] = PKPString::camelize($part, PKPString::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 PKPRequest $request
     *
     * @return string the requested operation or an empty string
     *  if none can be found.
     */
    public 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), PKPString::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 PKPRequest $request the request to be routed
     *
     * @return callable|array|null an array with the handler instance
     *  and the handler operation to be called by call_user_func().
     */
    public 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);
            $componentInstance = null;
            $allowedPackages = null;

            // Give plugins a chance to intervene
            if (!Hook::call('LoadComponentHandler', [&$component, &$op, &$componentInstance])) {
                if (empty($component)) {
                    return $nullVar;
                }

                // Construct the component handler file name and test its existence.
                $component = 'controllers.' . $component;
                $componentFileNamePart = str_replace('.', '/', $component);
                switch (true) {
                    case file_exists("{$componentFileNamePart}.php"):
                        $className = 'APP\\' . strtr($componentFileNamePart, '/', '\\');
                        $componentInstance = new $className();
                        break;

                    case file_exists("{$componentFileNamePart}.inc.php"):
                        // This behaviour is DEPRECATED as of 3.4.0.
                        break;

                    case file_exists(PKP_LIB_PATH . "/{$componentFileNamePart}.php"):
                        $className = 'PKP\\' . strtr($componentFileNamePart, '/', '\\');
                        $componentInstance = new $className();
                        break;

                    case file_exists(PKP_LIB_PATH . "/{$componentFileNamePart}.inc.php"):
                        // This behaviour is DEPRECATED as of 3.4.0.
                        $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 = [
                    'controllers',
                    'lib.pkp.controllers'
                ];
            }

            // A handler at least needs to implement the
            // following methods:
            $requiredMethods = [
                $op, 'authorize', 'validate', 'initialize'
            ];

            if (!$componentInstance) {
                $componentInstance = instantiate($component, 'PKPHandler', $allowedPackages, $requiredMethods);
            }
            if (!is_object($componentInstance)) {
                return $nullVar;
            }
            $this->setHandler($componentInstance);

            //
            // Callable service endpoint
            //
            // Construct the callable array
            $this->_rpcServiceEndpoint = [$componentInstance, $op];
        }

        return $this->_rpcServiceEndpoint;
    }


    //
    // Implement template methods from PKPRouter
    //
    /**
     * @copydoc PKPRouter::route()
     */
    public 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()
     *
     * @param null|mixed $newContext
     * @param null|mixed $component
     * @param null|mixed $op
     * @param null|mixed $path
     * @param null|mixed $params
     * @param null|mixed $anchor
     */
    public 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()');
        }

        //
        // Base URL and Context
        //
        [$baseUrl, $context] = $this->_urlGetBaseAndContext($request, $newContext);

        //
        // Component and Operation
        //
        // We only support component/op retrieval from the request
        // if this request is a component request.
        $currentRequestIsAComponentRequest = $request->getRouter() instanceof self;
        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 = [];
        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
        //
        // Context, page, operation and additional path go into the path info.
        $pathInfoArray = array_merge(
            $context,
            [COMPONENT_ROUTER_PATHINFO_MARKER],
            $uncamelizedComponentParts,
            [$opName]
        );

        // Query parameters
        $queryParametersArray = $additionalParameters;

        return $this->_urlFromParts($baseUrl, $pathInfoArray, $queryParametersArray, $anchor, $escape);
    }

    /**
     * @copydoc PKPRouter::handleAuthorizationFailure()
     */
    public function handleAuthorizationFailure(
        $request,
        $authorizationMessage,
        array $messageParams = []
    ) {
        $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.
        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 PKPRequest $request the request to be routed
     *
     * @return ?array a string array with the RPC service endpoint
     *  parts as values.
     */
    public 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 PKPRequest $request 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.
     */
    public function _retrieveServiceEndpointParts($request)
    {
        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();
        if (count($pathInfoParts) < 5) {
            // This path info is too short to be an RPC request
            return null;
        }

        // Check the component router marker
        if ($pathInfoParts[1] != COMPONENT_ROUTER_PATHINFO_MARKER) {
            // This is not an RPC request
            return null;
        }

        // Remove context and component marker from the array
        $rpcServiceEndpointParts = array_slice($pathInfoParts, 2);

        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 array $rpcServiceEndpointParts
     *
     * @return ?array the validated service endpoint parts or null if validation
     *  does not succeed.
     */
    public 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;
    }
}

if (!PKP_STRICT_MODE) {
    class_alias('\PKP\core\PKPComponentRouter', '\PKPComponentRouter');
}

3g86 2022