Subida del módulo y tema de PrestaShop

This commit is contained in:
Kaloyan
2026-04-09 18:31:51 +02:00
parent 12c253296f
commit 16b3ff9424
39262 changed files with 7418797 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;

View File

@@ -0,0 +1,8 @@
version: 1.x-{build}
build: false
clone_depth: 2
clone_folder: c:\projects\sentry-php
skip_branch_with_pr: true
branches:
only:
- master

View File

@@ -0,0 +1,12 @@
<?php
$finder = Symfony\CS\Finder\DefaultFinder::create()
->in(__DIR__)
;
return Symfony\CS\Config\Config::create()
->setUsingCache(true)
->setUsingLinter(true)
->level(Symfony\CS\FixerInterface::PSR2_LEVEL)
->finder($finder)
;

View File

@@ -0,0 +1,4 @@
The Sentry PHP SDK was originally written by Michael van Tellingen
and is maintained by the Sentry Team.
http://github.com/getsentry/sentry-php/contributors

View File

@@ -0,0 +1,12 @@
Copyright (c) 2012 Sentry Team and individual contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the Raven, Sentry, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,11 @@
<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;

View File

@@ -0,0 +1,92 @@
#!/usr/bin/env php
<?php
// Maximize error reporting
error_reporting(E_ALL | E_STRICT);
// TODO: if we could get rid of this and have composer figure things out it'd make it
// a bit more sane
require(dirname(__file__) . '/../lib/Raven/Autoloader.php');
Raven_Autoloader::register();
function raven_cli_test($command, $args)
{
// Do something silly
try {
throw new Exception('This is a test exception sent from the Raven CLI.');
} catch (Exception $ex) {
return $ex;
}
}
function cmd_test($dsn)
{
// Parse DSN as a test
try {
if (empty(Raven_Client::parseDSN($dsn))) {
exit('ERROR: Missing DSN value');
}
} catch (InvalidArgumentException $ex) {
exit("ERROR: There was an error parsing your DSN:\n " . $ex->getMessage());
}
$client = new Raven_Client($dsn, array(
'trace' => true,
'curl_method' => 'sync',
'app_path' => realpath(__DIR__ . '/..'),
'base_path' => realpath(__DIR__ . '/..'),
));
$config = get_object_vars($client);
$required_keys = array('server', 'project', 'public_key');
echo "Client configuration:\n";
foreach ($required_keys as $key) {
if (empty($config[$key])) {
exit("ERROR: Missing configuration for $key");
}
if (is_array($config[$key])) {
echo "-> $key: [".implode(", ", $config[$key])."]\n";
} else {
echo "-> $key: $config[$key]\n";
}
}
echo "\n";
echo "Sending a test event:\n";
$ex = raven_cli_test("command name", array("foo" => "bar"));
$event_id = $client->captureException($ex);
echo "-> event ID: $event_id\n";
$last_error = $client->getLastError();
if (!empty($last_error)) {
exit("ERROR: There was an error sending the test event:\n " . $last_error);
}
echo "\n";
echo "Done!";
}
function main() {
global $argv;
if (!isset($argv[1])) {
exit('Usage: sentry test <dsn>');
}
$cmd = $argv[1];
switch ($cmd) {
case 'test':
cmd_test(@$argv[2]);
break;
default:
exit('Usage: sentry test <dsn>');
}
}
main();

View File

@@ -0,0 +1,11 @@
<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;

View File

@@ -0,0 +1,44 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Autoloads Raven classes.
*
* @package raven
*/
class Raven_Autoloader
{
/**
* Registers Raven_Autoloader as an SPL autoloader.
*/
public static function register()
{
spl_autoload_register(array('Raven_Autoloader', 'autoload'));
}
/**
* Handles autoloading of classes.
*
* @param string $class A class name.
*/
public static function autoload($class)
{
if (substr($class, 0, 6) !== 'Raven_') {
return;
}
$file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php';
if (is_file($file)) {
/** @noinspection PhpIncludeInspection */
require $file;
}
}
}

View File

@@ -0,0 +1,76 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Raven Breadcrumbs
*
* @package raven
*/
class Raven_Breadcrumbs
{
public $count;
public $pos;
public $size;
/**
* @var array[]
*/
public $buffer;
public function __construct($size = 100)
{
$this->size = $size;
$this->reset();
}
public function reset()
{
$this->count = 0;
$this->pos = 0;
$this->buffer = array();
}
public function record($crumb)
{
if (empty($crumb['timestamp'])) {
$crumb['timestamp'] = microtime(true);
}
$this->buffer[$this->pos] = $crumb;
$this->pos = ($this->pos + 1) % $this->size;
$this->count++;
}
/**
* @return array[]
*/
public function fetch()
{
$results = array();
for ($i = 0; $i <= ($this->size - 1); $i++) {
$idx = ($this->pos + $i) % $this->size;
if (isset($this->buffer[$idx])) {
$results[] = $this->buffer[$idx];
}
}
return $results;
}
public function is_empty()
{
return $this->count === 0;
}
public function to_json()
{
return array(
'values' => $this->fetch(),
);
}
}

View File

@@ -0,0 +1,45 @@
<?php
class Raven_Breadcrumbs_ErrorHandler
{
protected $existingHandler;
/**
* @var Raven_Client the client object that sends the message to the server
*/
protected $ravenClient;
/**
* @param Raven_Client $ravenClient
*/
public function __construct(Raven_Client $ravenClient)
{
$this->ravenClient = $ravenClient;
}
public function handleError($code, $message, $file = '', $line = 0, $context = array())
{
$this->ravenClient->breadcrumbs->record(array(
'category' => 'error_reporting',
'message' => $message,
'level' => $this->ravenClient->translateSeverity($code),
'data' => array(
'code' => $code,
'line' => $line,
'file' => $file,
),
));
if ($this->existingHandler !== null) {
return call_user_func($this->existingHandler, $code, $message, $file, $line, $context);
} else {
return false;
}
}
public function install()
{
$this->existingHandler = set_error_handler(array($this, 'handleError'), E_ALL);
return $this;
}
}

