diff options
author | marvin-borner@live.com | 2018-04-16 21:09:05 +0200 |
---|---|---|
committer | marvin-borner@live.com | 2018-04-16 21:09:05 +0200 |
commit | cf14306c2b3f82a81f8d56669a71633b4d4b5fce (patch) | |
tree | 86700651aa180026e89a66064b0364b1e4346f3f /main/app/sprinkles/core/src/Util | |
parent | 619b01b3615458c4ed78bfaeabb6b1a47cc8ad8b (diff) |
Main merge to user management system - files are now at /main/public/
Diffstat (limited to 'main/app/sprinkles/core/src/Util')
-rwxr-xr-x | main/app/sprinkles/core/src/Util/BadClassNameException.php | 18 | ||||
-rwxr-xr-x | main/app/sprinkles/core/src/Util/Captcha.php | 159 | ||||
-rwxr-xr-x | main/app/sprinkles/core/src/Util/CheckEnvironment.php | 340 | ||||
-rwxr-xr-x | main/app/sprinkles/core/src/Util/ClassMapper.php | 94 | ||||
-rwxr-xr-x | main/app/sprinkles/core/src/Util/EnvironmentInfo.php | 68 | ||||
-rwxr-xr-x | main/app/sprinkles/core/src/Util/ShutdownHandler.php | 167 | ||||
-rwxr-xr-x | main/app/sprinkles/core/src/Util/Util.php | 173 |
7 files changed, 1019 insertions, 0 deletions
diff --git a/main/app/sprinkles/core/src/Util/BadClassNameException.php b/main/app/sprinkles/core/src/Util/BadClassNameException.php new file mode 100755 index 0000000..09c4ea5 --- /dev/null +++ b/main/app/sprinkles/core/src/Util/BadClassNameException.php @@ -0,0 +1,18 @@ +<?php +/** + * UserFrosting (http://www.userfrosting.com) + * + * @link https://github.com/userfrosting/UserFrosting + * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + */ +namespace UserFrosting\Sprinkle\Core\Util; + +/** + * Bad class name exception. Used when a class name is dynamically invoked, but the class does not exist. + * + * @author Alex Weissman (https://alexanderweissman.com) + */ +class BadClassNameException extends \LogicException +{ + // +} diff --git a/main/app/sprinkles/core/src/Util/Captcha.php b/main/app/sprinkles/core/src/Util/Captcha.php new file mode 100755 index 0000000..c788b77 --- /dev/null +++ b/main/app/sprinkles/core/src/Util/Captcha.php @@ -0,0 +1,159 @@ +<?php +/** + * UserFrosting (http://www.userfrosting.com) + * + * @link https://github.com/userfrosting/UserFrosting + * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + */ +namespace UserFrosting\Sprinkle\Core\Util; + +use UserFrosting\Session\Session; + +/** + * Captcha Class + * + * Implements the captcha for user registration. + * + * @author r3wt + * @author Alex Weissman (https://alexanderweissman.com) + * @see http://www.userfrosting.com/components/#messages + */ +class Captcha +{ + /** + * @var string The randomly generated captcha code. + */ + protected $code; + + /** + * @var string The captcha image, represented as a binary string. + */ + protected $image; + + /** + * @var UserFrosting\Session\Session We use the session object so that the hashed captcha token will automatically appear in the session. + */ + protected $session; + + /** + * @var string + */ + protected $key; + + /** + * Create a new captcha. + */ + public function __construct($session, $key) + { + $this->session = $session; + $this->key = $key; + + if (!$this->session->has($key)) { + $this->session[$key] = array(); + } + } + + /** + * Generates a new captcha for the user registration form. + * + * This generates a random 5-character captcha and stores it in the session with an md5 hash. + * Also, generates the corresponding captcha image. + */ + public function generateRandomCode() + { + $md5_hash = md5(rand(0,99999)); + $this->code = substr($md5_hash, 25, 5); + $enc = md5($this->code); + + // Store the generated captcha value to the session + $this->session[$this->key] = $enc; + + $this->generateImage(); + } + + /** + * Returns the captcha code. + */ + public function getCaptcha() + { + return $this->code; + } + + /** + * Returns the captcha image. + */ + public function getImage() + { + return $this->image; + } + + /** + * Check that the specified code, when hashed, matches the code in the session. + * + * Also, stores the specified code in the session with an md5 hash. + * @param string + * @return bool + */ + public function verifyCode($code) + { + return (md5($code) == $this->session[$this->key]); + } + + /** + * Generate the image for the current captcha. + * + * This generates an image as a binary string. + */ + protected function generateImage() + { + $width = 150; + $height = 30; + + $image = imagecreatetruecolor(150, 30); + + //color pallette + $white = imagecolorallocate($image, 255, 255, 255); + $black = imagecolorallocate($image, 0, 0, 0); + $red = imagecolorallocate($image,255,0,0); + $yellow = imagecolorallocate($image, 255, 255, 0); + $dark_grey = imagecolorallocate($image, 64,64,64); + $blue = imagecolorallocate($image, 0,0,255); + + //create white rectangle + imagefilledrectangle($image,0,0,150,30,$white); + + //add some lines + for($i=0;$i<2;$i++) { + imageline($image,0,rand()%10,10,rand()%30,$dark_grey); + imageline($image,0,rand()%30,150,rand()%30,$red); + imageline($image,0,rand()%30,150,rand()%30,$yellow); + } + + // RandTab color pallette + $randc[0] = imagecolorallocate($image, 0, 0, 0); + $randc[1] = imagecolorallocate($image,255,0,0); + $randc[2] = imagecolorallocate($image, 255, 255, 0); + $randc[3] = imagecolorallocate($image, 64,64,64); + $randc[4] = imagecolorallocate($image, 0,0,255); + + //add some dots + for($i=0;$i<1000;$i++) { + imagesetpixel($image,rand()%200,rand()%50,$randc[rand()%5]); + } + + //calculate center of text + $x = ( 150 - 0 - imagefontwidth( 5 ) * strlen( $this->code ) ) / 2 + 0 + 5; + + //write string twice + imagestring($image,5, $x, 7, $this->code, $black); + imagestring($image,5, $x, 7, $this->code, $black); + //start ob + ob_start(); + imagepng($image); + + //get binary image data + $this->image = ob_get_clean(); + + return $this->image; + } +} diff --git a/main/app/sprinkles/core/src/Util/CheckEnvironment.php b/main/app/sprinkles/core/src/Util/CheckEnvironment.php new file mode 100755 index 0000000..26925d9 --- /dev/null +++ b/main/app/sprinkles/core/src/Util/CheckEnvironment.php @@ -0,0 +1,340 @@ +<?php +/** + * UserFrosting (http://www.userfrosting.com) + * + * @link https://github.com/userfrosting/UserFrosting + * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + */ +namespace UserFrosting\Sprinkle\Core\Util; + +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Slim\Http\Body; + +/** + * Performs pre-flight tests on your server environment to check that it meets the requirements. + * + * @author Alex Weissman (https://alexanderweissman.com) + */ +class CheckEnvironment +{ + /** + * @var \RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator Locator service for stream resources. + */ + protected $locator; + + /** + * @var array The results of any failed checks performed. + */ + protected $resultsFailed = []; + + /** + * @var array The results of any successful checks performed. + */ + protected $resultsSuccess = []; + + /** + * @var \Slim\Views\Twig The view object, needed for rendering error page. + */ + protected $view; + + /** + * @var \Illuminate\Cache\CacheManager Cache service for cache access. + */ + protected $cache; + + /** + * Constructor. + * + * @param $view \Slim\Views\Twig The view object, needed for rendering error page. + * @param $locator \RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator Locator service for stream resources. + */ + public function __construct($view, $locator, $cache) + { + $this->view = $view; + $this->locator = $locator; + $this->cache = $cache; + } + + /** + * Invoke the CheckEnvironment middleware, performing all pre-flight checks and returning an error page if problems were found. + * + * @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request + * @param \Psr\Http\Message\ResponseInterface $response PSR7 response + * @param callable $next Next middleware + * + * @return \Psr\Http\Message\ResponseInterface + */ + public function __invoke($request, $response, $next) + { + $problemsFound = false; + + // If production environment and no cached checks, perform environment checks + if ($this->isProduction() && $this->cache->get('checkEnvironment') != 'pass') { + $problemsFound = $this->checkAll(); + + // Cache if checks passed + if (!$problemsFound) { + $this->cache->forever('checkEnvironment', 'pass'); + } + } elseif (!$this->isProduction()) { + $problemsFound = $this->checkAll(); + } + + if ($problemsFound) { + $results = array_merge($this->resultsFailed, $this->resultsSuccess); + + $response = $this->view->render($response, 'pages/error/config-errors.html.twig', [ + "messages" => $results + ]); + } else { + $response = $next($request, $response); + } + + return $response; + } + + /** + * Run through all pre-flight checks. + */ + public function checkAll() + { + $problemsFound = false; + + if ($this->checkApache()) $problemsFound = true; + + if ($this->checkPhp()) $problemsFound = true; + + if ($this->checkPdo()) $problemsFound = true; + + if ($this->checkGd()) $problemsFound = true; + + if ($this->checkImageFunctions()) $problemsFound = true; + + if ($this->checkPermissions()) $problemsFound = true; + + return $problemsFound; + } + + /** + * For Apache environments, check that required Apache modules are installed. + */ + public function checkApache() + { + $problemsFound = false; + + // Perform some Apache checks. We may also need to do this before any routing takes place. + if (strpos(php_sapi_name(), 'apache') !== false) { + + $require_apache_modules = ['mod_rewrite']; + $apache_modules = apache_get_modules(); + + $apache_status = []; + + foreach ($require_apache_modules as $module) { + if (!in_array($module, $apache_modules)) { + $problemsFound = true; + $this->resultsFailed['apache-' . $module] = [ + "title" => "<i class='fa fa-server fa-fw'></i> Missing Apache module <b>$module</b>.", + "message" => "Please make sure that the <code>$module</code> Apache module is installed and enabled. If you use shared hosting, you will need to ask your web host to do this for you.", + "success" => false + ]; + } else { + $this->resultsSuccess['apache-' . $module] = [ + "title" => "<i class='fa fa-server fa-fw'></i> Apache module <b>$module</b> is installed and enabled.", + "message" => "Great, we found the <code>$module</code> Apache module!", + "success" => true + ]; + } + } + } + + return $problemsFound; + } + + /** + * Check for GD library (required for Captcha). + */ + public function checkGd() + { + $problemsFound = false; + + if (!(extension_loaded('gd') && function_exists('gd_info'))) { + $problemsFound = true; + $this->resultsFailed['gd'] = [ + "title" => "<i class='fa fa-image fa-fw'></i> GD library not installed", + "message" => "We could not confirm that the <code>GD</code> library is installed and enabled. GD is an image processing library that UserFrosting uses to generate captcha codes for user account registration.", + "success" => false + ]; + } else { + $this->resultsSuccess['gd'] = [ + "title" => "<i class='fa fa-image fa-fw'></i> GD library installed!", + "message" => "Great, you have <code>GD</code> installed and enabled.", + "success" => true + ]; + } + + return $problemsFound; + } + + /** + * Check that all image* functions used by Captcha exist. + * + * Some versions of GD are missing one or more of these functions, thus why we check for them explicitly. + */ + public function checkImageFunctions() + { + $problemsFound = false; + + $funcs = [ + 'imagepng', + 'imagecreatetruecolor', + 'imagecolorallocate', + 'imagefilledrectangle', + 'imageline', + 'imagesetpixel', + 'imagefontwidth', + 'imagestring' + ]; + + foreach ($funcs as $func) { + if (!function_exists($func)) { + $problemsFound = true; + $this->resultsFailed['function-' . $func] = [ + "title" => "<i class='fa fa-code fa-fw'></i> Missing image manipulation function.", + "message" => "It appears that function <code>$func</code> is not available. UserFrosting needs this to render captchas.", + "success" => false + ]; + } else { + $this->resultsSuccess['function-' . $func] = [ + "title" => "<i class='fa fa-code fa-fw'></i> Function <b>$func</b> is available!", + "message" => "Sweet!", + "success" => true + ]; + } + } + + return $problemsFound; + } + + /** + * Check that PDO is installed and enabled. + */ + public function checkPdo() + { + $problemsFound = false; + + if (!class_exists('PDO')) { + $problemsFound = true; + $this->resultsFailed['pdo'] = [ + "title" => "<i class='fa fa-database fa-fw'></i> PDO is not installed.", + "message" => "I'm sorry, you must have PDO installed and enabled in order for UserFrosting to access the database. If you don't know what PDO is, please see <a href='http://php.net/manual/en/book.pdo.php'>http://php.net/manual/en/book.pdo.php</a>.", + "success" => false + ]; + } else { + $this->resultsSuccess['pdo'] = [ + "title" => "<i class='fa fa-database fa-fw'></i> PDO is installed!", + "message" => "You've got PDO installed. Good job!", + "success" => true + ]; + } + + return $problemsFound; + } + + /** + * Check that log, cache, and session directories are writable, and that other directories are set appropriately for the environment. + */ + function checkPermissions() + { + $problemsFound = false; + + $shouldBeWriteable = [ + $this->locator->findResource('log://') => true, + $this->locator->findResource('cache://') => true, + $this->locator->findResource('session://') => true + ]; + + if ($this->isProduction()) { + // Should be write-protected in production! + $shouldBeWriteable = array_merge($shouldBeWriteable, [ + \UserFrosting\SPRINKLES_DIR => false, + \UserFrosting\VENDOR_DIR => false + ]); + } + + // Check for essential files & perms + foreach ($shouldBeWriteable as $file => $assertWriteable) { + $is_dir = false; + if (!file_exists($file)) { + $problemsFound = true; + $this->resultsFailed['file-' . $file] = [ + "title" => "<i class='fa fa-file-o fa-fw'></i> File or directory does not exist.", + "message" => "We could not find the file or directory <code>$file</code>.", + "success" => false + ]; + } else { + $writeable = is_writable($file); + if ($assertWriteable !== $writeable) { + $problemsFound = true; + $this->resultsFailed['file-' . $file] = [ + "title" => "<i class='fa fa-file-o fa-fw'></i> Incorrect permissions for file or directory.", + "message" => "<code>$file</code> is " + . ($writeable ? "writeable" : "not writeable") + . ", but it should " + . ($assertWriteable ? "be writeable" : "not be writeable") + . ". Please modify the OS user or group permissions so that user <b>" + . exec('whoami') . "</b> " + . ($assertWriteable ? "has" : "does not have") . " write permissions for this directory.", + "success" => false + ]; + } else { + $this->resultsSuccess['file-' . $file] = [ + "title" => "<i class='fa fa-file-o fa-fw'></i> File/directory check passed!", + "message" => "<code>$file</code> exists and is correctly set as <b>" + . ($writeable ? "writeable" : "not writeable") + . "</b>.", + "success" => true + ]; + } + } + } + return $problemsFound; + } + + /** + * Check that PHP meets the minimum required version. + */ + public function checkPhp() + { + $problemsFound = false; + + // Check PHP version + if (version_compare(phpversion(), \UserFrosting\PHP_MIN_VERSION, '<')) { + $problemsFound = true; + $this->resultsFailed['phpVersion'] = [ + "title" => "<i class='fa fa-code fa-fw'></i> You need to upgrade your PHP installation.", + "message" => "I'm sorry, UserFrosting requires version " . \UserFrosting\PHP_MIN_VERSION . " or greater. Please upgrade your version of PHP, or contact your web hosting service and ask them to upgrade it for you.", + "success" => false + ]; + } else { + $this->resultsSuccess['phpVersion'] = [ + "title" => "<i class='fa fa-code fa-fw'></i> PHP version checks out!", + "message" => "You're using PHP " . \UserFrosting\PHP_MIN_VERSION . "or higher. Great!", + "success" => true + ]; + } + + return $problemsFound; + } + + /** + * Determine whether or not we are running in production mode. + * + * @return bool + */ + public function isProduction() + { + return (getenv('UF_MODE') == 'production'); + } +} diff --git a/main/app/sprinkles/core/src/Util/ClassMapper.php b/main/app/sprinkles/core/src/Util/ClassMapper.php new file mode 100755 index 0000000..5fa0881 --- /dev/null +++ b/main/app/sprinkles/core/src/Util/ClassMapper.php @@ -0,0 +1,94 @@ +<?php +/** + * UserFrosting (http://www.userfrosting.com) + * + * @link https://github.com/userfrosting/UserFrosting + * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + */ + +namespace UserFrosting\Sprinkle\Core\Util; + +/** + * UserFrosting class mapper. + * + * This creates an abstraction layer for overrideable classes. + * For example, if we want to replace usages of the User class with MyUser, this abstraction layer handles that. + * + * @author Alex Weissman (https://alexanderweissman.com) + * @author Roger Ardibee + */ +class ClassMapper +{ + /** + * Mapping of generic class identifiers to specific class names. + */ + protected $classMappings = []; + + /** + * Creates an instance for a requested class identifier. + * + * @param string $identifier The identifier for the class, e.g. 'user' + * @param mixed ...$arg Whatever needs to be passed to the constructor. + */ + public function createInstance($identifier) + { + $className = $this->getClassMapping($identifier); + + $params = array_slice(func_get_args(), 1); + + // We must use reflection in PHP < 5.6. See http://stackoverflow.com/questions/8734522/dynamically-call-class-with-variable-number-of-parameters-in-the-constructor + $reflection = new \ReflectionClass($className); + + return $reflection->newInstanceArgs($params); + } + + /** + * Gets the fully qualified class name for a specified class identifier. + * + * @param string $identifier + * @return string + */ + public function getClassMapping($identifier) + { + if (isset($this->classMappings[$identifier])) { + return $this->classMappings[$identifier]; + } else { + throw new \OutOfBoundsException("There is no class mapped to the identifier '$identifier'."); + } + } + + /** + * Assigns a fully qualified class name to a specified class identifier. + * + * @param string $identifier + * @param string $className + * @return ClassMapper + */ + public function setClassMapping($identifier, $className) + { + // Check that class exists + if (!class_exists($className)) { + throw new BadClassNameException("Unable to find the class '$className'." ); + } + + $this->classMappings[$identifier] = $className; + + return $this; + } + + /** + * Call a static method for a specified class. + * + * @param string $identifier The identifier for the class, e.g. 'user' + * @param string $methodName The method to be invoked. + * @param mixed ...$arg Whatever needs to be passed to the method. + */ + public function staticMethod($identifier, $methodName) + { + $className = $this->getClassMapping($identifier); + + $params = array_slice(func_get_args(), 2); + + return call_user_func_array("$className::$methodName", $params); + } +} diff --git a/main/app/sprinkles/core/src/Util/EnvironmentInfo.php b/main/app/sprinkles/core/src/Util/EnvironmentInfo.php new file mode 100755 index 0000000..aba9837 --- /dev/null +++ b/main/app/sprinkles/core/src/Util/EnvironmentInfo.php @@ -0,0 +1,68 @@ +<?php +/** + * UserFrosting (http://www.userfrosting.com) + * + * @link https://github.com/userfrosting/UserFrosting + * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + */ +namespace UserFrosting\Sprinkle\Core\Util; + +use Illuminate\Database\Capsule\Manager as Capsule; + +/** + * EnvironmentInfo Class + * + * Gets basic information about the application environment. + * + * @author Alex Weissman (https://alexanderweissman.com) + */ +class EnvironmentInfo +{ + /** + * @var ContainerInterface The DI container for your application. + */ + public static $ci; + + /** + * Get an array of key-value pairs containing basic information about the default database. + * + * @return string[] the properties of this database. + */ + public static function database() + { + static::$ci['db']; + + $pdo = Capsule::connection()->getPdo(); + $results = []; + + try { + $results['type'] = $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); + } catch (Exception $e) { + $results['type'] = "Unknown"; + } + + try { + $results['version'] = $pdo->getAttribute(\PDO::ATTR_SERVER_VERSION); + } catch (Exception $e) { + $results['version'] = ""; + } + + return $results; + } + + /** + * Test whether a DB connection can be established. + * + * @return bool true if the connection can be established, false otherwise. + */ + public static function canConnectToDatabase() + { + try { + Capsule::connection()->getPdo(); + } catch (\PDOException $e) { + return false; + } + + return true; + } +} diff --git a/main/app/sprinkles/core/src/Util/ShutdownHandler.php b/main/app/sprinkles/core/src/Util/ShutdownHandler.php new file mode 100755 index 0000000..e7a6903 --- /dev/null +++ b/main/app/sprinkles/core/src/Util/ShutdownHandler.php @@ -0,0 +1,167 @@ +<?php +/** + * UserFrosting (http://www.userfrosting.com) + * + * @link https://github.com/userfrosting/UserFrosting + * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + */ +namespace UserFrosting\Sprinkle\Core\Util; + +use Interop\Container\ContainerInterface; +use UserFrosting\Sprinkle\Core\Http\Concerns\DeterminesContentType; + +/** + * Registers a handler to be invoked whenever the application shuts down. + * If it shut down due to a fatal error, will generate a clean error message. + * + * @author Alex Weissman (https://alexanderweissman.com) + */ +class ShutdownHandler +{ + use DeterminesContentType; + + /** + * @var ContainerInterface The global container object, which holds all your services. + */ + protected $ci; + + /** + * @var bool + */ + protected $displayErrorInfo; + + /** + * Constructor. + * + * @param ContainerInterface $ci The global container object, which holds all your services. + * @param bool $displayErrorInfo + */ + public function __construct(ContainerInterface $ci, $displayErrorInfo) + { + $this->ci = $ci; + $this->displayErrorInfo = $displayErrorInfo; + } + + /** + * Register this class with the shutdown handler. + * + * @return void + */ + public function register() + { + register_shutdown_function([$this, 'fatalHandler']); + } + + /** + * Set up the fatal error handler, so that we get a clean error message and alert instead of a WSOD. + */ + public function fatalHandler() + { + $error = error_get_last(); + $fatalErrorTypes = [ + E_ERROR, + E_PARSE, + E_CORE_ERROR, + E_COMPILE_ERROR, + E_RECOVERABLE_ERROR + ]; + + // Handle fatal errors and parse errors + if ($error !== NULL && in_array($error['type'], $fatalErrorTypes)) { + + // Build the appropriate error message (debug or client) + if ($this->displayErrorInfo) { + $errorMessage = $this->buildErrorInfoMessage($error); + } else { + $errorMessage = "Oops, looks like our server might have goofed. If you're an admin, please ensure that <code>php.log_errors</code> is enabled, and then check the <strong>PHP</strong> error log."; + } + + // For CLI, just print the message and exit. + if (php_sapi_name() === 'cli') { + exit($errorMessage . PHP_EOL); + } + + // For all other environments, print a debug response for the requested data type + echo $this->buildErrorPage($errorMessage); + + // If this is an AJAX request and AJAX debugging is turned off, write message to the alert stream + if ($this->ci->request->isXhr() && !$this->ci->config['site.debug.ajax']) { + if ($this->ci->alerts && is_object($this->ci->alerts)) { + $this->ci->alerts->addMessageTranslated('danger', $errorMessage); + } + } + + header('HTTP/1.1 500 Internal Server Error'); + exit(); + } + } + + /** + * Build the error message string. + * + * @param array $error + * @return string + */ + protected function buildErrorInfoMessage(array $error) + { + $errfile = $error['file']; + $errline = (string) $error['line']; + $errstr = $error['message']; + + $errorTypes = [ + E_ERROR => 'Fatal error', + E_PARSE => 'Parse error', + E_CORE_ERROR => 'PHP core error', + E_COMPILE_ERROR => 'Zend compile error', + E_RECOVERABLE_ERROR => 'Catchable fatal error' + ]; + + return "<strong>" . $errorTypes[$error['type']] . "</strong>: $errstr in <strong>$errfile</strong> on line <strong>$errline</strong>"; + } + + /** + * Build an error response of the appropriate type as determined by the request's Accept header. + * + * @param string $message + * @return string + */ + protected function buildErrorPage($message) + { + $contentType = $this->determineContentType($this->ci->request, $this->ci->config['site.debug.ajax']); + + switch ($contentType) { + case 'application/json': + $error = ['message' => $message]; + return json_encode($error, JSON_PRETTY_PRINT); + + case 'text/html': + return $this->buildHtmlErrorPage($message); + + default: + case 'text/plain': + return $message; + } + } + + /** + * Build an HTML error page from an error string. + * + * @param string $errorMessage + * @return string + */ + protected function buildHtmlErrorPage($message) + { + $title = 'UserFrosting Application Error'; + $html = "<p>$message</p>"; + + return sprintf( + "<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'>" . + "<title>%s</title><style>body{margin:0;padding:30px;font:12px/1.5 Helvetica,Arial,Verdana," . + "sans-serif;}h1{margin:0;font-size:48px;font-weight:normal;line-height:48px;}" . + "</style></head><body><h1>%s</h1>%s</body></html>", + $title, + $title, + $html + ); + } +} diff --git a/main/app/sprinkles/core/src/Util/Util.php b/main/app/sprinkles/core/src/Util/Util.php new file mode 100755 index 0000000..ae551cf --- /dev/null +++ b/main/app/sprinkles/core/src/Util/Util.php @@ -0,0 +1,173 @@ +<?php +/** + * UserFrosting (http://www.userfrosting.com) + * + * @link https://github.com/userfrosting/UserFrosting + * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + */ +namespace UserFrosting\Sprinkle\Core\Util; + +/** + * Util Class + * + * Static utility functions. + * + * @author Alex Weissman (https://alexanderweissman.com) + */ +class Util +{ + /** + * Extracts specific fields from one associative array, and places them into another. + * + * @param mixed[] $inputArray + * @param string[] $fieldArray + * @param bool $remove + * @return mixed[] + */ + static public function extractFields(&$inputArray, $fieldArray, $remove = true) + { + $result = []; + + foreach ($fieldArray as $name) { + if (array_key_exists($name, $inputArray)) { + $result[$name] = $inputArray[$name]; + + // Optionally remove value from input array + if ($remove) { + unset($inputArray[$name]); + } + } + } + + return $result; + } + + /** + * Extracts numeric portion of a string (for example, for normalizing phone numbers). + * + * @param string $str + * @return string + */ + static public function extractDigits($str) + { + return preg_replace('/[^0-9]/', '', $str); + } + + /** + * Formats a phone number as a standard 7- or 10-digit string (xxx) xxx-xxxx + * + * @param string $phone + * @return string + */ + static public function formatPhoneNumber($phone) + { + $num = static::extractDigits($phone); + + $len = strlen($num); + + if ($len == 7) { + $num = preg_replace('/([0-9]{3})([0-9]{4})/', '$1-$2', $num); + } elseif ($len == 10) { + $num = preg_replace('/([0-9]{3})([0-9]{3})([0-9]{4})/', '($1) $2-$3', $num); + } + + return $num; + } + + /** + * Nicely format an array for printing. + * See https://stackoverflow.com/a/9776726/2970321 + * + * @param array $arr + * @return string + */ + static public function prettyPrintArray(array $arr) + { + $json = json_encode($arr); + $result = ''; + $level = 0; + $inQuotes = false; + $inEscape = false; + $endsLineLevel = NULL; + $jsonLength = strlen($json); + + for ($i = 0; $i < $jsonLength; $i++) { + $char = $json[$i]; + $newLineLevel = NULL; + $post = ''; + if ($endsLineLevel !== NULL) { + $newLineLevel = $endsLineLevel; + $endsLineLevel = NULL; + } + if ($inEscape) { + $inEscape = false; + } elseif ($char === '"') { + $inQuotes = !$inQuotes; + } elseif (!$inQuotes) { + switch ($char) { + case '}': case ']': + $level--; + $endsLineLevel = NULL; + $newLineLevel = $level; + break; + + case '{': case '[': + $level++; + + case ',': + $endsLineLevel = $level; + break; + + case ':': + $post = ' '; + break; + + case ' ': case '\t': case '\n': case '\r': + $char = ''; + $endsLineLevel = $newLineLevel; + $newLineLevel = NULL; + break; + } + } elseif ($char === '\\') { + $inEscape = true; + } + + if ($newLineLevel !== NULL) { + $result .= '<br>'.str_repeat( ' ', $newLineLevel); + } + + $result .= $char.$post; + } + + return $result; + } + + /** + * Generate a random phrase, consisting of a specified number of adjectives, followed by a noun. + * + * @param int $numAdjectives + * @param int $maxLength + * @param int $maxTries + * @param string $separator + * @return string + */ + static public function randomPhrase($numAdjectives, $maxLength = 9999999, $maxTries = 10, $separator = '-') + { + $adjectives = include('extra://adjectives.php'); + $nouns = include('extra://nouns.php'); + + for ($n = 0; $n < $maxTries; $n++) { + $keys = array_rand($adjectives, $numAdjectives); + $matches = array_only($adjectives, $keys); + + $result = implode($separator, $matches); + $result .= $separator . $nouns[array_rand($nouns)]; + $result = str_slug($result, $separator); + if (strlen($result) < $maxLength) { + return $result; + } + } + + return ''; + } +} |