"Fossies" - the Fresh Open Source Software Archive

Member "drupal-9.4.5/vendor/laminas/laminas-feed/src/PubSubHubbub/AbstractCallback.php" (24 Mar 2022, 10793 Bytes) of package /linux/www/drupal-9.4.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 <?php
    2 
    3 namespace Laminas\Feed\PubSubHubbub;
    4 
    5 use Laminas\Http\PhpEnvironment\Response as PhpResponse;
    6 use Laminas\Stdlib\ArrayUtils;
    7 use Traversable;
    8 
    9 use function array_key_exists;
   10 use function file_get_contents;
   11 use function function_exists;
   12 use function gettype;
   13 use function intval;
   14 use function is_array;
   15 use function is_resource;
   16 use function sprintf;
   17 use function str_replace;
   18 use function stream_get_contents;
   19 use function strlen;
   20 use function strpos;
   21 use function strtoupper;
   22 use function substr;
   23 use function trim;
   24 
   25 abstract class AbstractCallback implements CallbackInterface
   26 {
   27     /**
   28      * An instance of Laminas\Feed\Pubsubhubbub\Model\SubscriptionPersistenceInterface
   29      * used to background save any verification tokens associated with a subscription
   30      * or other.
   31      *
   32      * @var Model\SubscriptionPersistenceInterface
   33      */
   34     protected $storage;
   35 
   36     /**
   37      * An instance of a class handling Http Responses. This is implemented in
   38      * Laminas\Feed\Pubsubhubbub\HttpResponse which shares an unenforced interface with
   39      * (i.e. not inherited from) Laminas\Controller\Response\Http.
   40      *
   41      * @var HttpResponse|PhpResponse
   42      */
   43     protected $httpResponse;
   44 
   45     /**
   46      * The input stream to use when retrieving the request body. Defaults to
   47      * php://input, but can be set to another value in order to force usage
   48      * of another input method. This should primarily be used for testing
   49      * purposes.
   50      *
   51      * @var resource|string String indicates a filename or stream to open;
   52      *     resource indicates an already created stream to use.
   53      */
   54     protected $inputStream = 'php://input';
   55 
   56     /**
   57      * The number of Subscribers for which any updates are on behalf of.
   58      *
   59      * @var int
   60      */
   61     protected $subscriberCount = 1;
   62 
   63     /**
   64      * Constructor; accepts an array or Traversable object to preset
   65      * options for the Subscriber without calling all supported setter
   66      * methods in turn.
   67      *
   68      * @param null|array|Traversable $options Options array or Traversable object
   69      */
   70     public function __construct($options = null)
   71     {
   72         if ($options !== null) {
   73             $this->setOptions($options);
   74         }
   75     }
   76 
   77     /**
   78      * Process any injected configuration options
   79      *
   80      * @param  array|Traversable $options Options array or Traversable object
   81      * @return $this
   82      * @throws Exception\InvalidArgumentException
   83      */
   84     public function setOptions($options)
   85     {
   86         if ($options instanceof Traversable) {
   87             $options = ArrayUtils::iteratorToArray($options);
   88         }
   89 
   90         if (! is_array($options)) {
   91             throw new Exception\InvalidArgumentException(
   92                 'Array or Traversable object expected, got ' . gettype($options)
   93             );
   94         }
   95 
   96         if (is_array($options)) {
   97             $this->setOptions($options);
   98         }
   99 
  100         if (array_key_exists('storage', $options)) {
  101             $this->setStorage($options['storage']);
  102         }
  103         return $this;
  104     }
  105 
  106     /**
  107      * Send the response, including all headers.
  108      * If you wish to handle this via Laminas\Http, use the getter methods
  109      * to retrieve any data needed to be set on your HTTP Response object, or
  110      * simply give this object the HTTP Response instance to work with for you!
  111      *
  112      * @return void
  113      */
  114     public function sendResponse()
  115     {
  116         $this->getHttpResponse()->send();
  117     }
  118 
  119     /**
  120      * Sets an instance of Laminas\Feed\Pubsubhubbub\Model\SubscriptionPersistence used
  121      * to background save any verification tokens associated with a subscription
  122      * or other.
  123      *
  124      * @return $this
  125      */
  126     public function setStorage(Model\SubscriptionPersistenceInterface $storage)
  127     {
  128         $this->storage = $storage;
  129         return $this;
  130     }
  131 
  132     /**
  133      * Gets an instance of Laminas\Feed\Pubsubhubbub\Model\SubscriptionPersistence used
  134      * to background save any verification tokens associated with a subscription
  135      * or other.
  136      *
  137      * @return Model\SubscriptionPersistenceInterface
  138      * @throws Exception\RuntimeException
  139      */
  140     public function getStorage()
  141     {
  142         if ($this->storage === null) {
  143             throw new Exception\RuntimeException(
  144                 'No storage object has been set that subclasses'
  145                 . ' Laminas\Feed\Pubsubhubbub\Model\SubscriptionPersistence'
  146             );
  147         }
  148         return $this->storage;
  149     }
  150 
  151     /**
  152      * An instance of a class handling Http Responses. This is implemented in
  153      * Laminas\Feed\Pubsubhubbub\HttpResponse which shares an unenforced interface with
  154      * (i.e. not inherited from) Laminas\Controller\Response\Http.
  155      *
  156      * @param  HttpResponse|PhpResponse $httpResponse
  157      * @return $this
  158      * @throws Exception\InvalidArgumentException
  159      */
  160     public function setHttpResponse($httpResponse)
  161     {
  162         if (! $httpResponse instanceof HttpResponse && ! $httpResponse instanceof PhpResponse) {
  163             throw new Exception\InvalidArgumentException(
  164                 'HTTP Response object must'
  165                 . ' implement one of Laminas\Feed\Pubsubhubbub\HttpResponse or'
  166                 . ' Laminas\Http\PhpEnvironment\Response'
  167             );
  168         }
  169         $this->httpResponse = $httpResponse;
  170         return $this;
  171     }
  172 
  173     /**
  174      * An instance of a class handling Http Responses. This is implemented in
  175      * Laminas\Feed\Pubsubhubbub\HttpResponse which shares an unenforced interface with
  176      * (i.e. not inherited from) Laminas\Controller\Response\Http.
  177      *
  178      * @return HttpResponse|PhpResponse
  179      */
  180     public function getHttpResponse()
  181     {
  182         if ($this->httpResponse === null) {
  183             $this->httpResponse = new HttpResponse();
  184         }
  185         return $this->httpResponse;
  186     }
  187 
  188     /**
  189      * Sets the number of Subscribers for which any updates are on behalf of.
  190      * In other words, is this class serving one or more subscribers? How many?
  191      * Defaults to 1 if left unchanged.
  192      *
  193      * @param  int|string $count
  194      * @return $this
  195      * @throws Exception\InvalidArgumentException
  196      */
  197     public function setSubscriberCount($count)
  198     {
  199         $count = intval($count);
  200         if ($count <= 0) {
  201             throw new Exception\InvalidArgumentException(
  202                 'Subscriber count must be'
  203                 . ' greater than zero'
  204             );
  205         }
  206         $this->subscriberCount = $count;
  207         return $this;
  208     }
  209 
  210     /**
  211      * Gets the number of Subscribers for which any updates are on behalf of.
  212      * In other words, is this class serving one or more subscribers? How many?
  213      *
  214      * @return int
  215      */
  216     public function getSubscriberCount()
  217     {
  218         return $this->subscriberCount;
  219     }
  220 
  221     // phpcs:disable PSR2.Methods.MethodDeclaration.Underscore
  222 
  223     /**
  224      * Attempt to detect the callback URL (specifically the path forward)
  225      *
  226      * @return string
  227      */
  228     protected function _detectCallbackUrl()
  229     {
  230         $callbackUrl = null;
  231 
  232         // IIS7 with URL Rewrite: make sure we get the unencoded url
  233         // (double slash problem).
  234         $iisUrlRewritten = $_SERVER['IIS_WasUrlRewritten'] ?? null;
  235         $unencodedUrl    = $_SERVER['UNENCODED_URL'] ?? null;
  236         if ('1' === $iisUrlRewritten && ! empty($unencodedUrl)) {
  237             return $unencodedUrl;
  238         }
  239 
  240         // HTTP proxy requests setup request URI with scheme and host [and port]
  241         // + the URL path, only use URL path.
  242         if (isset($_SERVER['REQUEST_URI'])) {
  243             $callbackUrl = $this->buildCallbackUrlFromRequestUri();
  244         }
  245 
  246         if (null !== $callbackUrl) {
  247             return $callbackUrl;
  248         }
  249 
  250         if (isset($_SERVER['ORIG_PATH_INFO'])) {
  251             return $this->buildCallbackUrlFromOrigPathInfo();
  252         }
  253 
  254         return '';
  255     }
  256 
  257     /**
  258      * Get the HTTP host
  259      *
  260      * @return string
  261      */
  262     protected function _getHttpHost()
  263     {
  264         if (! empty($_SERVER['HTTP_HOST'])) {
  265             return $_SERVER['HTTP_HOST'];
  266         }
  267 
  268         $https  = $_SERVER['HTTPS'] ?? null;
  269         $scheme = $https === 'on' ? 'https' : 'http';
  270         $name   = $_SERVER['SERVER_NAME'] ?? '';
  271         $port   = isset($_SERVER['SERVER_PORT']) ? (int) $_SERVER['SERVER_PORT'] : 80;
  272 
  273         if (
  274             ($scheme === 'http' && $port === 80)
  275             || ($scheme === 'https' && $port === 443)
  276         ) {
  277             return $name;
  278         }
  279 
  280         return sprintf('%s:%d', $name, $port);
  281     }
  282 
  283     /**
  284      * Retrieve a Header value from either $_SERVER or Apache
  285      *
  286      * @param  string $header
  287      * @return bool|string
  288      */
  289     protected function _getHeader($header)
  290     {
  291         $temp = strtoupper(str_replace('-', '_', $header));
  292         if (! empty($_SERVER[$temp])) {
  293             return $_SERVER[$temp];
  294         }
  295         $temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header));
  296         if (! empty($_SERVER[$temp])) {
  297             return $_SERVER[$temp];
  298         }
  299         if (function_exists('apache_request_headers')) {
  300             $headers = apache_request_headers();
  301             if (! empty($headers[$header])) {
  302                 return $headers[$header];
  303             }
  304         }
  305         return false;
  306     }
  307 
  308     /**
  309      * Return the raw body of the request
  310      *
  311      * @return false|string Raw body, or false if not present
  312      */
  313     protected function _getRawBody()
  314     {
  315         $body = is_resource($this->inputStream)
  316             ? stream_get_contents($this->inputStream)
  317             : file_get_contents($this->inputStream);
  318 
  319         return strlen(trim($body)) > 0 ? $body : false;
  320     }
  321 
  322     // phpcs:enable PSR2.Methods.MethodDeclaration.Underscore
  323 
  324     /**
  325      * Build the callback URL from the REQUEST_URI server parameter.
  326      *
  327      * @return string
  328      */
  329     private function buildCallbackUrlFromRequestUri()
  330     {
  331         $callbackUrl = $_SERVER['REQUEST_URI'];
  332         $https       = $_SERVER['HTTPS'] ?? null;
  333         $scheme      = $https === 'on' ? 'https' : 'http';
  334         if ($https === 'on') {
  335             $scheme = 'https';
  336         }
  337         $schemeAndHttpHost = $scheme . '://' . $this->_getHttpHost();
  338         if (strpos($callbackUrl, $schemeAndHttpHost) === 0) {
  339             $callbackUrl = substr($callbackUrl, strlen($schemeAndHttpHost));
  340         }
  341         return $callbackUrl;
  342     }
  343 
  344     /**
  345      * Build the callback URL from the ORIG_PATH_INFO server parameter.
  346      *
  347      * @return string
  348      */
  349     private function buildCallbackUrlFromOrigPathInfo()
  350     {
  351         $callbackUrl = $_SERVER['ORIG_PATH_INFO'];
  352         if (! empty($_SERVER['QUERY_STRING'])) {
  353             $callbackUrl .= '?' . $_SERVER['QUERY_STRING'];
  354         }
  355         return $callbackUrl;
  356     }
  357 }