View File

@@ -0,0 +1,102 @@
<?php
use Monolog\Logger;
use Monolog\Handler\AbstractProcessingHandler;
class Raven_Breadcrumbs_MonologHandler extends AbstractProcessingHandler
{
/**
* Translates Monolog log levels to Raven log levels.
*/
protected $logLevels = array(
Logger::DEBUG => Raven_Client::DEBUG,
Logger::INFO => Raven_Client::INFO,
Logger::NOTICE => Raven_Client::INFO,
Logger::WARNING => Raven_Client::WARNING,
Logger::ERROR => Raven_Client::ERROR,
Logger::CRITICAL => Raven_Client::FATAL,
Logger::ALERT => Raven_Client::FATAL,
Logger::EMERGENCY => Raven_Client::FATAL,
);
protected $excMatch = '/^exception \'([^\']+)\' with message \'(.+)\' in .+$/s';
/**
* @var Raven_Client the client object that sends the message to the server
*/
protected $ravenClient;
/**
* @param Raven_Client $ravenClient
* @param int $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true)
{
parent::__construct($level, $bubble);
$this->ravenClient = $ravenClient;
}
/**
* @param string $message
* @return array|null
*/
protected function parseException($message)
{
if (preg_match($this->excMatch, $message, $matches)) {
return array($matches[1], $matches[2]);
}
return null;
}
/**
* {@inheritdoc}
*/
protected function write(array $record)
{
// sentry uses the 'nobreadcrumb' attribute to skip reporting
if (!empty($record['context']['nobreadcrumb'])) {
return;
}
if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) {
/**
* @var \Exception|\Throwable $exc
*/
$exc = $record['context']['exception'];
$crumb = array(
'type' => 'error',
'level' => $this->logLevels[$record['level']],
'category' => $record['channel'],
'data' => array(
'type' => get_class($exc),
'value' => $exc->getMessage(),
),
);
} else {
// TODO(dcramer): parse exceptions out of messages and format as above
if ($error = $this->parseException($record['message'])) {
$crumb = array(
'type' => 'error',
'level' => $this->logLevels[$record['level']],
'category' => $record['channel'],
'data' => array(
'type' => $error[0],
'value' => $error[1],
),
);
} else {
$crumb = array(
'level' => $this->logLevels[$record['level']],
'category' => $record['channel'],
'message' => $record['message'],
'data' => $record['context'],
);
}
}
$this->ravenClient->breadcrumbs->record($crumb);
}
}

View File

