<?php

namespace Airbrake\EventFilter\Error;

use Airbrake\Configuration;

/**
 * Duplicates the functionality you normally get via the error_reporting php.ini
 * setting. Unfortunately, this setting does not apply to custom php error
 * handlers and it is the handler's job to filter out errors.
 *
 * @package    Airbrake
 * @author     Leon Szkliniarz <leon@llamadigital.net>
 * @copyright  (c) 2014 Leon Szkliniarz
 * @license    http://www.opensource.org/licenses/mit-license.php
 */
class ErrorReporting implements FilterInterface
{
    /** @var \Airbrake\Configuration  */
    private $config;

    /**
     * @param Configuration $config
     */
    public function __construct(Configuration $config)
    {
        $this->config = $config;
    }

    /**
     * Filters out PHP errors before they get sent
     *
     * @param int $type
     * @param string $message
     * @param string $file
     * @param int $line
     * @param array $context
     * @see http://us3.php.net/manual/en/function.set-error-handler.php
     * @return bool
     */
    public function shouldSendError($type, $message, $file = null, $line = null, $context = null)
    {
        $level = $this->config->get('errorReportingLevel');
        if (-1 == $level) {
            return true;
        }

        return $level & $type;
    }
}


<?php

declare(strict_types=1);

/*
 * This file is part of boo/bnet.
 *
 * (c) Jonas Stendahl <jonas@stendahl.me>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace Boo\BattleNet;

final class Utils
{
    /**
     * @var array<array<string>>
     */
    private static $replaceTable = [
        ['à', 'ê', 'é', 'ü', '-'],
        ['a', 'e', 'e', 'u', ''],
    ];

    /**
     * @var array<array<string>>
     */
    private static $regexTable = [
        ['![^\-\pL\pN\s]+!u', '![\-\s]+!u'],
        ['', '-'],
    ];

    /**
     * Constructor.
     */
    private function __construct()
    {
    }

    /**
     * Returns an URL friendly version of a realm name.
     *
     * @param string $name
     *
     * @return string
     */
    public static function realmNameToSlug(string $name): string
    {
        $name = \mb_strtolower($name, 'UTF-8');
        $slug = \str_replace(static::$replaceTable[0], static::$replaceTable[1], $name);
        $slug = \preg_replace(static::$regexTable[0], static::$regexTable[1], $slug);

        return \trim((string) $slug, '-');
    }

    /**
     * Returns a character's unique ID from a thumbnail URL.
     *
     * @param string $thumbnailUrl
     *
     * @return string
     */
    public static function thumbnailToId(string $thumbnailUrl): string
    {
        if (1 !== \preg_match('/\/([\d]+)\/([\d]+)(\-avatar\.jpg)$/', $thumbnailUrl, $match)) {
            throw new \RuntimeException(\vsprintf('Invalid thumbnail URL "%s"', [
                $thumbnailUrl,
            ]));
        }

        return ltrim($match[1].$match[2], '0');
    }
}


<?php

/**
 * Defines ThreeScaleAuthorizeResponse and ThreeScaleAuthorizeResponseUsage classes.
 *
 * @copyright 2010 3scale networks S.L.
 */

require_once(dirname(__FILE__) . '/ThreeScaleResponse.php');

/**
 * Object that wraps responses from successful authorize calls.
 */
class ThreeScaleAuthorizeResponse extends ThreeScaleResponse {
  private $usageReports = array();
  private $plan;

  /**
   * @internal Set plan name.
   */
  public function setPlan($plan) {
    $this->plan = $plan;
  }

  /**
   * Get name of the plan the application is signed up to.
   *
   * @return string
   */
  public function getPlan() {
    return $this->plan;
  }

  /**
   * @internal Add usage report entry.
   */
  public function addUsageReport() {
    $usageReport = new ThreeScaleAuthorizeResponseUsageReport;
    array_push($this->usageReports, $usageReport);
    return $usageReport;
  }

  /**
   * Get list of usage report entries.
   *
   * There will be one entry per each usage limit defined on the plan the used
   * is signed up to.
   *
   * @see ThreeScaleAuthorizeResponseUsage
   */
  public function getUsageReports() {
    return $this->usageReports;
  }
}

/**
 * Object with information about application's usage and how close it is to meeting
 * the limits.
 *
 * One object of this class always corresponds to one usage limit defined on the plan.
 */
class ThreeScaleAuthorizeResponseUsageReport {
  private $metric;
  private $period;
  private $periodStart;
  private $periodEnd;
  private $parsedPeriodStart;
  private $parsedPeriodEnd;

  /**
   * Name of the metric the usage limit is defined for.
   *
   * @returns string
   */
  public function getMetric() {
    return $this->metric;
  }

  /**
   * @internal set the metric.
   */
  public function setMetric($metric) {
    $this->metric = $metric;
    return $this;
  }

  /**
   * The period of the usage limit.
   *
   * @returns string
   *
   * This returns symbolic value: "year", "month", "week", "day", "hour" or "minute".
   */
  public function getPeriod() {
    return $this->period;
  }

  /**
   * @internal set the period.
   */
  public function setPeriod($period) {
    $this->period = $period;
    return $this;
  }

  /**
   * Start of the current period of the usage limit, as unix timestamp.
   *
   * @return int (unit timestamp)
   */
  public function getPeriodStart() {
    if (is_null($this->parsedPeriodStart)) {
      $this->parsedPeriodStart = strtotime($this->periodStart);
    }

    return $this->parsedPeriodStart;
  }

  /**
   * End of the current period of the usage limit, as unix timestamp.
   *
   * @return int (unit timestamp)
   */
  public function getPeriodEnd() {
    if (is_null($this->parsedPeriodEnd)) {
      $this->parsedPeriodEnd = strtotime($this->periodEnd);
    }

    return $this->parsedPeriodEnd;
  }

  /**
   * @internal set start and end of the period.
   */
  public function setPeriodInterval($start, $end) {
    $this->periodStart = $start;
    $this->periodEnd = $end;
    return $this;
  }

  /**
   * The value the application alredy spent in the current period of the usage limit.
   *
   * @return int
   */
  public function getCurrentValue() {
    return $this->currentValue;
  }

  /**
   * @internal set current value.
   */
  public function setCurrentValue($value) {
    $this->currentValue = $value;
    return $this;
  }

  /**
   * Maximum value allowed by the usage limit for the current period.
   *
   * @return int
   */
  public function getMaxValue() {
    return $this->maxValue;
  }

  /**
   * @internal set max value.
   */
  public function setMaxValue($value) {
    $this->maxValue = $value;
    return $this;
  }

  /**
   * Is the usage limit corresponding to this report exceeded?
   */
  public function isExceeded() {
    return $this->getCurrentValue() > $this->getMaxValue();
  }
}

?>


<?php

/**
 * Defines ThreeScaleClient class.
 *
 * @copyright 2010 3scale networks S.L.
 */

require_once(dirname(__FILE__) . '/curl/curl.php');

require_once(dirname(__FILE__) . '/ThreeScaleResponse.php');
require_once(dirname(__FILE__) . '/ThreeScaleAuthorizeResponse.php');
require_once(dirname(__FILE__) . '/version.php');

/**
 * Wrapper for 3scale web service management system API.
 *
 * Objects of this class are stateless and can be shared through multiple
 * transactions and by multiple clients.
 * DEFAULT_ROOT_ENDPOINT  su1.3scale.net communicates with 3scale SAAS platform
 */
class ThreeScaleClient {
  const DEFAULT_ROOT_ENDPOINT = 'http://su1.3scale.net';

  private $providerKey = null;
  private $httpClient;
  private $host;

  /**
   * Create a ThreeScaleClient instance.
   *
   * @param $providerKey If (!Provider Key) then service token workflow is triggered.
   * @param $host String scheme + hostname + port of 3scale backend server or On-premise 3scale SAAS platform
   * @param $httpClient Object Object for handling HTTP requests. Default is CURL. Don't change it
   *                    unless you know what you are doing.
   */
  public function __construct($providerKey = null, $host = self::DEFAULT_ROOT_ENDPOINT, $httpClient = null) {
    if ($providerKey) {
      $this->providerKey = $providerKey;
    }

    $this->setHttpClient($httpClient);
    $this->host   = $host;
  }

  /**
   * Get provider's API key.
   * @return string
   */
  public function getProviderKey() {
    return $this->providerKey;
  }

  /**
   * Get hostname of backend server.
   * @return string
   */
  public function getHost() {
    return $this->host;
  }

  /**
   * Authorize an application for app id auth mode
   *
   * @param $appId  application id.
   * @param $appKey secret application key.
   * @param ThreeScaleClientCredentials $credentials_or_service_id accepts service id and service token as tuple
   * @param string $credentials_or_service_id accepts only service id
   *
   * @return ThreeScaleResponse object containing additional authorization information.
   * If both provider key and application id are valid, the returned object is actually
   * @see ThreeScaleAuthorizeResponse (which is derived from ThreeScaleResponse) and
   * contains additional information about the usage status.
   *
   * @see ThreeScaleResponse
   * @see ThreeScaleAuthorizeResponse
   *
   * @throws ThreeScaleServerError in case of unexpected internal server error
   *
   * Example:
   *
   *
   *   <?php
   *   $response = $client->authorize('app-id', 'app-key');
   *   // or $response = $client->authorize('app-id', 'app-key', 'service_id');
   *
   *   if ($response->isSuccess()) {
   *     // ok.
   *   } else {
   *     // something is wrong.
   *   }
   *   ?>
   *
   */

     public function authorize($appId, $appKey = null, $credentials_or_service_id, $usage = null) {
    $url =  $this->getHost() . "/transactions/authorize.xml";
    $params = array('app_id' => $appId);

    if ($credentials_or_service_id instanceof ThreeScaleClientCredentials ) {
      $params['service_token'] = $credentials_or_service_id->service_token;
      $params['service_id'] = $credentials_or_service_id->service_id;
    } else {
      $params['provider_key'] = $this->getProviderKey();
      $params['service_id'] = $credentials_or_service_id;
    }

    if ($appKey) {
      $params['app_key'] = $appKey;
    }

    if ($usage) {
      $params['usage'] = $usage;
    }

    $httpResponse = $this->httpClient->get($url, $params);
    if (self::isHttpSuccess($httpResponse)) {
      return $this->buildAuthorizeResponse($httpResponse->body);
    } else {
      return $this->processError($httpResponse);
    }
  }

  /**
   * Authorize an application for OAuth auth mode.
   *
   * @param $appId  application id or client id (they are equivalent)
   * @param $usage usage
   * @param ThreeScaleClientCredentials $credentials_or_service_id accepts service id and service token as tuple
   * @param string $credentials_or_service_id accepts only service id
   *
   * @return ThreeScaleResponse object containing additional authorization information.
   * If both provider key and application id are valid, the returned object is actually
   * @see ThreeScaleAuthorizeResponse (which is derived from ThreeScaleResponse) and
   * contains additional information about the usage status.
   *
   * @see ThreeScaleResponse
   * @see ThreeScaleAuthorizeResponse
   *
   * @throws ThreeScaleServerError in case of unexpected internal server error
   *
   * Example:
   *
   *
   *   <?php
   *   $response = $client->oauth_authorize('app_id');
   *   // or $response = $client->oauth_authorize('app_id', 'service_id');
   *
   *   if ($response->isSuccess()) {
   *     // ok.
   *   } else {
   *     // something is wrong.
   *   }
   *   ?>
   *
   */
  public function oauth_authorize($appId, $credentials_or_service_id, $usage = null) {
    $url = $this->getHost() . "/transactions/oauth_authorize.xml";
    $params = array('app_id' => $appId);

   if ($credentials_or_service_id instanceof ThreeScaleClientCredentials ) {
      $params['service_token'] = $credentials_or_service_id->service_token;
      $params['service_id'] = $credentials_or_service_id->service_id;
    } else {
      $params['provider_key'] = $this->getProviderKey();
      $params['service_id'] = $credentials_or_service_id;
    }

    if ($usage) {
      $params['usage'] = $usage;
    }

    $httpResponse = $this->httpClient->get($url, $params);

    if (self::isHttpSuccess($httpResponse)) {
      return $this->buildAuthorizeResponse($httpResponse->body);
    } else {
      return $this->processError($httpResponse);
    }
  }

