YetiForceCompany/YetiForceCRM

View on GitHub
vtlib/Vtiger/Utils.php

Summary

Maintainability
A
0 mins
Test Coverage
F
46%
<?php
/* +***********************************************************************************
 * The contents of this file are subject to the vtiger CRM Public License Version 1.0
 * ("License"); You may not use this file except in compliance with the License
 * The Original Code is:  vtiger CRM Open Source
 * The Initial Developer of the Original Code is vtiger.
 * Portions created by vtiger are Copyright (C) vtiger.
 * All Rights Reserved.
 * ********************************************************************************** */

namespace vtlib;

/**
 * Provides few utility functions.
 */
class Utils
{
    /**
     * Check if given value is a number or not.
     *
     * @param mixed String or Integer
     * @param mixed $value
     */
    public static function isNumber($value)
    {
        return is_numeric($value) ? (int) $value == $value : false;
    }

    /**
     * Implode the prefix and suffix as string for given number of times.
     *
     * @param string prefix to use
     * @param int Number of times
     * @param string suffix to use (optional)
     * @param mixed $prefix
     * @param mixed $count
     * @param mixed $suffix
     */
    public static function implodestr($prefix, $count, $suffix = false)
    {
        $strvalue = '';
        for ($index = 0; $index < $count; ++$index) {
            $strvalue .= $prefix;
            if ($suffix && $index != ($count - 1)) {
                $strvalue .= $suffix;
            }
        }
        return $strvalue;
    }

    /**
     * Function to check the file access is made within web root directory as well as is safe for php inclusion.
     *
     * @param string File path to check
     * @param bool False to avoid die() if check fails
     * @param mixed $filepath
     * @param mixed $dieOnFail
     */
    public static function checkFileAccessForInclusion($filepath, $dieOnFail = true)
    {
        $unsafeDirectories = ['storage', 'cache', 'test'];
        $realfilepath = realpath($filepath);

        /** Replace all \\ with \ first */
        $realfilepath = str_replace('\\\\', '\\', $realfilepath);
        $rootdirpath = str_replace('\\\\', '\\', ROOT_DIRECTORY . \DIRECTORY_SEPARATOR);

        /** Replace all \ with / now */
        $realfilepath = str_replace('\\', '/', $realfilepath);
        $rootdirpath = str_replace('\\', '/', $rootdirpath);

        $relativeFilePath = str_replace($rootdirpath, '', $realfilepath);
        $filePathParts = explode('/', $relativeFilePath);

        if (0 !== stripos($realfilepath, $rootdirpath) || in_array($filePathParts[0], $unsafeDirectories)) {
            if ($dieOnFail) {
                \App\Log::error(__METHOD__ . '(' . $filepath . ') - Sorry! Attempt to access restricted file. realfilepath: ' . print_r($realfilepath, true));
                throw new \App\Exceptions\AppException('Sorry! Attempt to access restricted file.');
            }

            return false;
        }
        return true;
    }

    /**
     * Function to check the file access is made within web root directory.
     *
     * @param string File path to check
     * @param bool False to avoid die() if check fails
     * @param mixed $filepath
     * @param mixed $dieOnFail
     */
    public static function checkFileAccess($filepath, $dieOnFail = true)
    {
        // Set the base directory to compare with
        $use_root_directory = \App\Config::main('root_directory');
        if (empty($use_root_directory)) {
            $use_root_directory = realpath(__DIR__ . '/../../.');
        }

        $realfilepath = realpath($filepath);

        /** Replace all \\ with \ first */
        $realfilepath = str_replace('\\\\', '\\', $realfilepath);
        $rootdirpath = str_replace('\\\\', '\\', $use_root_directory);

        /** Replace all \ with / now */
        $realfilepath = str_replace('\\', '/', $realfilepath);
        $rootdirpath = str_replace('\\', '/', $rootdirpath);

        if (0 !== stripos($realfilepath, $rootdirpath)) {
            if ($dieOnFail) {
                \App\Log::error(__METHOD__ . '(' . $filepath . ') - Sorry! Attempt to access restricted file. realfilepath: ' . print_r($realfilepath, true));
                throw new \App\Exceptions\AppException('Sorry! Attempt to access restricted file.');
            }

            return false;
        }
        return true;
    }

    /**
     * Check if table is present in database.
     *
     * @param string tablename to check
     * @param mixed $tableName
     */
    public static function checkTable($tableName)
    {
        return \App\Db::getInstance()->isTableExists($tableName);
    }

    /**
     * Add column to existing table.
     *
     * @param string       $tableName  to alter
     * @param string       $columnName to add
     * @param array|string $criteria   ([\yii\db\Schema::TYPE_STRING, 1024] | string(1024))
     */
    public static function addColumn($tableName, $columnName, $criteria)
    {
        $db = \App\Db::getInstance();
        $tableSchema = $db->getSchema()->getTableSchema($tableName, true);
        if (null === $tableSchema->getColumn((string) $columnName)) {
            if (is_array($criteria)) {
                $criteria = $db->getSchema()->createColumnSchemaBuilder($criteria[0], $criteria[1]);
            }
            $db->createCommand()->addColumn($tableName, $columnName, $criteria)->execute();
        }
    }

    /**
     * Check if the given SQL is a CREATE statement.
     *
     * @param string SQL String
     * @param mixed $sql
     */
    public static function isCreateSql($sql)
    {
        if (preg_match('/(CREATE TABLE)/', strtoupper($sql))) {
            return true;
        }
        return false;
    }

    /**
     * Check if the given SQL is destructive (DELETE's DATA).
     *
     * @param string SQL String
     * @param mixed $sql
     */
    public static function isDestructiveSql($sql)
    {
        if (preg_match('/(DROP TABLE)|(DROP COLUMN)|(DELETE FROM)/', strtoupper($sql))) {
            return true;
        }
        return false;
    }
}