@@ -0,0 +1,11 @@
<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,198 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Raven_Compat
{
public static function gethostname()
{
if (function_exists('gethostname')) {
return gethostname();
}
return self::_gethostname();
}
public static function _gethostname()
{
return php_uname('n');
}
public static function hash_hmac($algo, $data, $key, $raw_output = false)
{
if (function_exists('hash_hmac')) {
return hash_hmac($algo, $data, $key, $raw_output);
}
return self::_hash_hmac($algo, $data, $key, $raw_output);
}
/**
* Implementation from 'KC Cloyd'.
*
* @param string $algo Name of selected hashing algorithm
* @param string $data Message to be hashed
* @param string $key Shared secret key used for generating the HMAC variant of the message digest
* @param bool $raw_output Must be binary
* @return string
* @doc http://php.net/manual/en/function.hash-hmac.php
*/
public static function _hash_hmac($algo, $data, $key, $raw_output = false)
{
$algo = strtolower($algo);
$pack = 'H'.strlen($algo('test'));
$size = 64;
$opad = str_repeat(chr(0x5C), $size);
$ipad = str_repeat(chr(0x36), $size);
if (strlen($key) > $size) {
$key = str_pad(pack($pack, $algo($key)), $size, chr(0x00));
} else {
$key = str_pad($key, $size, chr(0x00));
}
$keyLastPos = strlen($key) - 1;
for ($i = 0; $i < $keyLastPos; $i++) {
$opad[$i] = $opad[$i] ^ $key[$i];
$ipad[$i] = $ipad[$i] ^ $key[$i];
}
$output = $algo($opad.pack($pack, $algo($ipad.$data)));
return ($raw_output) ? pack($pack, $output) : $output;
}
/**
* Note that we discard the options given to be compatible
* with PHP < 5.3
*
* @param mixed $value
* @param int $options
* @param int $depth Set the maximum depth
* @return string
*/
public static function json_encode($value, $options = 0, $depth = 512)
{
if (function_exists('json_encode')) {
if (PHP_VERSION_ID < 50300) {
return json_encode($value);
} elseif (PHP_VERSION_ID < 50500) {
return json_encode($value, $options);
} else {
return json_encode($value, $options, $depth);
}
}
// @codeCoverageIgnoreStart
return self::_json_encode($value, $depth);
// @codeCoverageIgnoreEnd
}
/**
* @param mixed $value
* @param int $depth Set the maximum depth
* @return string|false
*/
public static function _json_encode($value, $depth = 513)
{
if (extension_loaded('xdebug')) {
ini_set('xdebug.max_nesting_level', 2048);
}
return self::_json_encode_lowlevel($value, $depth);
}
/**
* Implementation taken from
* http://www.mike-griffiths.co.uk/php-json_encode-alternative/
*
* @param mixed $value
* @param int $depth Set the maximum depth
* @return string|false
*/
private static function _json_encode_lowlevel($value, $depth)
{
static $jsonReplaces = array(
array('\\', '/', "\n", "\t", "\r", "\f", '"'),
array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\f', '\"'));
if (is_null($value)) {
return 'null';
}
if ($value === false) {
return 'false';
}
if ($value === true) {
return 'true';
}
if (is_scalar($value)) {
// Always use '.' for floats.
if (is_float($value)) {
return floatval(str_replace(',', '.', strval($value)));
}
if (is_string($value)) {
return sprintf('"%s"',
str_replace($jsonReplaces[0], $jsonReplaces[1], $value));
} else {
return $value;
}
} elseif ($depth <= 1) {
return false;
}
$isList = true;
for ($i = 0, reset($value); $i<count($value); $i++, next($value)) {
if (key($value) !== $i) {
$isList = false;
break;
}
}
$result = array();
if ($isList) {
foreach ($value as $v) {
$this_value = self::_json_encode($v, $depth - 1);
if ($this_value === false) {
return false;
}
$result[] = $this_value;
}
return '[' . join(',', $result) . ']';
} else {
foreach ($value as $k => $v) {
$this_value = self::_json_encode($v, $depth - 1);
if ($this_value === false) {
return false;
}
$result[] = self::_json_encode($k, $depth - 1).':'.$this_value;
}
return '{' . join(',', $result) . '}';
}
}
public static function strlen($string)
{
if (extension_loaded('mbstring')) {
return mb_strlen($string, 'UTF-8');
}
return strlen($string);
}
public static function substr($string, $start, $length)
{
if (extension_loaded('mbstring')) {
return mb_substr($string, $start, $length, 'UTF-8');
}
return substr($string, $start, $length);
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Storage for additional client context.
*
* @package raven
*/
class Raven_Context
{
/**
* @var array
*/
public $tags;
/**
* @var array
*/
public $extra;
/**
* @var array|null
*/
public $user;
public function __construct()
{
$this->clear();
}
/**
* Clean up existing context.
*/
public function clear()
{
$this->tags = array();
$this->extra = array();
$this->user = null;
}
}

View File

@@ -0,0 +1,126 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Asynchronous Curl connection manager.
*
* @package raven
*/
// TODO(dcramer): handle ca_cert
class Raven_CurlHandler
{
protected $join_timeout;
protected $multi_handle;
protected $options;
protected $requests;
public function __construct($options, $join_timeout = 5)
{
$this->options = $options;
$this->multi_handle = curl_multi_init();
$this->requests = array();
$this->join_timeout = $join_timeout;
$this->registerShutdownFunction();
}
public function __destruct()
{
$this->join();
}
public function enqueue($url, $data = null, $headers = array())
{
$ch = curl_init();
$new_headers = array();
foreach ($headers as $key => $value) {
array_push($new_headers, $key .': '. $value);
}
// XXX(dcramer): Prevent 100-continue response form server (Fixes GH-216)
$new_headers[] = 'Expect:';
curl_setopt($ch, CURLOPT_HTTPHEADER, $new_headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt_array($ch, $this->options);
if (isset($data)) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
curl_multi_add_handle($this->multi_handle, $ch);
$fd = (int)$ch;
$this->requests[$fd] = 1;
$this->select();
return $fd;
}
public function registerShutdownFunction()
{
register_shutdown_function(array($this, 'join'));
}
public function join($timeout = null)
{
if (!isset($timeout)) {
$timeout = $this->join_timeout;
}
$start = time();
do {
$this->select();
if (count($this->requests) === 0) {
break;
}
usleep(10000);
} while ($timeout !== 0 && time() - $start < $timeout);
}
/**
* @doc http://php.net/manual/en/function.curl-multi-exec.php
*/
protected function select()
{
$active = false;
do {
$mrc = curl_multi_exec($this->multi_handle, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($this->multi_handle) !== -1) {
do {
$mrc = curl_multi_exec($this->multi_handle, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
} else {
return;
}
}
while ($info = curl_multi_info_read($this->multi_handle)) {
$ch = $info['handle'];
$fd = (int)$ch;
curl_multi_remove_handle($this->multi_handle, $ch);
if (!isset($this->requests[$fd])) {
return;
}
unset($this->requests[$fd]);
}
}
}

View File

@@ -0,0 +1,231 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Event handlers for exceptions and errors
*
* $client = new Raven_Client('http://public:secret/example.com/1');
* $error_handler = new Raven_ErrorHandler($client);
* $error_handler->registerExceptionHandler();
* $error_handler->registerErrorHandler();
* $error_handler->registerShutdownFunction();
*
* @package raven
*/
// TODO(dcramer): deprecate default error types in favor of runtime configuration
// unless a reason can be determined that making them dynamic is better. They
// currently are not used outside of the fatal handler.
class Raven_ErrorHandler
{
protected $old_exception_handler;
protected $call_existing_exception_handler = false;
protected $old_error_handler;
protected $call_existing_error_handler = false;
protected $reservedMemory;
/** @var Raven_Client */
protected $client;
protected $send_errors_last = false;
protected $fatal_error_types = array(
E_ERROR,
E_PARSE,
E_CORE_ERROR,
E_CORE_WARNING,
E_COMPILE_ERROR,
E_COMPILE_WARNING,
E_STRICT,
);
/**
* @var array
* Error types which should be processed by the handler.
* A 'null' value implies "whatever error_reporting is at time of error".
*/
protected $error_types = null;
/** @var \Exception|null */
private $lastHandledException;
public function __construct($client, $send_errors_last = false, $error_types = null,
$__error_types = null)
{
// support legacy fourth argument for error types
if ($error_types === null) {
$error_types = $__error_types;
}
$this->client = $client;
$this->error_types = $error_types;
$this->fatal_error_types = array_reduce($this->fatal_error_types, array($this, 'bitwiseOr'));
if ($send_errors_last) {
$this->send_errors_last = true;
$this->client->store_errors_for_bulk_send = true;
}
}
public function bitwiseOr($a, $b)
{
return $a | $b;
}
public function handleException($e, $isError = false, $vars = null)
{
$event_id = $this->client->captureException($e, null, null, $vars);
try {
$e->event_id = $event_id;
} catch (\Exception $e) {
// Ignore any errors while setting the event id on the exception object
// @see: https://github.com/getsentry/sentry-php/issues/579
}
$this->lastHandledException = $e;
if (!$isError && $this->call_existing_exception_handler) {
if ($this->old_exception_handler !== null) {
call_user_func($this->old_exception_handler, $e);
} else {
throw $e;
}
}
}
public function handleError($type, $message, $file = '', $line = 0, $context = array())
{
// http://php.net/set_error_handler
// The following error types cannot be handled with a user defined function: E_ERROR,
// E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and
// most of E_STRICT raised in the file where set_error_handler() is called.
if (error_reporting() !== 0) {
$error_types = $this->error_types;
if ($error_types === null) {
$error_types = error_reporting();
}
if ($error_types & $type) {
$e = new ErrorException($message, 0, $type, $file, $line);
$this->handleException($e, true, $context);
}
}
if ($this->call_existing_error_handler) {
if ($this->old_error_handler !== null) {
return call_user_func(
$this->old_error_handler,
$type,
$message,
$file,
$line,
$context
);
} else {
return false;
}
}
return true;
}
public function handleFatalError()
{
unset($this->reservedMemory);
if (null === $error = error_get_last()) {
return;
}
if ($this->shouldCaptureFatalError($error['type'], $error['message'])) {
$e = new ErrorException(
@$error['message'], 0, @$error['type'],
@$error['file'], @$error['line']
);
$this->client->useCompression = $this->client->useCompression && PHP_VERSION_ID > 70000;
$this->handleException($e, true);
}
}
/**
* @param int $type
* @param string|null $message
* @return bool
*/
public function shouldCaptureFatalError($type, $message = null)
{
if (PHP_VERSION_ID >= 70000 && $this->lastHandledException) {
if ($type === E_CORE_ERROR && strpos($message, 'Exception thrown without a stack frame') === 0) {
return false;
}
if ($type === E_ERROR) {
$expectedMessage = 'Uncaught '
. \get_class($this->lastHandledException)
. ': '
. $this->lastHandledException->getMessage();
if (strpos($message, $expectedMessage) === 0) {
return false;
}
}
}
return (bool) ($type & $this->fatal_error_types);
}
/**
* Register a handler which will intercept unhandled exceptions and report them to the
* associated Sentry client.
*
* @param bool $call_existing Call any existing exception handlers after processing
* this instance.
* @return Raven_ErrorHandler
*/
public function registerExceptionHandler($call_existing = true)
{
$this->old_exception_handler = set_exception_handler(array($this, 'handleException'));
$this->call_existing_exception_handler = $call_existing;
return $this;
}
/**
* Register a handler which will intercept standard PHP errors and report them to the
* associated Sentry client.
*
* @param bool $call_existing Call any existing errors handlers after processing
* this instance.
* @param array $error_types All error types that should be sent.
* @return Raven_ErrorHandler
*/
public function registerErrorHandler($call_existing = true, $error_types = null)
{
if ($error_types !== null) {
$this->error_types = $error_types;
}
$this->old_error_handler = set_error_handler(array($this, 'handleError'), E_ALL);
$this->call_existing_error_handler = $call_existing;
return $this;
}
/**
* Register a fatal error handler, which will attempt to capture errors which
* shutdown the PHP process. These are commonly things like OOM or timeouts.
*
* @param int $reservedMemorySize Number of kilobytes memory space to reserve,
* which is utilized when handling fatal errors.
* @return Raven_ErrorHandler
*/
public function registerShutdownFunction($reservedMemorySize = 10)
{
register_shutdown_function(array($this, 'handleFatalError'));
$this->reservedMemory = str_repeat('x', 1024 * $reservedMemorySize);
return $this;
}
}

View File

@@ -0,0 +1,4 @@
<?php
class Raven_Exception extends Exception
{
}

View File

@@ -0,0 +1,45 @@
<?php
/**
* Base class for data processing.
*
* @package raven
*/
abstract class Raven_Processor
{
/**
* This constant defines the mask string used to strip sensitive information.
*/
const STRING_MASK = '********';
/**
* @var Raven_Client The Raven client
*/
protected $client;
/**
* Class constructor.
*
* @param Raven_Client $client The Raven client
*/
public function __construct(Raven_Client $client)
{
$this->client = $client;
}
/**
* Override the default processor options
*
* @param array $options Associative array of processor options
*/
public function setProcessorOptions(array $options)
{
}
/**
* Process and sanitize data, modifying the existing value if necessary.
*
* @param array $data Array of log data
*/
abstract public function process(&$data);
}

View File

@@ -0,0 +1,35 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* This processor removes all the cookies from the request to ensure no sensitive
* informations are sent to the server.
*
* @author Stefano Arlandini <sarlandini@alice.it>
*/
final class Raven_Processor_RemoveCookiesProcessor extends Raven_Processor
{
/**
* {@inheritdoc}
*/
public function process(&$data)
{
if (isset($data['request'])) {
if (isset($data['request']['cookies'])) {
$data['request']['cookies'] = self::STRING_MASK;
}
if (isset($data['request']['headers']) && isset($data['request']['headers']['Cookie'])) {
$data['request']['headers']['Cookie'] = self::STRING_MASK;
}
}
}
}

View File

@@ -0,0 +1,30 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* This processor removes all the data of the HTTP body to ensure no sensitive
* informations are sent to the server in case the request method is POST, PUT,
* PATCH or DELETE.
*
* @author Stefano Arlandini <sarlandini@alice.it>
*/
final class Raven_Processor_RemoveHttpBodyProcessor extends Raven_Processor
{
/**
* {@inheritdoc}
*/
public function process(&$data)
{
if (isset($data['request'], $data['request']['method']) && in_array(strtoupper($data['request']['method']), array('POST', 'PUT', 'PATCH', 'DELETE'))) {
$data['request']['data'] = self::STRING_MASK;
}
}
}

View File

@@ -0,0 +1,160 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Asterisk out passwords from password fields in frames, http,
* and basic extra data.
*
* @package raven
*/
class Raven_Processor_SanitizeDataProcessor extends Raven_Processor
{
const MASK = self::STRING_MASK;
const FIELDS_RE = '/(authorization|password|passwd|secret|password_confirmation|card_number|auth_pw)/i';
const VALUES_RE = '/^(?:\d[ -]*?){13,19}$/';
protected $fields_re;
protected $values_re;
protected $session_cookie_name;
/**
* {@inheritdoc}
*/
public function __construct(Raven_Client $client)
{
parent::__construct($client);
$this->fields_re = self::FIELDS_RE;
$this->values_re = self::VALUES_RE;
$this->session_cookie_name = ini_get('session.name');
}
/**
* {@inheritdoc}
*/
public function setProcessorOptions(array $options)
{
if (isset($options['fields_re'])) {
$this->fields_re = $options['fields_re'];
}
if (isset($options['values_re'])) {
$this->values_re = $options['values_re'];
}
}
/**
* Replace any array values with our mask if the field name or the value matches a respective regex
*
* @param mixed $item Associative array value
* @param string $key Associative array key
*/
public function sanitize(&$item, $key)
{
if (empty($item)) {
return;
}
if (preg_match($this->values_re, $item)) {
$item = self::STRING_MASK;
}
if (empty($key)) {
return;
}
if (preg_match($this->fields_re, $key)) {
$item = self::STRING_MASK;
}
}
public function sanitizeException(&$data)
{
foreach ($data['exception']['values'] as &$value) {
$this->sanitizeStacktrace($value['stacktrace']);
}
}
public function sanitizeHttp(&$data)
{
$http = &$data['request'];
if (!empty($http['cookies']) && is_array($http['cookies'])) {
$cookies = &$http['cookies'];
if (!empty($cookies[$this->session_cookie_name])) {
$cookies[$this->session_cookie_name] = self::STRING_MASK;
}
}
if (!empty($http['data']) && is_array($http['data'])) {
array_walk_recursive($http['data'], array($this, 'sanitize'));
}
}
public function sanitizeStacktrace(&$data)
{
foreach ($data['frames'] as &$frame) {
if (empty($frame['vars'])) {
continue;
}
array_walk_recursive($frame['vars'], array($this, 'sanitize'));
}
}
/**
* {@inheritdoc}
*/
public function process(&$data)
{
if (!empty($data['exception'])) {
$this->sanitizeException($data);
}
if (!empty($data['stacktrace'])) {
$this->sanitizeStacktrace($data['stacktrace']);
}
if (!empty($data['request'])) {
$this->sanitizeHttp($data);
}
if (!empty($data['extra'])) {
array_walk_recursive($data['extra'], array($this, 'sanitize'));
}
}
/**
* @return string
*/
public function getFieldsRe()
{
return $this->fields_re;
}
/**
* @param string $fields_re
*/
public function setFieldsRe($fields_re)
{
$this->fields_re = $fields_re;
}
/**
* @return string
*/
public function getValuesRe()
{
return $this->values_re;
}
/**
* @param string $values_re
*/
public function setValuesRe($values_re)
{
$this->values_re = $values_re;
}
}

View File

@@ -0,0 +1,64 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* This processor sanitizes the configured HTTP headers to ensure no sensitive
* informations are sent to the server.
*
* @author Stefano Arlandini <sarlandini@alice.it>
*/
final class Raven_Processor_SanitizeHttpHeadersProcessor extends Raven_Processor
{
/**
* @var string[] $httpHeadersToSanitize The list of HTTP headers to sanitize
*/
private $httpHeadersToSanitize = array();
/**
* {@inheritdoc}
*/
public function __construct(Raven_Client $client)
{
parent::__construct($client);
}
/**
* {@inheritdoc}
*/
public function setProcessorOptions(array $options)
{
$this->httpHeadersToSanitize = array_merge($this->getDefaultHeaders(), isset($options['sanitize_http_headers']) ? $options['sanitize_http_headers'] : array());
}
/**
* {@inheritdoc}
*/
public function process(&$data)
{
if (isset($data['request']) && isset($data['request']['headers'])) {
foreach ($data['request']['headers'] as $header => &$value) {
if (in_array($header, $this->httpHeadersToSanitize)) {
$value = self::STRING_MASK;
}
}
}
}
/**
* Gets the list of default headers that must be sanitized.
*
* @return string[]
*/
private function getDefaultHeaders()
{
return array('Authorization', 'Proxy-Authorization', 'X-Csrf-Token', 'X-CSRFToken', 'X-XSRF-TOKEN');
}
}

View File

@@ -0,0 +1,39 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* This processor removes the `pre_context`, `context_line` and `post_context`
* informations from all exceptions captured by an event.
*
* @author Stefano Arlandini <sarlandini@alice.it>
*/
class Raven_Processor_SanitizeStacktraceProcessor extends Raven_Processor
{
/**
* {@inheritdoc}
*/
public function process(&$data)
{
if (!isset($data['exception'], $data['exception']['values'])) {
return;
}
foreach ($data['exception']['values'] as &$exception) {
if (!isset($exception['stacktrace'])) {
continue;
}
foreach ($exception['stacktrace']['frames'] as &$frame) {
unset($frame['pre_context'], $frame['context_line'], $frame['post_context']);
}
}
}
}

View File

@@ -0,0 +1,11 @@
<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;

View File

@@ -0,0 +1,41 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Serializes a value into a representation that should reasonably suggest
* both the type and value, and be serializable into JSON.
* @package raven
*/
class Raven_ReprSerializer extends Raven_Serializer
{
protected function serializeValue($value)
{
if ($value === null) {
return 'null';
} elseif ($value === false) {
return 'false';
} elseif ($value === true) {
return 'true';
} elseif (is_float($value) && (int) $value == $value) {
return $value.'.0';
} elseif (is_integer($value) || is_float($value)) {
return (string) $value;
} elseif (is_object($value) || gettype($value) == 'object') {
return 'Object '.get_class($value);
} elseif (is_resource($value)) {
return 'Resource '.get_resource_type($value);
} elseif (is_array($value)) {
return 'Array of length ' . count($value);
} else {
return $this->serializeString($value);
}
}
}

View File

@@ -0,0 +1,19 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
@trigger_error('The '.__NAMESPACE__.'\Raven_SanitizeDataProcessor class is deprecated since version 1.7 and will be removed in 2.0. Use the Raven_Processor_SanitizeDataProcessor class in the same namespace instead.', E_USER_DEPRECATED);
/**
* {@inheritdoc}
*/
class Raven_SanitizeDataProcessor extends Raven_Processor_SanitizeDataProcessor
{
}

View File

@@ -0,0 +1,200 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This helper is based on code from Facebook's Phabricator project
*
* https://github.com/facebook/phabricator
*
* Specifically, it is an adaptation of the PhutilReadableSerializer class.
*
* @package raven
*/
class Raven_Serializer
{
/*
* The default mb detect order
*
* @see http://php.net/manual/en/function.mb-detect-encoding.php
*/
const DEFAULT_MB_DETECT_ORDER = 'auto';
/*
* Suggested detect order for western countries
*/
const WESTERN_MB_DETECT_ORDER = 'UTF-8, ASCII, ISO-8859-1, ISO-8859-2, ISO-8859-3, ISO-8859-4, ISO-8859-5, ISO-8859-6, ISO-8859-7, ISO-8859-8, ISO-8859-9, ISO-8859-10, ISO-8859-13, ISO-8859-14, ISO-8859-15, ISO-8859-16, Windows-1251, Windows-1252, Windows-1254';
/**
* This is the default mb detect order for the detection of encoding
*
* @var string
*/
protected $mb_detect_order = self::DEFAULT_MB_DETECT_ORDER;
/**
* The default maximum message lengths. Longer strings will be truncated
*
* @var int
*/
protected $message_limit = Raven_Client::MESSAGE_LIMIT;
/**
* The default max depth.
*
* @var int
*/
protected $default_max_depth = 3;
/**
* @param null|string $mb_detect_order
* @param null|int $message_limit
*/
public function __construct($mb_detect_order = null, $message_limit = null)
{
if ($mb_detect_order != null) {
$this->mb_detect_order = $mb_detect_order;
}
if ($message_limit != null) {
$this->message_limit = (int) $message_limit;
}
}
/**
* Serialize an object (recursively) into something safe for data
* sanitization and encoding.
*
* @param mixed $value
* @param int|null $max_depth
* @param int $_depth
* @return string|bool|double|int|null|object|array
*/
public function serialize($value, $max_depth = null, $_depth = 0)
{
$className = is_object($value) ? get_class($value) : null;
if (is_null($max_depth)) {
$max_depth = $this->getDefaultMaxDepth();
}
$toArray = is_array($value) || $className === 'stdClass';
if ($toArray && $_depth < $max_depth) {
$new = array();
foreach ($value as $k => $v) {
$new[$this->serializeValue($k)] = $this->serialize($v, $max_depth, $_depth + 1);
}
return $new;
}
return $this->serializeValue($value);
}
protected function serializeString($value)
{
$value = (string) $value;
// Check if mbstring extension is loaded
if (extension_loaded('mbstring')) {
// we always guarantee this is coerced, even if we can't detect encoding
if ($currentEncoding = mb_detect_encoding($value, $this->mb_detect_order)) {
$value = mb_convert_encoding($value, 'UTF-8', $currentEncoding);
} else {
$value = mb_convert_encoding($value, 'UTF-8');
}
}
if ($this->message_limit !== 0 && Raven_Compat::strlen($value) > $this->message_limit) {
$value = Raven_Compat::substr($value, 0, $this->message_limit - 10) . ' {clipped}';
}
return $value;
}
/**
* @param mixed $value
* @return string|bool|double|int|null
*/
protected function serializeValue($value)
{
if (is_null($value) || is_bool($value) || is_float($value) || is_integer($value)) {
return $value;
} elseif (is_object($value) || gettype($value) == 'object') {
return 'Object '.get_class($value);
} elseif (is_resource($value)) {
return 'Resource '.get_resource_type($value);
} elseif (is_array($value)) {
return 'Array of length ' . count($value);
} else {
return $this->serializeString($value);
}
}
/**
* @return string
* @codeCoverageIgnore
*/
public function getMbDetectOrder()
{
return $this->mb_detect_order;
}
/**
* @param string $mb_detect_order
*
* @return Raven_Serializer
* @codeCoverageIgnore
*/
public function setMbDetectOrder($mb_detect_order)
{
$this->mb_detect_order = $mb_detect_order;
return $this;
}
/**
* @return int
* @codeCoverageIgnore
*/
public function getMessageLimit()
{
return $this->message_limit;
}
/**
* @param int $message_limit
* @codeCoverageIgnore
*/
public function setMessageLimit($message_limit)
{
$this->message_limit = (int)$message_limit;
}
/**
* @return int
*/
public function getDefaultMaxDepth()
{
return $this->default_max_depth;
}
/**
* @param int $max_depth
*/
public function setDefaultMaxDepth($max_depth)
{
$this->default_max_depth = (int)$max_depth;
}
}

View File

@@ -0,0 +1,311 @@
<?php
/**
* Small helper class to inspect the stacktrace
*
* @package raven
*/
class Raven_Stacktrace
{
public static $statements = array(
'include',
'include_once',
'require',
'require_once',
);
public static function get_stack_info($frames,
$trace = false,
$errcontext = null,
$frame_var_limit = Raven_Client::MESSAGE_LIMIT,
$strip_prefixes = null,
$app_path = null,
$excluded_app_paths = null,
Raven_Serializer $serializer = null,
Raven_ReprSerializer $reprSerializer = null)
{
$serializer = $serializer ?: new Raven_Serializer();
$reprSerializer = $reprSerializer ?: new Raven_ReprSerializer();
/**
* PHP stores calls in the stacktrace, rather than executing context. Sentry
* wants to know "when Im calling this code, where am I", and PHP says "I'm
* calling this function" not "I'm in this function". Due to that, we shift
* the context for a frame up one, meaning the variables (which are the calling
* args) come from the previous frame.
*/
$result = array();
for ($i = 0; $i < count($frames); $i++) {
$frame = isset($frames[$i]) ? $frames[$i] : array();
$nextframe = isset($frames[$i + 1]) ? $frames[$i + 1] : array();
if (!array_key_exists('file', $frame)) {
$context = array();
if (!empty($frame['class'])) {
$context['line'] = sprintf('%s%s%s', $frame['class'], $frame['type'], $frame['function']);
try {
$reflect = new ReflectionClass($frame['class']);
$context['filename'] = $filename = $reflect->getFileName();
} catch (ReflectionException $e) {
// Forget it if we run into errors, it's not worth it.
}
} elseif (!empty($frame['function'])) {
$context['line'] = sprintf('%s(anonymous)', $frame['function']);
} else {
$context['line'] = sprintf('(anonymous)');
}
if (empty($context['filename'])) {
$context['filename'] = $filename = '[Anonymous function]';
}
$abs_path = '';
$context['prefix'] = '';
$context['suffix'] = '';
$context['lineno'] = 0;
} else {
$context = self::read_source_file($frame['file'], $frame['line']);
$abs_path = $frame['file'];
}
// strip base path if present
$context['filename'] = self::strip_prefixes($context['filename'], $strip_prefixes);
if ($i === 0 && isset($errcontext)) {
// If we've been given an error context that can be used as the vars for the first frame.
$vars = $errcontext;
} else {
if ($trace) {
$vars = self::get_frame_context($nextframe, $frame_var_limit);
} else {
$vars = array();
}
}
$data = array(
'filename' => $context['filename'],
'lineno' => (int) $context['lineno'],
'function' => isset($nextframe['function']) ? $nextframe['function'] : null,
'pre_context' => $serializer->serialize($context['prefix']),
'context_line' => $serializer->serialize($context['line']),
'post_context' => $serializer->serialize($context['suffix']),
);
// detect in_app based on app path
if ($app_path) {
$norm_abs_path = @realpath($abs_path) ?: $abs_path;
if (!$abs_path) {
$in_app = false;
} else {
$in_app = (bool)(substr($norm_abs_path, 0, strlen($app_path)) === $app_path);
}
if ($in_app && $excluded_app_paths) {
foreach ($excluded_app_paths as $path) {
if (substr($norm_abs_path, 0, strlen($path)) === $path) {
$in_app = false;
break;
}
}
}
$data['in_app'] = $in_app;
}
// dont set this as an empty array as PHP will treat it as a numeric array
// instead of a mapping which goes against the defined Sentry spec
if (!empty($vars)) {
$cleanVars = array();
foreach ($vars as $key => $value) {
$value = $reprSerializer->serialize($value);
if (is_string($value) || is_numeric($value)) {
$cleanVars[(string)$key] = Raven_Compat::substr($value, 0, $frame_var_limit);
} else {
$cleanVars[(string)$key] = $value;
}
}
$data['vars'] = $cleanVars;
}
$result[] = $data;
}
return array_reverse($result);
}
public static function get_default_context($frame, $frame_arg_limit = Raven_Client::MESSAGE_LIMIT)
{
if (!isset($frame['args'])) {
return array();
}
$i = 1;
$args = array();
foreach ($frame['args'] as $arg) {
$args['param'.$i] = self::serialize_argument($arg, $frame_arg_limit);
$i++;
}
return $args;
}
public static function get_frame_context($frame, $frame_arg_limit = Raven_Client::MESSAGE_LIMIT)
{
if (!isset($frame['args'])) {
return array();
}
// The reflection API seems more appropriate if we associate it with the frame
// where the function is actually called (since we're treating them as function context)
if (!isset($frame['function'])) {
return self::get_default_context($frame, $frame_arg_limit);
}
if (strpos($frame['function'], '__lambda_func') !== false) {
return self::get_default_context($frame, $frame_arg_limit);
}
if (isset($frame['class']) && $frame['class'] == 'Closure') {
return self::get_default_context($frame, $frame_arg_limit);
}
if (strpos($frame['function'], '{closure}') !== false) {
return self::get_default_context($frame, $frame_arg_limit);
}
if (in_array($frame['function'], self::$statements)) {
if (empty($frame['args'])) {
// No arguments
return array();
} else {
// Sanitize the file path
return array(
'param1' => self::serialize_argument($frame['args'][0], $frame_arg_limit),
);
}
}
try {
if (isset($frame['class'])) {
if (method_exists($frame['class'], $frame['function'])) {
$reflection = new ReflectionMethod($frame['class'], $frame['function']);
} elseif ($frame['type'] === '::') {
$reflection = new ReflectionMethod($frame['class'], '__callStatic');
} else {
$reflection = new ReflectionMethod($frame['class'], '__call');
}
} elseif (function_exists($frame['function'])) {
$reflection = new ReflectionFunction($frame['function']);
} else {
return self::get_default_context($frame, $frame_arg_limit);
}
} catch (ReflectionException $e) {
return self::get_default_context($frame, $frame_arg_limit);
}
$params = $reflection->getParameters();
$args = array();
foreach ($frame['args'] as $i => $arg) {
$arg = self::serialize_argument($arg, $frame_arg_limit);
if (isset($params[$i])) {
// Assign the argument by the parameter name
$args[$params[$i]->name] = $arg;
} else {
$args['param'.$i] = $arg;
}
}
return $args;
}
private static function serialize_argument($arg, $frame_arg_limit)
{
if (is_array($arg)) {
$_arg = array();
foreach ($arg as $key => $value) {
if (is_string($value) || is_numeric($value)) {
$_arg[$key] = Raven_Compat::substr($value, 0, $frame_arg_limit);
} else {
$_arg[$key] = $value;
}
}
return $_arg;
} elseif (is_string($arg) || is_numeric($arg)) {
return Raven_Compat::substr($arg, 0, $frame_arg_limit);
} else {
return $arg;
}
}
private static function strip_prefixes($filename, $prefixes)
{
if ($prefixes === null) {
return $filename;
}
foreach ($prefixes as $prefix) {
if (substr($filename, 0, strlen($prefix)) === $prefix) {
return substr($filename, strlen($prefix));
}
}
return $filename;
}
private static function read_source_file($filename, $lineno, $context_lines = 5)
{
$frame = array(
'prefix' => array(),
'line' => '',
'suffix' => array(),
'filename' => $filename,
'lineno' => $lineno,
);
if ($filename === null || $lineno === null) {
return $frame;
}
// Code which is eval'ed have a modified filename.. Extract the
// correct filename + linenumber from the string.
$matches = array();
$matched = preg_match("/^(.*?)\\((\\d+)\\) : eval\\(\\)'d code$/",
$filename, $matches);
if ($matched) {
$frame['filename'] = $filename = $matches[1];
$frame['lineno'] = $lineno = $matches[2];
}
// In the case of an anonymous function, the filename is sent as:
// "</path/to/filename>(<lineno>) : runtime-created function"
// Extract the correct filename + linenumber from the string.
$matches = array();
$matched = preg_match("/^(.*?)\\((\\d+)\\) : runtime-created function$/",
$filename, $matches);
if ($matched) {
$frame['filename'] = $filename = $matches[1];
$frame['lineno'] = $lineno = $matches[2];
}
if (!file_exists($filename)) {
return $frame;
}
try {
$file = new SplFileObject($filename);
$target = max(0, ($lineno - ($context_lines + 1)));
$file->seek($target);
$cur_lineno = $target+1;
while (!$file->eof()) {
$line = rtrim($file->current(), "\r\n");
if ($cur_lineno == $lineno) {
$frame['line'] = $line;
} elseif ($cur_lineno < $lineno) {
$frame['prefix'][] = $line;
} elseif ($cur_lineno > $lineno) {
$frame['suffix'][] = $line;
}
$cur_lineno++;
if ($cur_lineno > $lineno + $context_lines) {
break;
}
$file->next();
}
} catch (RuntimeException $exc) {
return $frame;
}
return $frame;
}
}

View File

@@ -0,0 +1,54 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
class Raven_TransactionStack
{
public function __construct()
{
$this->stack = array();
}
public function clear()
{
$this->stack = array();
}
public function peek()
{
$len = count($this->stack);
if ($len === 0) {
return null;
}
return $this->stack[$len - 1];
}
public function push($context)
{
$this->stack[] = $context;
}
/** @noinspection PhpInconsistentReturnPointsInspection
* @param string|null $context
* @return mixed
*/
public function pop($context = null)
{
if (!$context) {
return array_pop($this->stack);
}
while (!empty($this->stack)) {
if (array_pop($this->stack) === $context) {
return $context;
}
}
// @codeCoverageIgnoreStart
}
// @codeCoverageIgnoreEnd
}

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of Raven.
*
* (c) Sentry Team
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
/**
* Utilities
*
* @package raven
*/
class Raven_Util
{
/**
* Because we love Python, this works much like dict.get() in Python.
*
* Returns $var from $array if set, otherwise returns $default.
*
* @param array $array
* @param string $var
* @param mixed $default
* @return mixed
*/
public static function get($array, $var, $default = null)
{
if (isset($array[$var])) {
return $array[$var];
}
return $default;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;

View File

@@ -0,0 +1,11 @@
<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;

View File

@@ -0,0 +1,11 @@
<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;