  /**
   * Authorize an application for user key auth mode
   *
   * @param $userKey  user key.
   * @param ThreeScaleClientCredentials $credentials_or_service_id accepts service id and service token as tuple
   * @param string $credentials_or_service_id accepts only service id
   *
   * @return ThreeScaleResponse object containing additional authorization information.
   * If both provider key and application id are valid, the returned object is actually
   * @see ThreeScaleAuthorizeResponse (which is derived from ThreeScaleResponse) and
   * contains additional information about the usage status.
   *
   * @see ThreeScaleResponse
   * @see ThreeScaleAuthorizeResponse
   *
   * @throws ThreeScaleServerError in case of unexpected internal server error
   *
   * Example:
   *
   *
   *   <?php
   *   $response = $client->authorize_with_user_key('user-key');
   *   // or $response = $client->authorize_with_user_key('user-key','service_id');
   *
   *   if ($response->isSuccess()) {
   *     // ok.
   *   } else {
   *     // something is wrong.
   *   }
   *   ?>
   *
   */

  public function authorize_with_user_key($userKey, $credentials_or_service_id, $usage = null) {
    $url = $this->getHost() . "/transactions/authorize.xml";
    $params = array('user_key' => $userKey);

    if ($credentials_or_service_id instanceof ThreeScaleClientCredentials ) {
      $params['service_token'] = $credentials_or_service_id->service_token;
      $params['service_id'] = $credentials_or_service_id->service_id;
    } else {
      $params['provider_key'] = $this->getProviderKey();
      $params['service_id'] = $credentials_or_service_id;
    }

    if ($usage) {
      $params['usage'] = $usage;
    }

    $httpResponse = $this->httpClient->get($url, $params);

    if (self::isHttpSuccess($httpResponse)) {
      return $this->buildAuthorizeResponse($httpResponse->body);
    } else {
      return $this->processError($httpResponse);
    }
  }

/**
   * Authorize and report in a single shot for app id auth mode
   *
   * @param $appId  application id.
   * @param $appKey secret application key.
   * @param ThreeScaleClientCredentials $credentials_or_service_id accepts service id and service token as tuple
   * @param string $credentials_or_service_id accepts only service id
   *
   * @return ThreeScaleResponse object containing additional authorization information.
   * If both provider key and application id are valid, the returned object is actually
   * @see ThreeScaleAuthorizeResponse (which is derived from ThreeScaleResponse) and
   * contains additional information about the usage status.
   *
   * @see ThreeScaleResponse
   * @see ThreeScaleAuthorizeResponse
   *
   * @throws ThreeScaleServerError in case of unexpected internal server error
   *
   * Example:
   *
   *
   *   <?php
   *   $response = $client->authorize('app-id', 'app-key');
   *   // or $response = $client->authorize('app-id', 'app-key','service_id');
   *
   *   if ($response->isSuccess()) {
   *     // ok.
   *   } else {
   *     // something is wrong.
   *   }
   *   ?>
   *
   */

   public function authrep($appId, $appKey = null, $credentials_or_service_id, $usage = null, $userId = null, $object = null, $no_body = null) {
    $url = $this->getHost() . "/transactions/authrep.xml";

    $params = array('app_id' => $appId);

    if ($credentials_or_service_id instanceof ThreeScaleClientCredentials ) {
      $params['service_token'] = $credentials_or_service_id->service_token;
      $params['service_id'] = $credentials_or_service_id->service_id;
    } else {
      $params['provider_key'] = $this->getProviderKey();
      $params['service_id'] = $credentials_or_service_id;
    }

    if ($appKey) $params['app_key'] = $appKey;
    if ($userId) $params['user_id'] = $userId;
    if ($object) $params['object'] = $object;
    if ($usage) $params['usage'] = $usage;
    if ($no_body) $params['no_body'] = $no_body;

    $httpResponse = $this->httpClient->get($url, $params);

    if (self::isHttpSuccess($httpResponse)) {
      return $this->buildAuthorizeResponse($httpResponse->body);
    } else {
      return $this->processError($httpResponse);
    }

  }

  /**
   * Authorize and report in a single shot for user key auth mode
   *
   * @param $userKey  User key.
   * @param ThreeScaleClientCredentials $credentials_or_service_id accepts service id and service token as tuple
   * @param string $credentials_or_service_id accepts only service id
   *
   * @return ThreeScaleResponse object containing additional authorization information.
   * If both provider key and application id are valid, the returned object is actually
   * @see ThreeScaleAuthorizeResponse (which is derived from ThreeScaleResponse) and
   * contains additional information about the usage status.
   *
   * @see ThreeScaleResponse
   * @see ThreeScaleAuthorizeResponse
   *
   * @throws ThreeScaleServerError in case of unexpected internal server error
   *
   * Example:
   *
   *
   *   <?php
   *   $response = $client->authorize('user_key');
   *   // or $response = $client->authorize('user_key','service_id');
   *
   *   if ($response->isSuccess()) {
   *     // ok.
   *   } else {
   *     // something is wrong.
   *   }
   *   ?>
   *
   */

  public function authrep_with_user_key($userKey, $credentials_or_service_id, $usage = null, $userId = null, $object = null, $no_body = null) {
    $url = $this->getHost() . "/transactions/authrep.xml";

    $params = array('user_key' => $userKey);

    if ($credentials_or_service_id instanceof ThreeScaleClientCredentials ) {

      $params['service_token'] = $credentials_or_service_id->service_token;
      $params['service_id'] = $credentials_or_service_id->service_id;
    } else {

      $params['provider_key'] = $this->getProviderKey();
      $params['service_id'] = $credentials_or_service_id;
    }

    if ($userId) $params['user_id'] = $userId;
    if ($object) $params['object'] = $object;
    if ($usage) $params['usage'] = $usage;
    if ($no_body) $params['no_body'] = $no_body;

    $httpResponse = $this->httpClient->get($url, $params);

    if (self::isHttpSuccess($httpResponse)) {
      return $this->buildAuthorizeResponse($httpResponse->body);
    } else {
      return $this->processError($httpResponse);
    }

  }

  /**
   * Report transaction(s).
   *
   * @param $transactions array of transactions to report.
   *
   * Each transaction is an array with these elements:
   *
   * "app_id"    - ID of the application to report the transaction for.
   *               This parameter is required.
   *
   * "usage"     - Array of usage values. The keys are metric names and values
   *               are correspoding numeric values.
   *               Example: array('hits' => 1, 'transfer' => 1024).
   *               This parameter is required.
   *
   * "timestamp" - Timestamp of the transaction. This can be either an integer
   *               (the unix timestamp) or a string in the "YYYY-MM-DD HH:MM:SS"
   *               format (if the time is in the UTC), or a string in the
   *               "YYYY-MM-DD HH:MM:SS ZZZZZZ" format, where the ZZZZZZ is the time
   *               offset from the UTC. For example, "US Pacific Time" has offset -08:00,
   *               "Tokyo" has offset +09:00. This parameter is optional, and if not
   *               provided, equals to the current time.
   *
   * @return ThreeScaleResponse
   *
   * The response object's isSuccess() method returns true if the report was successful,
   * or false if there was an error. See @see ThreeScaleResponse class for more information.
   *
   * @throws ThreeScaleServerError in case of unexpected internal server error.
   *
   * Example:
   *
   *
   *   <?php
   *   // Report two transactions of two applications with app_id
   *   $client->report(array(array('app_id' => 'foo', 'usage' => array('hits' => 1)),
   *                         array('app_id' => 'bar', 'usage' => array('hits' => 1)), 'service id');
   *
   *   // Report one transaction with timestamp with app_id
   *   $client->report(array(array('app_id'    => 'foo',
   *                               'timestamp' => mktime(15, 14, 00, 2, 27, 2010),
   *                               'usage'     => array('hits' => 1),
   *                               'service id')));
   *
   *   // Report two transactions of two applications with user_key
   *   $client->report(array(array('user_key' => 'foo', 'usage' => array('hits' => 1)),
   *                         array('user_key' => 'bar', 'usage' => array('hits' => 1)), 'service id'));
   *
   *    // Report one transaction with timestamp and with user_key
   *   $client->report(array(array('user_key'    => 'foo',
   *                               'timestamp' => mktime(15, 14, 00, 2, 27, 2010),
   *                               'usage'     => array('hits' => 1),
   *                               'service id')));
   *
   *   ?>
   *
   */
  public function report($transactions, $credentials_or_service_id) {
    if (empty($transactions)) {
      throw new InvalidArgumentException('no transactions to report');
    }

    $url = $this->getHost() . "/transactions.xml";

    $params = array();

    if ($credentials_or_service_id instanceof ThreeScaleClientCredentials ) {

      $params['service_token'] = $credentials_or_service_id->service_token;
      $params['service_id'] = $credentials_or_service_id->service_id;
    } else {
      $params['provider_key'] = $this->getProviderKey();
      $params['service_id'] = $credentials_or_service_id;
    }

    $params['transactions'] = $this->encodeTransactions($transactions);

    $httpResponse = $this->httpClient->post($url, $params);

    if (self::isHttpSuccess($httpResponse)) {
      return new ThreeScaleResponse(true);
    } else {
      return $this->processError($httpResponse);
    }
  }

  private function processError($httpResponse) {
    if (self::isHttpClientError($httpResponse)) {
      return $this->buildErrorResponse($httpResponse->body);
    } else {
      throw new ThreeScaleServerError($httpResponse);
    }
  }

  private function buildAuthorizeResponse($body) {
    $response = new ThreeScaleAuthorizeResponse;

    $doc = new SimpleXMLElement($body);

    if ((string) $doc->authorized == 'true') {
      $response->setSuccess();
    } else {
      $response->setError((string) $doc->reason);
    }

    $response->setPlan((string) $doc->plan);

    if ($doc->usage_reports) {
      foreach ($doc->usage_reports->usage_report as $node) {
        $response->addUsageReport()
          ->setMetric(trim($node['metric']))
          ->setPeriod(trim($node['period']))
          ->setPeriodInterval((string) $node->period_start, (string) $node->period_end)
          ->setCurrentValue((int) (string) $node->current_value)
          ->setMaxValue((int) (string) $node->max_value);
      }
    }

    return $response;
  }

  private function buildErrorResponse($body) {
    $response = new ThreeScaleResponse(false);
    $doc = new SimpleXMLElement($body);

    $response->setError(trim((string) $doc), $doc['code']);
    return $response;
  }

  private function encodeTransactions($transactions) {
    $encoded_transactions = array();

    foreach($transactions as $index => $transaction) {
      if (array_key_exists('timestamp', $transaction)) {
        $transaction['timestamp'] = self::encodeTimestamp($transaction['timestamp']);
      }

      $encoded_transactions[(string) $index] = self::urlencodeRecursive($transaction);
    }

    return $encoded_transactions;
  }

  private static function encodeTimestamp($timestamp) {
    if (is_numeric($timestamp)) {
      return date('Y-m-d H:i:s P', $timestamp);
    } else {
      return $timestamp;
    }
  }

  private static function urlencodeRecursive($array) {
    $result = array();

    foreach ($array as $key => $value) {
      if (is_array($value)) {
        $new_value = self::urlencodeRecursive($value);
      } else {
        if($key == 'timestamp') {
          $new_value = $value;
        }
        else {
          $new_value = urlencode($value);
        }
      }

      $result[$key] = $new_value;
    }

    return $result;
  }

  private static function isHttpSuccess($httpResponse) {
    return (self::isHttpStatusCodeIn($httpResponse, 100, 299)) || ($httpResponse->headers['Status-Code'] == 409);
  }

  private static function isHttpClientError($httpResponse) {
    return self::isHttpStatusCodeIn($httpResponse, 400, 404);
  }

  private static function isHttpStatusCodeIn($httpResponse, $min, $max) {
    $code = $httpResponse->headers['Status-Code'];
    return $min <= $code && $code <= $max;
  }

  // Set the HTTP Client object used for the HTTP requests. By default, it uses the bundled
  // Curl library, which is just a thin wrapper around php's curl functions.
  public function setHttpClient($httpClient) {
    if (is_null($httpClient)) {
      $httpClient = new Curl;
      $threeScaleVersion = new ThreeScaleVersion();

      $version = $threeScaleVersion->getVersion();

      $httpClient->options['CURLOPT_FOLLOWLOCATION'] = false;
      $httpClient->headers['X-3scale-User-Agent'] = 'plugin-php-v'. $version;
    }

    $this->httpClient = $httpClient;
  }
}

// Base class for all exceptions.
class ThreeScaleException extends RuntimeException {}

// This exceptions is thrown when there is an unexpected internal server error
// on the 3scale server.
class ThreeScaleServerError extends ThreeScaleException {
  public function __construct($response = null) {
    parent::__construct('server error');
    $this->response = $response;
  }

  public function getResponse() {
    return $this->response;
  }
}

 /* Objects of this class are stateless and can be shared through multiple
 * transactions and by multiple clients.
 */
class ThreeScaleClientCredentials {
  public $service_id;
  public $service_token;

  public function __construct($service_id, $service_token) {

   if (!$service_token){
    throw new InvalidArgumentException('missing $service_token');
   }

   $this->service_token=$service_token;
   $this->service_id=$service_id;
  }
}

?>


<?php

declare(strict_types=1);

/*
 * This file is part of boo/bnet.
 *
 * (c) Jonas Stendahl <jonas@stendahl.me>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace Boo\BattleNet\OAuth2;

use Boo\BattleNet\Exceptions\OAuthException;
use Boo\BattleNet\Regions\RegionInterface;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Token\AccessToken;
use Psr\Http\Message\ResponseInterface;

final class BattleNetProvider extends AbstractProvider
{
    /**
     * @var RegionInterface
     */
    protected $region;

    /**
     * {@inheritdoc}
     */
    public function __construct(array $options = [], array $collaborators = [])
    {
        parent::__construct($options, $collaborators);

        if (false === array_key_exists('region', $options) ||
            false === $options['region'] instanceof RegionInterface) {
            throw new OAuthException('Missing required option "region"');
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getBaseAccessTokenUrl(array $params): string
    {
        return $this->region->getOAuthBaseUrl().'/oauth/token';
    }

    /**
     * {@inheritdoc}
     */
    public function getBaseAuthorizationUrl(): string
    {
        return $this->region->getOAuthBaseUrl().'/oauth/authorize';
    }

    /**
     * {@inheritdoc}
     */
    public function getResourceOwnerDetailsUrl(AccessToken $token): string
    {
        return $this->region->getApiBaseUrl().'/account/user?access_token='.$token->getToken();
    }

    /**
     * {@inheritdoc}
     */
    protected function getDefaultScopes(): array
    {
        return [];
    }

    /**
     * {@inheritdoc}
     */
    protected function checkResponse(ResponseInterface $response, $data): void
    {
        if (\is_array($data) && array_key_exists('error', $data)) {
            throw new OAuthException($data['error'].': '.$data['error_description']);
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function createResourceOwner(array $response, AccessToken $token): \stdClass
    {
        return (object) $response;
    }
}


<?php

/*
 * This file is part of the Runalyze DEM Reader.
 *
 * (c) RUNALYZE <mail@runalyze.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace Runalyze\DEM\Provider;

use Runalyze\DEM\Exception\InvalidArgumentException;
use Runalyze\DEM\Interpolation\InterpolationInterface;

abstract class AbstractFileProvider implements ProviderInterface
{
    use GuessInvalidValuesTrait;

    /** @var int */
    const MAX_LATITUDE = 90;

    /** @var int */
    const MAX_LONGITUDE = 180;

    /** @var string */
    protected $PathToFiles;

    /** @var resource */
    protected $FileResource;

    /** @var string|bool */
    protected $CurrentFilename = false;

    /** @var InterpolationInterface|null */
    protected $Interpolation;

    /** @var ResourceReaderInterface */
    protected $ResourceReader;

    /**
     * @param string                      $pathToFiles
     * @param InterpolationInterface|null $interpolation
     */
    public function __construct($pathToFiles, InterpolationInterface $interpolation = null)
    {
        $this->PathToFiles = $pathToFiles;
        $this->Interpolation = $interpolation;

        $this->addSlashToPathIfNotThere();
        $this->initResourceReader();
    }

    private function addSlashToPathIfNotThere()
    {
        if (substr($this->PathToFiles, -1) !== '/') {
            $this->PathToFiles .= '/';
        }
    }

    /**
     * @param InterpolationInterface $interpolation
     */
    public function setInterpolation(InterpolationInterface $interpolation)
    {
        $this->Interpolation = $interpolation;
    }

    public function removeInterpolation()
    {
        $this->Interpolation = null;
    }

    /**
     * @param  array                    $latitudeLongitudes array(array($lat, $lng), ...)
     * @return bool
     * @throws InvalidArgumentException
     */
    public function hasDataFor(array $latitudeLongitudes)
    {
        foreach ($latitudeLongitudes as $location) {
            if (!is_array($location) || count($location) !== 2) {
                throw new InvalidArgumentException('Locations must be arrays of two values.');
            }

            if (!$this->locationIsInBounds($location[0], $location[1])) {
                return false;
            }

            if (!file_exists($this->PathToFiles.$this->getFilenameFor($location[0], $location[1]))) {
                return false;
            }
        }

        return true;
    }

    /**
     * @param  float $latitude
     * @param  float $longitude
     * @return bool
     */
    protected function locationIsInBounds($latitude, $longitude)
    {
        return
            ($latitude > -static::MAX_LATITUDE) && ($latitude <= static::MAX_LATITUDE) &&
            ($longitude > -static::MAX_LONGITUDE) && ($longitude < static::MAX_LONGITUDE)
        ;
    }

    /**
     * @return bool
     */
    public function usesInterpolation()
    {
        return null !== $this->Interpolation;
    }

    /**
     * @param  float[]                   $latitudes
     * @param  float[]                   $longitudes
     * @return array                     elevations [m] can be false if nothing retrieved
     * @throws InvalidArgumentException;
     */
    public function getElevations(array $latitudes, array $longitudes)
    {
        $numberOfPoints = count($latitudes);
        $elevations = [];

        if (count($longitudes) !== $numberOfPoints) {
            throw new InvalidArgumentException('Arrays for latitude and longitude must be of same size.');
        }

        for ($i = 0; $i < $numberOfPoints; ++$i) {
            $elevations[] = $this->getElevation($latitudes[$i], $longitudes[$i]);
        }

        return $elevations;
    }

    /**
     * Get elevation for specified location.
     *
     * Availability of data must be checked in advance via hasDataFor($locations).
     * Only 'invalid' locations such as (0.0, 0.0) won't throw an exception but return false.
     *
     * @param  float                     $latitude
     * @param  float                     $longitude
     * @return int|bool                  elevation [m] can be false if nothing retrieved
     * @throws InvalidArgumentException;
     */
    public function getElevation($latitude, $longitude)
    {
        if ($latitude === 0.0 && $longitude === 0.0) {
            return false;
        }

        if (!$this->locationIsInBounds($latitude, $longitude)) {
            throw new InvalidArgumentException(
                sprintf('Location (%f, %f) is out of bounds ([-%f, %f], [-%f, %f]).',
                    $latitude, $longitude,
                    static::MAX_LATITUDE, static::MAX_LATITUDE,
                    static::MAX_LONGITUDE, static::MAX_LONGITUDE
                )
            );
        }

        $filename = $this->getFilenameFor($latitude, $longitude);

        if ($this->CurrentFilename !== $filename) {
            $this->openResource($filename);
        }

        return $this->getElevationFromResource($latitude, $longitude);
    }

    /**
     * @param  float    $latitude
     * @param  float    $longitude
     * @return int|bool can be false if nothing retrieved
     */
    protected function getElevationFromResource($latitude, $longitude)
    {
        list($exactRowValue, $exactColValue) = $this->getExactRowAndColFor($latitude, $longitude);

        if (!$this->usesInterpolation()) {
            return $this->getElevationFor(round($exactRowValue), round($exactColValue));
        }

        return $this->getInterpolatedElevationFor($exactRowValue, $exactColValue);
    }

    /**
     * @param  float    $exactRowValue
     * @param  float    $exactColValue
     * @return int|bool can be false if nothing retrieved
     */
    protected function getInterpolatedElevationFor($exactRowValue, $exactColValue)
    {
        $row = floor($exactRowValue);
        $col = floor($exactColValue);

        $elevationOnBoundingBox = [
            $this->getElevationFor($row, $col),
            $this->getElevationFor($row, $col + 1),
            $this->getElevationFor($row + 1, $col),
            $this->getElevationFor($row + 1, $col + 1),
        ];

        $this->guessInvalidValuesOnBox($elevationOnBoundingBox);

        return $this->Interpolation->interpolate(
            ($exactColValue - $col),
            ($exactRowValue - $row),
            $elevationOnBoundingBox
        );
    }

    /**
     * @param  float  $latitude
     * @param  float  $longitude
     * @return string
     */
    abstract protected function getFilenameFor($latitude, $longitude);

    abstract protected function initResourceReader();

    /**
     * @param string $filename
     */
    abstract protected function openResource($filename);

    /**
     * @param  int      $row
     * @param  int      $col
     * @return int|bool elevation [m] can be false if nothing retrieved
     */
    abstract protected function getElevationFor($row, $col);

    /**
     * @param  float $latitude
     * @param  float $longitude
     * @return array array(row, col)
     */
    abstract protected function getExactRowAndColFor($latitude, $longitude);
}


<?php
namespace Czim\CmsAclModule;

use Czim\CmsAclModule\Support\Route\ApiRouteMapper;
use Czim\CmsAclModule\Support\Route\WebRouteMapper;
use Czim\CmsCore\Contracts\Core\CoreInterface;
use Czim\CmsCore\Contracts\Modules\Data\AclPresenceInterface;
use Czim\CmsCore\Contracts\Modules\Data\MenuPresenceInterface;
use Czim\CmsCore\Contracts\Modules\ModuleInterface;
use Czim\CmsCore\Support\Enums\AclPresenceType;
use Czim\CmsCore\Support\Enums\MenuPresenceType;
use Illuminate\Routing\Router;

class AclModule implements ModuleInterface
{

    /**
     * @var CoreInterface
     */
    protected $core;

    /**
     * @param CoreInterface $core
     */
    public function __construct(CoreInterface $core)
    {
        $this->core = $core;
    }

    /**
     * Returns unique identifying key for the module.
     * This should also be able to perform as a slug for it.
     *
     * @return string
     */
    public function getKey()
    {
        return 'acl-simple';
    }

    /**
     * Returns display name for the module.
     *
     * @return string
     */
    public function getName()
    {
        return 'Access Control Management';
    }

    /**
     * Returns release/version number of module.
     *
     * @return string
     */
    public function getVersion()
    {
        return '0.0.1';
    }

    /**
     * Returns the FQN for a class mainly associated with this module.
     *
     * @return string|null
     */
    public function getAssociatedClass()
    {
        return null;
    }

    /**
     * Generates web routes for the module given a contextual router instance.
     * Note that the module is responsible for ACL-checks, including route-based.
     *
     * @param Router $router
     */
    public function mapWebRoutes(Router $router)
    {
        (new WebRouteMapper())->mapRoutes($router);
    }

    /**
     * Generates API routes for the module given a contextual router instance.
     * Note that the module is responsible for ACL-checks, including route-based.
     *
     * @param Router $router
     */
    public function mapApiRoutes(Router $router)
    {
        (new ApiRouteMapper())->mapRoutes($router);
    }

    /**
     * @return null|array|AclPresenceInterface|AclPresenceInterface[]
     */
    public function getAclPresence()
    {
        return [
            [
                'id'          => 'simple-acl-roles',
                'label'       => 'Managing roles',
                'type'        => AclPresenceType::GROUP,
                'permissions' => [
                    'acl.roles.show',
                    'acl.roles.create',
                    'acl.roles.edit',
                    'acl.roles.delete',
                ],
            ],
            [
                'id'          => 'simple-acl-users',
                'label'       => 'Managing users',
                'type'        => AclPresenceType::GROUP,
                'permissions' => [
                    'acl.users.show',
                    'acl.users.create',
                    'acl.users.edit',
                    'acl.users.delete',
                ],
            ],
        ];
    }

    /**
     * Returns data for CMS menu presence.
     *
     * @return null|array|MenuPresenceInterface[]|MenuPresenceInterface[]
     */
    public function getMenuPresence()
    {
        return [
            'id'       => 'simple-acl',
            'type'     => MenuPresenceType::GROUP,
            'label'    => 'Access Control',
            'children' => [
                [
                    'id'          => 'simple-acl-users',
                    'type'        => MenuPresenceType::ACTION,
                    'label'       => 'Users',
                    'permissions' => 'acl.users.show',
                    'action'      => $this->core->prefixRoute('acl.users.index'),
                    'parameters'  => [],
                ],
                [
                    'id'          => 'simple-acl-create-user',
                    'type'        => MenuPresenceType::ACTION,
                    'label'       => 'New User',
                    'permissions' => 'acl.users.create',
                    'action'      => $this->core->prefixRoute('acl.users.create'),
                    'parameters'  => [],
                ],
                [
                    'id'          => 'simple-acl-roles',
                    'type'        => MenuPresenceType::ACTION,
                    'label'       => 'Roles',
                    'permissions' => 'acl.roles.show',
                    'action'      => $this->core->prefixRoute('acl.roles.index'),
                    'parameters'  => [],
                ],
            ]
        ];
    }
}


<?php
/**
 * @author Richard Weinhold
 */
namespace ricwein\FileSystem\Storage;

use ricwein\FileSystem\Storage;
use ricwein\FileSystem\FileSystem;
use ricwein\FileSystem\Enum\Hash;
use ricwein\FileSystem\Helper\Stream;
use ricwein\FileSystem\Exceptions\AccessDeniedException;
use ricwein\FileSystem\Exceptions\FileNotFoundException;
use ricwein\FileSystem\Exceptions\RuntimeException;
use ricwein\FileSystem\Helper\Path;
use ricwein\FileSystem\Helper\MimeType;
use ricwein\FileSystem\Storage\Extensions\Binary;

/**
 * represents a file/directory at the local filesystem
 */
class Disk extends Storage
{
    /**
     * @var Path
     */
    protected $path;

    /**
     * @param string|FileSystem|Path $path ,...
     */
    public function __construct(...$path)
    {
        if (empty($path)) {
            throw new RuntimeException('unable to load Disk-Storage without a path', 400);
        }
        $this->path = new Path($path);
    }

    /**
     * @return void
     */
    public function __destruct()
    {
        if (!$this->selfdestruct || !file_exists($this->path->raw)) {
            return;
        }

        if (is_file($this->path->raw)) {
            $this->removeFile();
        } elseif (is_dir($this->path->raw)) {
            $this->removeDir();
        }
    }

    /**
     * @inheritDoc
     */
    public function getDetails(): array
    {
        return array_merge(parent::getDetails(), $this->path->getDetails());
    }

    /**
     * @inheritDoc
     */
    public function doesSatisfyConstraints(): bool
    {
        return $this->constraints->isValidPath($this->path);
    }

    /**
     * @return Path
     */
    public function path(): Path
    {
        return $this->path;
    }

    /**
     * @inheritDoc
     */
    public function isFile(): bool
    {
        return $this->path->real !== null && file_exists($this->path->real) && $this->path->fileInfo()->isFile();
    }

    /**
     * @inheritDoc
     */
    public function isDir(): bool
    {
        return $this->path->real !== null && file_exists($this->path->real) && $this->path->fileInfo()->isDir();
    }

    /**
     * @inheritDoc
     */
    public function isExecutable(): bool
    {
        return $this->isFile() && $this->path->fileInfo()->isExecutable();
    }

    /**
     * @inheritDoc
     */
    public function isSymlink(): bool
    {
        return $this->path->real !== null && $this->path->fileInfo()->isLink();
    }

    /**
     * @inheritDoc
     */
    public function isReadable(): bool
    {
        return $this->path->real !== null && $this->path->fileInfo()->isReadable();
    }

    /**
     * @inheritDoc
     */
    public function isWriteable(): bool
    {
        return $this->path->fileInfo()->isWritable();
    }

    /**
     * @inheritDoc
     * @throws FileNotFoundException|RuntimeException
     */
    public function readFile(?int $offset = null, ?int $length = null, int $mode = LOCK_SH): string
    {
        if (!$this->isFile() || !$this->isReadable()) {
            throw new FileNotFoundException('file not found', 404);
        }

        // open file-handler in readonly mode
        $handle = $this->getStream('r');

        try {

            // try to set lock if provided
            if ($mode !== 0 && !\flock($handle, $mode | LOCK_NB)) {
                throw new RuntimeException('unable to get file-lock', 500);
            }

            return (new Stream($handle))->read($offset, $length);
        } finally {

            // ensure the file in unlocked after reading and the file-handler is closed again
            if ($mode !== 0) {
                \flock($handle, LOCK_UN);
            }
            \fclose($handle);
        }
    }

    /**
     * @inheritDoc
     * @throws FileNotFoundException|RuntimeException
     */
    public function streamFile(?int $offset = null, ?int $length = null, int $mode = LOCK_SH): void
    {
        if (!$this->isFile() || !$this->isReadable()) {
            throw new FileNotFoundException('file not found', 404);
        }

        // open file-handler in readonly mode
        $handle =  $this->getStream('r');

        try {

            // try to set lock if provided
            if ($mode !== 0 && !\flock($handle, $mode | LOCK_NB)) {
                throw new RuntimeException('unable to get file-lock', 500);
            }

            (new Stream($handle))->send($offset, $length);
        } finally {

            // ensure the file in unlocked after reading and the file-handler is closed again
            if ($mode !== 0) {
                \flock($handle, LOCK_UN);
            }
            \fclose($handle);
        }
    }

    /**
     * @inheritDoc
     */
    public function writeFile(string $content, bool $append = false, int $mode = LOCK_EX): bool
    {
        // ensure file exists and path-real is set correctly
        $this->touch(true);

        // open file-handler in readonly mode
        $handle = $this->getStream($append ? 'a' : 'w');

        try {

            // try to set lock if provided
            if ($mode !== 0 && !\flock($handle, $mode | LOCK_NB)) {
                throw new RuntimeException('unable to get file-lock', 500);
            }

            // write content
            if (\fwrite($handle, $content) <= 0) {
                return false;
            }

            $this->path->reload();
            return true;
        } finally {

            // ensure the file in unlocked after reading and the file-handler is closed again
            if ($mode !== 0) {
                \flock($handle, LOCK_UN);
            }
            \fclose($handle);
        }
    }

    /**
     * @inheritDoc
     */
    public function removeFile(): bool
    {
        $this->selfdestruct = false;

        if (!unlink($this->path->real ?? $this->path->raw)) {
            return false;
        }

        $this->path->reload();
        return true;
    }

    /**
     * @param bool $recursive
     * @param int $mode
     * @return \Iterator
     */
    protected function getIterator(bool $recursive, int $mode = \RecursiveIteratorIterator::SELF_FIRST): \Iterator
    {
        if (!$recursive) {
            return new \DirectoryIterator($this->path->real);
        }

        return new \RecursiveIteratorIterator(
            new \RecursiveDirectoryIterator($this->path->real, \RecursiveDirectoryIterator::SKIP_DOTS),
            $mode
        );
    }

    /**
     * removes directory from disk
     * @return bool
     * @throws AccessDeniedException
     */
    public function removeDir(): bool
    {
        if (!$this->isDir()) {
            throw new AccessDeniedException(sprintf('unable to remove directory for path: "%s"', $this->path->raw), 500);
        }

        try {
            $iterator = $this->getIterator(true, \RecursiveIteratorIterator::CHILD_FIRST);

            /** @var \SplFileInfo $file */
            foreach ($iterator as $splFile) {

                // file not readable
                if (!$splFile->isReadable()) {
                    throw new AccessDeniedException(sprintf('unable to access file for path: "%s"', $splFile->getPathname()), 500);
                }

                // try to remove files/dirs/links
                switch ($splFile->getType()) {
                    case 'dir': rmdir($splFile->getRealPath()); break;
                    case 'link': unlink($splFile->getPathname()); break;
                    default: unlink($splFile->getRealPath());
                }
            }

            return rmdir($this->path->raw);
        } finally {
            $this->selfdestruct = false;
            $this->path->reload();
        }
    }

    /**
     * @inheritDoc
     * @throws AccessDeniedException
     */
    public function list(bool $recursive = false): \Generator
    {
        if (!$this->isDir()) {
            throw new RuntimeException(sprintf('unable to open directory "%s"', $this->path->raw), 500);
        }

        $iterator = $this->getIterator($recursive);

        /** @var \SplFileInfo $file */
        foreach ($iterator as $file) {
            if (in_array($file->getFilename(), ['.', '..'], true)) {
                continue;
            }

            // file not readable
            if (!$file->isReadable()) {
                throw new AccessDeniedException(sprintf('unable to access file for path: "%s"', $file->getPathname()), 500);
            }

            yield new self(
                $this->path->real,
                str_replace($this->path->real, '', $file->getPathname())
            );
        }
    }

    /**
     * @inheritDoc
     */
    public function getSize(): int
    {
        return $this->path->fileInfo()->getSize();
    }

    /**
     * @inheritDoc
     */
    public function getFileType(bool $withEncoding = false): ?string
    {
        if ($this->path->real === null) {
            return null;
        }

        // detect mimetype by magic.mime
        $type = (new \finfo($withEncoding ? FILEINFO_MIME : FILEINFO_MIME_TYPE))->file($this->path->raw);
        if (!in_array($type, [false, 'text/plain', 'application/octet-stream', 'inode/x-empty'], true)) {
            return $type;
        }

        // detect mimetype by file-extension
        return MimeType::getMimeFor($this->path->extension);
    }

    /**
     * @inheritDoc
     */
    public function getFileHash(int $mode = Hash::CONTENT, string $algo = 'sha256'): ?string
    {
        if ($this->path->real === null) {
            return null;
        }

        switch ($mode) {
            case Hash::CONTENT: return hash_file($algo, $this->path->real, false);
            case Hash::FILENAME: return hash($algo, $this->path->filename, false);
            case Hash::FILEPATH: return hash($algo, $this->path->real, false);
            default: throw new RuntimeException('unknown hashing-mode', 500);
        }
    }

    /**
     * @inheritDoc
     */
    public function getTime(): int
    {
        return $this->path->fileInfo()->getMTime();
    }

    /**
     * @inheritDoc
     */
    public function touch(bool $ifNewOnly = false, ?int $time = null, ?int $atime = null): bool
    {
        if ($ifNewOnly === true && $this->isFile()) {
            return true;
        }

        // actual touch file
        if (!touch($this->path->raw, $time, $atime)) {
            return false;
        }

        // reset internal path-state to re-evaluate the realpath
        $this->path->reload();

        return true;
    }

    /**
     * @param bool $ifNewOnly
     * @return bool
     */
    public function mkdir(bool $ifNewOnly = false): bool
    {
        if ($ifNewOnly && $this->isDir() && $this->isFile()) {
            return true;
        }

        if (mkdir($this->path->raw, 0777, true)) {
            $this->path->reload();
            return true;
        }

        return false;
    }

    /**
     * @inheritDoc
     */
    public function isDotfile(): bool
    {
        return strpos($this->path->basename, '.') === 0;
    }

    /**
     * @return string
     */
    public function __toString(): string
    {
        return sprintf('%s at: "%s"', parent::__toString(), (string) $this->path);
    }

    /**
     * @inheritDoc
     * @return Binary\Disk
     */
    public function getHandle(int $mode): Binary
    {
        return new Binary\Disk($this, $mode);
    }

    /**
     * changes current directory
     * @param string[]|FileSystem[]|Path[] $path
     * @return void
     */
    public function cd(array $path): void
    {
        array_unshift($path, $this->path);
        $this->path = new Path($path);
    }

    /**
     * @inheritDoc
     * @throws RuntimeException
     */
    public function getStream(string $mode = 'r+')
    {
        $stream = \fopen($this->path->real, $mode);

        if ($stream === false) {
            throw new RuntimeException('failed to open stream', 500);
        }

        return $stream;
    }

    /**
     * @inheritDoc
     * @throws RuntimeException
     */
    public function writeFromStream($stream): bool
    {
        if (!is_resource($stream)) {
            throw new RuntimeException(sprintf('file-handle must be of type \'resource\' but \'%s\' given', is_object($handle) ? get_class($handle) : gettype($handle)), 500);
        }

        $destStream = $this->getStream('w');
        try {
            if (!\stream_copy_to_stream($stream, $destStream)) {
                return false;
            }

            $destination->path()->reload();
            return true;
        } finally {
            \fclose($destStream);
        }
    }

    /**
     * @inheritDoc
     */
    public function copyFileTo(Storage $destination): bool
    {
        switch (true) {

            // copy file from disk to disk
            case $destination instanceof Disk:
                if (!\copy($this->path->real, $destination->path()->raw)) {
                    return false;
                }
                $destination->path()->reload();
                return true;

            case $destination instanceof Flysystem:
                $readStream = $this->getStream('r');
                try {
                    return $destination->writeFromStream($readStream);
                } finally {
                    \fclose($readStream);
                }

            case $destination instanceof Memory:
            default:
                return $destination->writeFile($this->readFile());
        }
    }

    /**
    * @inheritDoc
     */
    public function moveFileTo(Storage $destination): bool
    {
        switch (true) {

            // copy file from disk to disk
            case $destination instanceof Disk:
                if (!\rename($this->path->real, $destination->path()->raw)) {
                    return false;
                }
                $destination->path()->reload();
                return true;

            case $destination instanceof Flysystem:
            case $destination instanceof Memory:
            default:
                if (!$this->copyFileTo($destination)) {
                    return false;
                }

                $this->removeFile();
                return true;
        }
    }
}


<?php

namespace Pakettikauppa\Shipment;

/**
 * Class AdditionalService
 *
 * Possible additional services include:
 *
 * 2106 = Alternative pickip point, specifiers: [pickup_point_id]
 * 3101 = Cash on delivery, specifiers: [amount, account, reference, codbic]
 * 3102 = Multiple parcel shipment, specifiers [count]
 * 3104 = Fragile
 * 3174 = Large
 *
 * For a complete list of possible additional services use listAdditionalServices() in the Client class.
 * Also note that available additional services depend on the shipping method selected.
 *
 * @package Pakettikauppa\Shipment
 */
class AdditionalService
{
    /**
     * @var integer
     */
    protected $service_code;
    /**
     * @var array
     */
    protected $specifiers;

    public function __construct()
    {
        $this->specifiers = array();
    }

    /**
     * @return int
     */
    public function getServiceCode()
    {
        return $this->service_code;
    }

    /**
     * @param int $service_code
     */
    public function setServiceCode($service_code)
    {
        $this->service_code = $service_code;
    }

    /**
     * @return array
     */
    public function getSpecifiers()
    {
        return $this->specifiers;
    }

    public function getSpecifier($name)
    {
        foreach($this->specifiers as $specifier) {
            if($specifier[0] == $name) {
                return $specifier[1];
            }
        }

        return null;
    }

    /**
     * @param string $name
     * @param string $value
     */
    public function addSpecifier($name, $value)
    {
        $this->specifiers[] = [$name, $value];
    }

    /**
     * Checks that service_code is numeric and that expected specifiers exist with certain service_code values.
     *
     * @return bool
     */
    public function isValid()
    {
        // alternative pickup point
        if($this->service_code == 2106) {
            if($this->getSpecifier('pickup_point_id') === null)
                return false;
        }

        // cash on delivery (Postiennakko/Bussiennakko)
        if($this->service_code == 3101) {
            $expected_params = array('amount', 'account', 'reference', 'codbic');

            foreach($expected_params as $param)
            {
                if($this->getSpecifier($param) === null)
                    return false;
            }
        }

        // multipacket shipment requires package count
        if($this->service_code == 3102) {
            if($this->getSpecifier('count') === null)
                return false;

            if(!is_numeric($this->getSpecifier('count')))
                return false;
        }

        if($this->service_code == 3111) {
            if($this->getSpecifier('insurancevalue') === null)
                return false;
        }

        if($this->service_code == 3120) {
            if($this->getSpecifier('deliverytime'))
                return false;
        }

        if($this->service_code == 3143) {
            if($this->getSpecifier('lqweight') === null or $this->getSpecifier('lqcount') === null)
                return false;
        }

        if(!is_numeric($this->service_code)) {
            return false;
        }

        return true;
    }

}


<?php
/**
 * @author Richard Weinhold
 */
namespace ricwein\FileSystem;

use ricwein\FileSystem\Enum\Hash;
use ricwein\FileSystem\Helper\Path;
use ricwein\FileSystem\Helper\Constraint;
use ricwein\FileSystem\Storage;
use ricwein\FileSystem\Exceptions\RuntimeException;

/**
 * base of all FileSystem type-classes (File/Directory)
 */
abstract class FileSystem
{
    /**
     * @var Storage
     */
    protected $storage;

    /**
     * @param Storage $storage
     * @param int $constraints Constraint::LOOSE || Constraint::STRICT || Constraint::IN_SAFEPATH | Constraint::IN_OPENBASEDIR | Constraint::DISALLOW_LINK
     */
    public function __construct(Storage $storage, int $constraints = Constraint::STRICT)
    {
        $this->storage = $storage;
        $this->storage->setConstraints($constraints);
    }

    /**
     * free internal resources
     */
    public function __destruct()
    {
        $this->storage = null;
    }

    /**
     * @internal this should only be used for debugging purposes
     * @return Storage
     */
    public function storage(): Storage
    {
        return $this->storage;
    }

    /**
     * @return Path
     * @throws RuntimeException
     */
    public function path(): Path
    {
        if ($this->storage instanceof Storage\Disk) {
            return $this->storage->path();
        }

        throw new RuntimeException('unable to fetch path from non-disk FileSystem', 500);
    }

    /**
     * @return bool
     */
    public function isDotfile(): bool
    {
        return $this->storage->isDotfile();
    }

    /**
     * get last-modified timestamp
     * @return int
     */
    public function getTime(): int
    {
        return $this->storage->getTime();
    }

    /**
     * remove file
     * @return self
     */
    abstract public function remove(): self;

    /**
     * check if path is readable
     * @return bool
     */
    public function isReadable(): bool
    {
        return $this->storage->isReadable();
    }

    /**
     * check if path is writeable
     * @return bool
     */
    public function isWriteable(): bool
    {
        return $this->storage->isWriteable();
    }

    /**
     * check if path is a symlink
     * @return bool
     */
    public function isSymlink(): bool
    {
        return $this->storage->isSymlink();
    }

    /**
     * calculate hash above content or filename
     * @param int $mode Hash::CONTENT | Hash::FILENAME | Hash::FILEPATH
     * @param string $algo hashing-algorithm
     * @return string
     */
    abstract public function getHash(int $mode = Hash::CONTENT, string $algo = 'sha256'): string;

    /**
     * @return bool
     */
    public function isValid(): bool
    {
        return $this->storage->doesSatisfyConstraints();
    }

    /**
     * @return string
     */
    public function __toString(): string
    {
        return (string) $this->storage;
    }

    /**
     * check if file exists and is an actual file
     * @return bool
     */
    public function isFile(): bool
    {
        return false;
    }

    /**
     * check if directory exists and is an actual directory
     * @return bool
     */
    public function isDir(): bool
    {
        return false;
    }

    /**
     * remove file from filesystem on object destruction
     * => leaving scope or removing object reference
     * @param  bool $activate
     * @return self
     */
    public function removeOnFree(bool $activate = true): self
    {
        $this->storage->removeOnFree($activate);
        return $this;
    }

    /**
     * cast current object to given class-name,
     * reusing internal storage-objects
     * @param  string $class
     * @return self
     */
    public function as(string $class): self
    {
        return new $class($this->storage);
    }
}


<?php

/*
 * This file is part of the Runalyze DEM Reader.
 *
 * (c) RUNALYZE <mail@runalyze.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace Runalyze\DEM\Provider\GeoTIFF;

use Runalyze\DEM\Exception\RuntimeException;
use Runalyze\DEM\Provider\AbstractResourceReader;

/**
 * @see http://www.awaresystems.be/imaging/tiff/tifftags.html
 */
class GeoTIFFReader extends AbstractResourceReader
{
    /**
     * The number of bytes required to hold a TIFF offset address.
     * @var int
     */
    const LEN_OFFSET = 4;

    /**
     * Magic number located at bytes 2-3 which identifies a TIFF file.
     * @var int
     */
    const MAGIC_TIFF_ID = 42;

    /** @var int */
    const TIFF_CONST_STRIPOFSETS = 273;

    /** @var int */
    const TIFF_CONST_IMAGE_WIDTH = 256;

    /** @var int */
    const TIFF_CONST_IMAGE_LENGTH = 257;

    /** @var int */
    const TIFF_CONST_BITS_PER_SAMPLE = 258;

    /** @var int */
    const TIFF_CONST_SAMPLES_PER_PIXEL = 277;

    /** @var int */
    const TIFF_CONST_ROWS_PER_STRIP = 278;

    /** @var int */
    const TIFF_CONST_STRIPBYTECOUNTS = 279;

    /** @var int */
    const TIFF_CONST_IFD_ENTRY_BYTES = 12;

    /** @var string */
    const BIG_ENDIAN = 'MM';

    /** @var string */
    const LITTLE_ENDIAN = 'II';

    /** @var int */
    const UNKNOWN = -32768;

    /** @var int The number of bytes containing each item of elevation data */
    protected $BytesPerSample = 2;

    /** @var int 	The number of components per pixel */
    protected $SamplesPerPixel = 1;

    /** @var int The number of rows per strip */
    protected $RowsPerStrip = 1;

    /** @var int */
    protected $NumDataRows;

    /** @var int */
    protected $NumDataCols;

    /** @var int */
    protected $StripOffsets;

    /** @var string */
    protected $ByteOrder;

    public function readHeader()
    {
        $this->checkByteOrderAndTiffIdentifier();
        $this->goToIFDEntries();
        $this->readIFDEntries();
    }

    /**
     * Go to the file header and work out the byte order (bytes 0-1) and TIFF identifier (bytes 2-3).
     * @throws RuntimeException
     */
    protected function checkByteOrderAndTiffIdentifier()
    {
        fseek($this->FileResource, 0);
        $data = unpack('c2chars/vTIFF_ID', fread($this->FileResource, 4));

        if (static::MAGIC_TIFF_ID !== $data['TIFF_ID']) {
            throw new RuntimeException('Provided GeoTIFF file is not a valid tiff file.');
        }

        $this->ByteOrder = sprintf('%c%c', $data['chars1'], $data['chars2']);

        if ($this->ByteOrder !== static::LITTLE_ENDIAN && $this->ByteOrder !== static::BIG_ENDIAN) {
            throw new RuntimeException('Provided GeoTIFF file has an unknown byte order.');
        }
    }

    /**
     * The remaining 4 bytes in the header are the offset to the IFD.
     */
    protected function goToIFDEntries()
    {
        fseek($this->FileResource, 4);

        $ifdOffsetFormat = $this->isLittleEndian() ? 'VIFDoffset' : 'NIFDoffset';
        $data = unpack($ifdOffsetFormat, fread($this->FileResource, 4));

        fseek($this->FileResource, $data['IFDoffset']);
    }

    /**
     * Read IFD entries which (the number of entries in each is in the first two bytes).
     */
    protected function readIFDEntries()
    {
        $countFormat = $this->isLittleEndian() ? 'vcount' : 'ncount';
        $countData = unpack($countFormat, fread($this->FileResource, 2));
        $ifdFormat = $this->isLittleEndian() ? 'vtag/vtype/Vcount/Voffset' : 'ntag/ntype/Ncount/Noffset';

        for ($i = 0; $i < $countData['count']; ++$i) {
            $constData = unpack($ifdFormat, fread($this->FileResource, static::TIFF_CONST_IFD_ENTRY_BYTES));

            switch ($constData['tag']) {
                case static::TIFF_CONST_IMAGE_WIDTH:
                    $this->NumDataCols = $constData['offset'];
                    break;
                case static::TIFF_CONST_IMAGE_LENGTH:
                    $this->NumDataRows = $constData['offset'];
                    break;
                case static::TIFF_CONST_BITS_PER_SAMPLE:
                    $this->BytesPerSample = (int) ($constData['offset'] / 8);
                    break;
                case static::TIFF_CONST_SAMPLES_PER_PIXEL:
                    $this->SamplesPerPixel = $constData['offset'];
                    break;
                case static::TIFF_CONST_ROWS_PER_STRIP:
                    $this->RowsPerStrip = $constData['offset'];
                    break;
                case static::TIFF_CONST_STRIPOFSETS:
                    $this->StripOffsets = $constData['offset'];
                    break;
            }
        }
    }

    /**
     * @return bool
     */
    protected function isLittleEndian()
    {
        return static::LITTLE_ENDIAN === $this->ByteOrder;
    }

    /**
     * @param  float   $relativeLatitude
     * @param  float   $relativeLongitude
     * @return float[] array(row, col)
     */
    public function getExactRowAndColFor($relativeLatitude, $relativeLongitude)
    {
        return [
            $relativeLatitude * ($this->NumDataRows - 1),
            $relativeLongitude * ($this->NumDataCols - 1),
        ];
    }

    /**
     * @param  int      $row
     * @param  int      $col
     * @return int|bool
     */
    public function getElevationFor($row, $col)
    {
        fseek($this->FileResource, $this->StripOffsets + ceil($row / $this->RowsPerStrip) * static::LEN_OFFSET);

        $firstColumnData = unpack('Voffset', fread($this->FileResource, static::LEN_OFFSET));

        fseek($this->FileResource, $firstColumnData['offset'] + ($this->NumDataCols * ($row % $this->RowsPerStrip) + $col) * $this->BytesPerSample);

        $elevation = unpack('velevation', fread($this->FileResource, $this->BytesPerSample))['elevation'];

        return ($elevation <= self::UNKNOWN || $elevation >= -self::UNKNOWN) ? false : $elevation;
    }
}


<?php
namespace Czim\CmsAclModule\Http\Controllers\Api;

use Czim\CmsAclModule\Api\Transformers\PermissionTransformer;
use Czim\CmsAuth\Http\Controllers\Controller;
use Czim\CmsCore\Api\Response\TransformContainer;
use Czim\CmsCore\Contracts\Core\CoreInterface;

class PermissionsController extends Controller
{

    /**
     * @var CoreInterface
     */
    protected $core;

    /**
     * @param CoreInterface    $core
     */
    public function __construct(CoreInterface $core)
    {
        $this->core = $core;

        $this->core->acl()->initialize();
    }

    /**
     * Returns available permissions as defined by loaded modules.
     *
     * @return mixed
     */
    public function available()
    {
        return $this->core->api()->response(
            $this->makeContainer(
                $this->core->modules()->getAllPermissions()
            )
        );
    }

    /**
     * Returns available permissions for a single module.
     *
     * @param $key
     * @return mixed
     */
    public function module($key)
    {
        if ( ! $this->core->modules()->has($key)) {
            abort(404, 'Module not loaded');
        }

        return $this->core->api()->response(
            $this->makeContainer(
                $this->core->modules()->getModulePermissions($key)
            )
        );
    }

    /**
     * Returns the permissions actually in use by users and roles.
     *
     * @return mixed
     */
    public function used()
    {
        return $this->core->api()->response(
            $this->makeContainer(
                $this->core->auth()->getAllPermissions()
            )
        );
    }

    /**
     * Wraps data in a transform container.
     *
     * @param array $data
     * @param bool  $collection
     * @return TransformContainer
     */
    protected function makeContainer($data, $collection = true)
    {
        return new TransformContainer([
            'content'     => $data,
            'transformer' => new PermissionTransformer,
            'collection'  => $collection,
        ]);
    }
}


<?php

namespace Pakettikauppa;

use Pakettikauppa\Shipment\AdditionalService;
use Pakettikauppa\Shipment\Info;
use Pakettikauppa\Shipment\Parcel;
use Pakettikauppa\Shipment\Sender;
use Pakettikauppa\Shipment\Receiver;

/**
 * Class Shipment
 *
 * A container for all shipment data.
 *
 * For the API to work a shipment must have a Sender, Receiver, $shipping_method and at least 1 Parcel.
 * For shipments with more then 1 Parcel, Multi-parcel shipment (3102) additional service must be added.
 *
 * @package Pakettikauppa
 */
class Shipment
{
    /**
     * @var Sender
     */
    private $sender;
    /**
     * @var Receiver
     */
    private $receiver;
    /**
     * @var integer
     */
    private $shipping_method;
    /**
     * @var AdditionalService[]
     */
    private $additional_services;
    /**
     * @var Info
     */
    private $shipment_info;
    /**
     * @var Parcel[]
     */
    private $parcels;

    /**
     * @var string
     */
    private $tracking_code;

    /**
     * @var string
     */
    private $reference;

    /**
     * @var string base64 encoded shipping label pdf
     */
    private $pdf;

    /**
     * @var bool
     */
    private $print_return_label;

    public function __construct()
    {
        $this->additional_services  = array();
        $this->print_return_label   = false;
        $this->parcels              = array();
    }

    public function addAdditionalService(AdditionalService $additional_service)
    {
        $this->additional_services[] = $additional_service;
    }

    public function addParcel(Parcel $parcel)
    {
        $this->parcels[] = $parcel;
    }

    /**
     * @param boolean $include If true a return shipping label is also generated and appended to the shipping label pdf, if the shipping method supports returns.
     */
    public function includeReturnLabel($include)
    {
        if($include)
            $this->print_return_label = true;
        else
            $this->print_return_label = false;
    }

    public function setSender(Sender $sender)
    {
        $this->sender = $sender;
    }

    public function setReceiver(Receiver $receiver)
    {
        $this->receiver = $receiver;
    }

    public function setShipmentInfo(Info $info)
    {
        $this->shipment_info = $info;
    }

    public function setShippingMethod($shipping_method_code)
    {
        $this->shipping_method = $shipping_method_code;
    }

    /**
     * @return string
     */
    public function getTrackingCode()
    {
        return $this->tracking_code;
    }

    /**
     * @param string $tracking_code
     */
    public function setTrackingCode($tracking_code)
    {
        $this->tracking_code = $tracking_code;
    }

    /**
     * Sets a pickup point for the shipment.
     *
     * @param $pickup_point_id
     */
    public function setPickupPoint($pickup_point_id)
    {
        $service = new AdditionalService();
        $service->setServiceCode(2106); // alternative pickup point
        $service->addSpecifier('pickup_point_id', $pickup_point_id);

        $this->addAdditionalService($service);
    }

    /**
     * @return string
     */
    public function getPdf()
    {
        return $this->pdf;
    }

    /**
     * @param string $pdf
     */
    public function setPdf($pdf)
    {
        $this->pdf = $pdf;
    }

    /**
     * @return string
     */
    public function getReference()
    {
        return $this->reference;
    }

    /**
     * @param string $reference
     */
    public function setReference($reference)
    {
        $this->reference = $reference;
    }

    /**
     * Builds the xml from given data
     *
     * @return SimpleXMLElement
     */
    private function toXml()
    {
        $xml = new SimpleXMLElement('<eChannel/>');

        $routing = $xml->addChild('ROUTING');
        $routing->addChild("Routing.Time", time());

        $shipment = $xml->addChild('Shipment');

        $sender = $shipment->addChild('Shipment.Sender');
        $sender->addChild('Sender.Name1', $this->sender->getName1());
        $sender->addChild('Sender.Name2', $this->sender->getName2());
        $sender->addChild('Sender.Addr1', $this->sender->getAddr1());
        $sender->addChild('Sender.Addr2', $this->sender->getAddr2());
        $sender->addChild('Sender.Addr3', $this->sender->getAddr3());
        $sender->addChild('Sender.Postcode', $this->sender->getPostcode());
        $sender->addChild('Sender.City', $this->sender->getCity());
        $sender->addChild('Sender.Country', $this->sender->getCountry());
        $sender->addChild('Sender.Phone', $this->sender->getPhone());
        $sender->addChild('Sender.Vatcode', $this->sender->getVatcode());

        $receiver = $shipment->addChild('Shipment.Recipient');
        $receiver->addChild('Recipient.Name1', $this->receiver->getName1());
        $receiver->addChild('Recipient.Name2', $this->receiver->getName2());
        $receiver->addChild('Recipient.Addr1', $this->receiver->getAddr1());
        $receiver->addChild('Recipient.Addr2', $this->receiver->getAddr2());
        $receiver->addChild('Recipient.Addr3', $this->receiver->getAddr3());
        $receiver->addChild('Recipient.Postcode', $this->receiver->getPostcode());
        $receiver->addChild('Recipient.City', $this->receiver->getCity());
        $receiver->addChild('Recipient.Country', $this->receiver->getCountry());
        $receiver->addChild('Recipient.Phone', $this->receiver->getPhone());
        $receiver->addChild('Recipient.Vatcode', $this->receiver->getVatcode());
        $receiver->addChild('Recipient.Email', $this->receiver->getEmail());

        $consignment = $shipment->addChild('Shipment.Consignment');
        $consignment->addChild('Consignment.Reference', $this->shipment_info->getReference());
        $consignment->addChild('Consignment.Product', $this->shipping_method);
        $consignment->addChild('Consignment.Contentcode', $this->shipment_info->getContentCode());
        $consignment->addChild('Consignment.ReturnInstruction', $this->shipment_info->getReturnInstruction());
        $consignment->addChild('Consignment.Invoicenumber', $this->shipment_info->getInvoiceNumber());
        $consignment->addChild('Consignment.Merchandisevalue', $this->shipment_info->getMerchandiseValue());

        foreach ($this->additional_services as $service)
        {
            if($service->isValid())
            {
                $additional_service = $consignment->addChild('Consignment.AdditionalService');
                $additional_service->addChild('AdditionalService.ServiceCode', $service->getServiceCode());

                foreach ($service->getSpecifiers() as $nameValue)
                {
                    $specifier          = $additional_service->addChild('AdditionalService.Specifier', $nameValue[1]);
                    $specifier['name']  = $nameValue[0];
                }
            }
        }

        $additional_info = $consignment->addChild('Consignment.AdditionalInfo');
        $additional_info->addChild('AdditionalInfo.Text', $this->shipment_info->getAdditionalInfoText());

        foreach ($this->parcels as $parcel)
        {
            $parcel_xml = $consignment->addChild('Consignment.Parcel');
            $parcel_xml->addChild('Parcel.Reference', $parcel->getReference());
            $parcel_xml->addChild('Parcel.PackageType', $parcel->getPackageType());
            $weight = $parcel_xml->addChild('Parcel.Weight', $parcel->getWeight());
            $volume = $parcel_xml->addChild('Parcel.Volume', $parcel->getVolume());

            $weight['unit'] = 'kg';
            $volume['unit'] = 'm3';

            $parcel_xml->addChild('Parcel.Infocode', $parcel->getInfocode());
            $parcel_xml->addChild('Parcel.Contents', $parcel->getContents());

            if($this->print_return_label)
                $parcel_xml->addChild('Parcel.ReturnService', 2108);

            foreach ($parcel->getContentLines() as $content_line)
            {
                $content = $parcel_xml->addChild('Parcel.contentline');
                $content->addChild('contentline.description', $content_line->getDescription());
                $content->addChild('contentline.quantity', $content_line->getQuantity());
                $content->addChild('contentline.currency', $content_line->getCurrency());
                $content->addChild('contentline.netweight', $content_line->getNetweight());
                $content->addChild('contentline.value', $content_line->getValue());
                $content->addChild('contentline.countryoforigin', $content_line->getCountryOfOrigin());
                $content->addChild('contentline.tariffcode', $content_line->getTariffCode());
            }
        }

        return $xml;
    }

    /**
     * Returns the class data as an xml string
     *
     * @return string $xml
     */
    public function asXml()
    {
        return $this->toXml()->asXML();
    }

    /**
     * Returns the class data as a SimpleXmlElement
     *
     * @return \SimpleXMLElement
     */
    public function asSimpleXml()
    {
        return $this->toXml();
    }
}


<?php

namespace Pakettikauppa;

class SimpleXMLElement extends \SimpleXMLElement
{
  /**
   * Escapes input text
   *
   * @param string
   * @param string
   */
  public function addChild($key, $value = null, $namespace = null)
  {
    if ( $value != null )
    {
      $value = htmlspecialchars($value, ENT_XML1);
    }

    return parent::addChild($key, $value, $namespace);
  }
}


<?php
/**
 * @author Richard Weinhold
 */
namespace ricwein\FileSystem\Storage;

use ricwein\FileSystem\Helper\Stream;

use ricwein\FileSystem\Storage;
use ricwein\FileSystem\Enum\Hash;
use ricwein\FileSystem\Exceptions\RuntimeException;
use ricwein\FileSystem\Storage\Extensions\Binary;

/**
 * represents a file/directory from in-memory
 */
class Memory extends Storage
{

    /**
     * @var string|null
     */
    protected $content = '';

    /**
     * @param string|null $content
     */
    public function __construct(?string $content = null)
    {
        if ($content !== null) {
            $this->content = $content;
        }
    }

    /**
     * @inheritDoc
     */
    public function doesSatisfyConstraints(): bool
    {
        return true;
    }

    /**
     * @inheritDoc
     */
    public function isFile(): bool
    {
        return $this->content !== null;
    }

    /**
     * @inheritDoc
     */
    public function isDir():bool
    {
        return true;
    }

    /**
     * @inheritDoc
     */
    public function isExecutable(): bool
    {
        return true;
    }

    /**
     * @inheritDoc
     */
    public function isSymlink(): bool
    {
        return true;
    }

    /**
     * @inheritDoc
     */
    public function isReadable(): bool
    {
        return true;
    }

    /**
     * @inheritDoc
     */
    public function isWriteable(): bool
    {
        return true;
    }

    /**
     * @inheritDoc
     */
    public function readFile(?int $offset = null, ?int $length = null, int $mode = LOCK_SH): string
    {
        if ($offset !== null && $length !== null) {
            return mb_substr($this->content ?? '', $offset, $length, '8bit');
        }

        return $this->content ?? '';
    }

    /**
     * @inheritDoc
     */
    public function streamFile(?int $offset = null, ?int $length = null, int $mode = LOCK_SH): void
    {
        echo $this->readFile($offset, $length, $mode);
    }

    /**
     * @inheritDoc
     */
    public function writeFile(string $content, bool $append = false, int $mode = 0): bool
    {
        if ($this->content === null) {
            $this->content = '';
        }

        if ($append) {
            $this->content .= $content;
        } else {
            $this->content = $content;
        }

        return true;
    }

    /**
     * @inheritDoc
     */
    public function removeFile():bool
    {
        $this->content = null;
        return true;
    }

    /**
     * @inheritDoc
     */
    public function getSize(): int
    {
        return ($this->content === null) ? 0 : mb_strlen($this->content, '8bit');
    }

    /**
     * @inheritDoc
     */
    public function getFileType(bool $withEncoding = false): string
    {
        return (new \finfo($withEncoding ? FILEINFO_MIME : FILEINFO_MIME_TYPE))->buffer($this->content ?? '');
    }

    /**
     * @inheritDoc
     */
    public function getFileHash(int $mode = Hash::CONTENT, string $algo = 'sha256'): string
    {
        switch ($mode) {
            case Hash::CONTENT: return hash($algo, $this->content ?? '', false);
            case Hash::FILENAME: case Hash::FILEPATH: throw new RuntimeException('unable to calculate filepath/name hash for in-memory-files', 500);
            default: throw new RuntimeException('unknown hashing-mode', 500);
        }
    }

    /**
     * @inheritDoc
     */
    public function getTime(): int
    {
        return time();
    }

    /**
     * @inheritDoc
     */
    public function touch(bool $ifNewOnly = false, ?int $time = null, ?int $atime = null): bool
    {
        return true;
    }

    /**
     * @inheritDoc
     */
    public function isDotfile(): bool
    {
        return false;
    }

    /**
     * @inheritDoc
     * @return Binary\Memory
     */
    public function getHandle(int $mode): Binary
    {
        return new Binary\Memory($this, $mode);
    }

    /**
     * this stream is <b>READONLY!</b>
     * @inheritDoc
     * @throws RuntimeException
     */
    public function getStream(string $mode = 'r+')
    {
        if (!in_array($mode, ['r+','w','w+','a+','x','x+','c+',true])) {
            throw new RuntimeException(sprintf('unable to open stream for memory-storage in non-write mode "%s"', $mode), 500);
        }

        $stream = \fopen('php://memory', $mode);

        if ($stream === false) {
            throw new RuntimeException('failed to open stream', 500);
        }

        // pre-fill stream
        if ($this->content !== null) {
            \fwrite($stream, $this->content);
            \rewind($stream);
        }
        return $stream;
    }

    /**
     * @inheritDoc
     * @throws RuntimeException
     */
    public function writeFromStream($stream): bool
    {
        $streamer = new Stream($stream);
        $this->content = $streamer->read();
        return true;
    }

    /**
     * @inheritDoc
     */
    public function copyFileTo(Storage $destination): bool
    {
        switch (true) {

            case $destination instanceof Disk:
                if (!$destination->writeFile($this->readFile())) {
                    return false;
                }
                $destination->path()->reload();
                return true;

            case $destination instanceof Flysystem:
            case $destination instanceof Memory:
            default:
                return $destination->writeFile($this->readFile());
        }
    }

    /**
    * @inheritDoc
     */
    public function moveFileTo(Storage $destination): bool
    {
        if (!$this->copyFileTo($destination)) {
            return false;
        }

        return $this->removeFile();
    }
}


<?php
/**
 * @author Richard Weinhold
 */
namespace ricwein\FileSystem\Storage\Extensions;

use ricwein\FileSystem\Storage;
use ricwein\FileSystem\Exceptions\RuntimeException;
use ricwein\FileSystem\Exceptions\AccessDeniedException;

/**
 * allows binary file access
 */
abstract class Binary
{

    /**
     * @var int
     */
    public const MODE_CLOSED = 0;

    /**
     * @var int
     */
    public const MODE_READ = 1;

    /**
     * @var int
     */
    public const MODE_WRITE = 2;

    /**
     * @var int
     */
    protected $mode = self::MODE_CLOSED;

    /**
     * @var int
     */
    protected $pos = 0;

    /**
     * @param Storage $storage
     * @param int $mode
     */
    public function __construct(Storage $storage, int $mode)
    {
        $this->applyAccessMode($mode);
    }

    /**
     * check current access-mode and set new modes
     * @param  int $mode
     * @return void
     * @throws AccessDeniedException
     */
    protected function applyAccessMode(int $mode): void
    {
        if ($this->mode === self::MODE_CLOSED) {

            // set new mode
            $this->mode = $mode;
            return;
        } elseif ($mode === $this->mode) {

            // nothing to do
            return;
        }

        // mode-switching detected
        throw new AccessDeniedException('unable to switch access-mode for existing binary file handle', 500);
    }

    /**
     * Write to a stream
     * @param  string $bytes bytes
     * @param  int|null $length byte-count
     * @return int
     */
    abstract public function write(string $bytes, ?int $length = null): int;

    /**
     * read from a stream
     * prevent partial reads (also uses run-time testing to prevent partial reads)
     * @param  int $length byte-count
     * @return string
     * @throws RuntimeException
     */
    abstract public function read(int $length): string;

    /**
     * get number of bytes remaining
     * @return int
     */
    public function remainingBytes(): int
    {
        return (int) (PHP_INT_MAX & ($this->getSize() - $this->pos));
    }

    /**
     * current position in file-buffer
     * @return int
     */
    public function getPos(): int
    {
        return $this->pos;
    }

    /**
     * gets file-size in bytes
     * @return int
     */
    abstract public function getSize(): int;

    /**
     * set the current cursor position to the desired location
     * @param  int $position
     * @return bool
     */
    abstract public function seek(int $position = 0): bool;
}


<?php

/*
 * This file is part of the Runalyze DEM Reader.
 *
 * (c) RUNALYZE <mail@runalyze.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

namespace Runalyze\DEM\Interpolation;

use Runalyze\DEM\Exception\InvalidArgumentException;

class LambdaInterpolation implements InterpolationInterface
{
    use ArgumentsCheckTrait;

    /** @var \Closure */
    protected $Lambda;

    /**
     * LambdaInterpolation constructor.
     * @param  \Closure                 $interpolationFunction
     * @throws InvalidArgumentException
     */
    public function __construct(\Closure $interpolationFunction)
    {
        if (!$this->isValidClosure($interpolationFunction)) {
            throw new InvalidArgumentException('Provided closure does not fulfill the requirements.');
        }

        $this->Lambda = $interpolationFunction;
    }

    /**
     * @param  \Closure $function
     * @return bool
     */
    protected function isValidClosure(\Closure $function)
    {
        $Reflection = new \ReflectionFunction($function);

        return 3 === $Reflection->getNumberOfRequiredParameters();
    }

    /**
     * Interpolate.
     *
     * p0------------p1
     * |      |
     * |      y
     * |      |
     * |--x-- Z
     * |
     * p2------------p3
     *
     * @param  float                    $x                      x position of Z within bounding box, required: $x in [0.0, 1.0]
     * @param  float                    $y                      y position of Z within bounding box, required: $y in [0.0, 1.0]
     * @param  array                    $elevationOnBoundingBox elevation data on [p0, p1, p2, p3]
     * @return int                      estimated elevation on point Z
     * @throws InvalidArgumentException
     */
    public function interpolate($x, $y, array $elevationOnBoundingBox)
    {
        $this->checkArguments($x, $y, $elevationOnBoundingBox);

        return $this->Lambda->__invoke($x, $y, $elevationOnBoundingBox);
    }
}


<?php
/**
 * @author Richard Weinhold
 */
namespace ricwein\FileSystem;

use ricwein\FileSystem\Directory;
use ricwein\FileSystem\Enum\Hash;
use ricwein\FileSystem\Helper\Constraint;
use ricwein\FileSystem\Helper\DirectoryIterator;
use ricwein\FileSystem\Storage;
use ricwein\FileSystem\Exceptions\AccessDeniedException;
use ricwein\FileSystem\Exceptions\UnexpectedValueException;

/**
 * represents a selected directory
 */
class Directory extends FileSystem
{
    /**
     * @var Storage\Disk
     */
    protected $storage;

    /**
     * @inheritDoc
     */
    public function __construct(Storage $storage, int $constraints = Constraint::STRICT)
    {
        if ($storage instanceof Storage\Memory) {
            throw new UnexpectedValueException('in-memory directories are not supported', 500);
        }

        if ($storage instanceof Storage\Disk\Temp && !$storage->isDir() && !$storage->mkdir()) {
            throw new AccessDeniedException('unable to create temp directory', 500);
        }

        parent::__construct($storage, $constraints);
    }

    /**
     * create new dir if not exists
     * @return self
     */
    public function mkdir(): self
    {
        if (!$this->storage->isDir()) {
            if (!$this->storage->mkdir()) {
                throw new AccessDeniedException(sprintf('unable to create directory at: "%s"', $this->storage->path()->raw), 500);
            }
        }
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function remove(): FileSystem
    {
        $this->storage->removeDir();
        return $this;
    }

    /**
     * @inheritDoc
     */
    public function isDir(): bool
    {
        return $this->storage->isDir();
    }

    /**
     * @param bool $recursive
     * @param bool $recursive
     * @return DirectoryIterator
     */
    public function list(bool $recursive = false): DirectoryIterator
    {
        return new DirectoryIterator($this->storage, $recursive);
    }

    /**
     * @inheritDoc
     * @param bool $recursive
     */
    public function getHash(int $mode = Hash::CONTENT, string $algo = 'sha256', bool $recursive = true): string
    {
        $fileHashes = [];

        /** @var File $entry */
        foreach ($this->list($recursive)->files($this->storage->getConstraints()) as $entry) {
            $fileHashes[] = $entry->getHash($mode, $algo);
        }

        return hash($algo, implode(':', $fileHashes), false);
    }

    /**
     * calculate size
     * @param bool $recursive
     * @return int
     * @throws UnexpectedValueException
     */
    public function getSize(bool $recursive = true): int
    {
        $size = 0;

        /** @var File $entry */
        foreach ($this->list($recursive)->files($this->storage->getConstraints()) as $file) {
            $size += $file->getSize();
        }
        return $size;
    }

    /**
     * changes current directory
     * @param string|FileSystem|Helper\Path $path ,...
     * @return self
     */
    public function cd(...$path): self
    {
        $this->storage->cd($path);
        return $this;
    }

    /**
     * move directory upwards (like /../)
     * @param int $move
     * @return self
     */
    public function up(int $move = 1): self
    {
        $this->storage->cd(array_fill(0, $move, '/..'));
        return $this;
    }

    /**
     * @param string $filename
     * @param int|null $constraints
     * @return File
     */
    public function file(string $filename, ?int $constraints = null): File
    {
        if (!$this->storage->doesSatisfyConstraints()) {
            throw $this->storage->getConstraintViolations();
        }

        $dirpath = $this->path()->raw;
        if (is_dir($dirpath)) {
            $dirpath = realpath($dirpath);
        }

        $safepath = $this->path()->safepath;
        if (is_dir($safepath)) {
            $safepath = realpath($safepath);
        }

        /** @var Storage $storage */
        $storage = null;

        if (is_dir($safepath) && strpos($dirpath, $safepath) === 0) {
            $storage = new Storage\Disk($safepath, str_replace($safepath, '', $dirpath), $filename);
        } else {
            $storage = new Storage\Disk($dirpath, $filename);
        }

        return new File(
            $storage,
            $constraints !== null ? $constraints : $this->storage->getConstraints()
        );
    }
}


<?php
/**
 * @author Richard Weinhold
 */
namespace ricwein\FileSystem\Helper;

use ricwein\FileSystem\Storage;
use ricwein\FileSystem\FileSystem;
use ricwein\FileSystem\Helper\Path;
use ricwein\FileSystem\Exceptions\UnexpectedValueException;
use ricwein\FileSystem\Exceptions\FileNotFoundException;

/**
 * creates a absolute path from current-working-directory
 */
class PathFinder
{
    /**
     * list of possible paths
     * => !not components of a single path!
     * @param  string[]|Path[]|Storage[]|FileSystem[] $paths
     * @return Storage
     */
    public static function try(array $paths): Storage
    {
        foreach ($paths as $diskpath) {
            if (is_string($diskpath)) {
                if (file_exists($diskpath)) {
                    return new Storage\Disk($diskpath);
                }
            } elseif ($diskpath instanceof Path) {
                if ($diskpath->fileInfo()->isFile() || $diskpath->fileInfo()->isDir()) {
                    return new Storage\Disk($diskpath);
                }
            } elseif ($diskpath instanceof Storage) {
                if ($diskpath->isFile() || $diskpath->isDir()) {
                    return $diskpath;
                }
            } elseif ($diskpath instanceof FileSystem) {
                if ($diskpath->isFile() || $diskpath->isDir()) {
                    return $diskpath->storage();
                }
            } else {
                throw new UnexpectedValueException(sprintf('invalid search-path of type \'%s\'', is_object($diskpath) ? get_class($diskpath) : gettype($diskpath)), 500);
            }
        }

        throw new FileNotFoundException('file not found', 404);
    }
}


<?php
/**
 * @author Richard Weinhold
 */
namespace ricwein\FileSystem\Helper;

use ricwein\FileSystem\Exceptions\RuntimeException;

/**
 * creates a absolute path from current-working-directory
 */
class Stream
{
    /**
     * @var resource
     */
    protected $handle;

    /**
     * @var bool
     */
    protected $closeOnFree = false;

    /**
     * @param resource $handle
     */
    public function __construct($handle)
    {
        if (!is_resource($handle)) {
            throw new RuntimeException(sprintf('file-handle must be of type \'resource\' but \'%s\' given', is_object($handle) ? get_class($handle) : gettype($handle)), 500);
        }

        $this->handle = $handle;
    }

    /**
     */
    public function __destruct()
    {
        if ($this->closeOnFree && is_resource($this->handle)) {
            \fclose($this->handle);
        }
    }

    /**
     * @throws RuntimeException
     * @return self
     */
    public function rewind(): self
    {
        if (\fseek($this->handle, 0) !== 0) {
            throw new RuntimeException('error while rewinding file', 500);
        }

        return $this;
    }

    /**
     * auto-close stream on destruction
     * @param  bool $activate
     * @return self
     */
    public function closeOnFree(bool $activate = true): self
    {
        $this->closeOnFree = $activate;
        return $this;
    }

    /**
     * [hash description]
     * @param  string $algo [description]
     * @return string       [description]
     */
    public function hash(string $algo = 'sha256'): string
    {
        $this->rewind();

        $hc = \hash_init($algo);
        \hash_update_stream($hc, $this->handle);
        return \hash_final($hc);
    }

    /**
     * @param  int|null $offset
     * @param  int|null $length
     * @throws RuntimeException
     * @return string
     */
    public function read(?int $offset = null, ?int $length = null): string
    {
        if (($offset === null || $length === null)) {
            $this->rewind();

            if (0 < $filesize = \fstat($this->handle)['size'] ?? 0) {
                if (false !== $buffer = \fread($this->handle, $filesize)) {
                    return $buffer;
                }
                throw new RuntimeException('error while reading file', 500);
            }

            return '';
        }

        if (\fseek($this->handle, $offset) !== 0) {
            throw new RuntimeException('error while seeking file', 500);
        }

        // read part of file
        if (false !== $result = \fread($this->handle, $length)) {
            return $result;
        }

        throw new RuntimeException('error while reading file', 500);
    }

    /**
     * @param  int|null $offset
     * @param  int|null $length
     * @param  int      $bufferSize
     * @throws RuntimeException
     * @return void
     */
    public function send(?int $offset = null, ?int $length = null, int $bufferSize = 1024): void
    {
        if ($offset === null || $length === null) {
            $this->rewind();

            if (\fpassthru($this->handle) !== false) {
                \flush();
                return;
            }

            throw new RuntimeException('error while reading file', 500);
        }

        if (\fseek($this->handle, $offset) !== 0) {
            throw new RuntimeException('error while seeking file', 500);
        }

        $remaining = $length;

        while ($remaining > 0 && !\feof($this->handle)) {
            $readLength = ($remaining > $bufferSize) ? $bufferSize : $remaining;
            $remaining -= $readLength;

            if (false !== $result = \fread($this->handle, $readLength)) {
                echo $result;
                \flush();
            } else {
                throw new RuntimeException('error while reading file', 500);
            }
        }
    }
}