Viewing File: /usr/local/cpanel/base/frontend/jupiter/ls_web_cache_manager/core/Lsc/UserUtil.php

<?php

/** *********************************************
 * LiteSpeed Web Cache Management Plugin for cPanel
 *
 * @author    Michael Alegre
 * @copyright 2018-2025 LiteSpeed Technologies, Inc.
 * *******************************************
 */

namespace LsUserPanel\Lsc;

use LsUserPanel\Ls_WebCacheMgr_Util;
use LsUserPanel\PluginSettings;

class UserUtil
{

    /**
     *
     * @return string
     *
     * @throws UserLSCMException  Thrown indirectly by
     *     PluginSettings::getSetting() call.
     * @throws UserLSCMException  Thrown indirectly by
     *     Ls_WebCacheMgr_Util::getHomeDir() call.
     */
    public static function getUserCacheDir()
    {
        $vhCacheRoot =
            PluginSettings::getSetting(PluginSettings::FLD_VHOST_CACHE_ROOT);

        if ( !empty($vhCacheRoot) && $vhCacheRoot[0] != '/' ) {
            $vhCacheRoot = Ls_WebCacheMgr_Util::getHomeDir() . "/$vhCacheRoot";
        }

        return ($vhCacheRoot == '') ? '' : $vhCacheRoot;
    }

    /**
     * Flushes LiteSpeed Cache for the current user by removing all VH cache
     * files.
     *
     * @param string $cacheDir  Path to user's VH cache directory.
     *
     * @return void
     *
     * @throws UserLSCMException  Thrown indirectly by UserLogger::addUiMsg()
     *     call.
     * @throws UserLSCMException  Thrown indirectly by UserLogger::addUiMsg()
     *     call.
     */
    public static function flushVHCacheRoot( $cacheDir )
    {
        if ( !file_exists($cacheDir) ) {
            UserLogger::addUiMsg(
                sprintf(
                    _('Could Not Find Cache Directory %s'),
                    htmlspecialchars($cacheDir)
                ),
                UserLogger::UI_ERR
            );
            return;
        }

        $flushed = false;

        foreach (
            [
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f'
            ]
            as
            $subDir
        ) {

            if ( Ls_WebCacheMgr_Util::rrmdir("$cacheDir/$subDir") ) {
                $flushed = true;
            }
        }

        if ( $flushed ) {
            $msg = _('Cache Files Successfully Flushed');
        }
        else {
            $msg = _('No Cache Files To Flush');
        }

        UserLogger::addUiMsg($msg, UserLogger::UI_SUCC);
    }

    /**
     *
     * @since 2.1
     *
     * @param string $file
     * @param string $owner
     * @param string $group
     */
    private static function changeUserGroup( $file, $owner, $group )
    {
        chown($file, $owner);
        chgrp($file, $group);
    }

    /**
     * Set file permissions of $file2 to match those of $file1.
     *
     * @since 2.1
     *
     * @param string $file1
     * @param string $file2
     */
    private static function matchPermissions( $file1, $file2 )
    {
        /**
         * convert dec to oct
         */
        chmod($file2, (fileperms($file1) & 0777));
    }

    /**
     *
     * @since 2.1
     *
     * @param string $file
     * @param string $backup
     *
     * @return bool
     *
     * @throws UserLSCMException  Thrown indirectly by UserLogger::debug() call.
     * @throws UserLSCMException  Thrown indirectly by UserLogger::debug() call.
     */
    private static function matchFileSettings( $file, $backup )
    {
        clearstatcache();

        $ownerID = fileowner($file);
        $groupID = filegroup($file);

        if ( $ownerID === false || $groupID === false ) {
            UserLogger::debug("Could not get owner/group of file $file");

            unlink($backup);

            UserLogger::debug("Removed file $backup");
            return false;
        }

        self::changeUserGroup($backup, $ownerID, $groupID);
        self::matchPermissions($file, $backup);

        return true;
    }

    /**
     *
     * @since 2.1
     *
     * @param string $filepath
     * @param string $bak
     *
     * @return string
     */
    private static function getBackupSuffix(
        $filepath,
        $bak = '_lscachebak_orig'
    )
    {
        $i = 1;

        if ( file_exists($filepath . $bak) ) {
            $bak = sprintf("_lscachebak_%02d", $i);

            while ( file_exists($filepath . $bak) ) {
                $i++;
                $bak = sprintf("_lscachebak_%02d", $i);
            }
        }

        return $bak;
    }

    /**
     *
     * @since 2.1
     *
     * @param string $filepath
     *
     * @return bool
     *
     * @throws UserLSCMException  Thrown indirectly by UserLogger::debug() call.
     * @throws UserLSCMException  Thrown indirectly by UserLogger::logMsg()
     *     call.
     * @throws UserLSCMException  Thrown indirectly by self::matchFileSettings()
     *     call.
     * @throws UserLSCMException  Thrown indirectly by UserLogger::debug() call.
     * @throws UserLSCMException  Thrown indirectly by UserLogger::debug() call.
     * @throws UserLSCMException  Thrown indirectly by UserLogger::info() call.
     */
    public static function createBackup( $filepath )
    {
        $backup = $filepath . self::getBackupSuffix($filepath);

        if ( !copy($filepath, $backup) ) {
            UserLogger::debug(
                "Could not backup file $filepath to location $backup"
            );

            return false;
        }

        UserLogger::logMsg("Created file $backup", UserLogger::L_VERBOSE);

        if ( !self::matchFileSettings($filepath, $backup) ) {
            UserLogger::debug(
                "Could not backup file $filepath to location $backup"
            );

            return false;
        }

        UserLogger::debug('Matched owner/group setting for both files');
        UserLogger::info(
            "Successfully backed up file $filepath to location $backup"
        );

        return true;
    }

    /**
     *
     * @deprecated 2.1  Moved to
     *     Ls_WebCacheMgr_Controller::getUserLSCMDataDir().
     *
     * @return string
     *
     * @throws UserLSCMException  Thrown indirectly by
     *     Ls_WebCacheMgr_Util::getUserLSCMDataDir() call.
     */
    public static function getUserLSCMDataDir()
    {
        return Ls_WebCacheMgr_Util::getUserLSCMDataDir();
    }

    /**
     *
     * @deprecated 2.1  Moved to
     *     Ls_WebCacheMgr_Controller::createUserLSCMDataDir().
     *
     * @throws UserLSCMException  Thrown indirectly by
     *     Ls_WebCacheMgr_Util::createUserLSCMDataDir() call.
     */
    public static function createUserLSCMDataDir()
    {
        Ls_WebCacheMgr_Util::createUserLSCMDataDir();
    }

    /**
     *
     * @deprecated 2.1 Moved to
     *     Ls_WebCacheMgr_Controller::getLscmUserDirReadmeContent().
     *
     * @return string
     */
    public static function getLscmUserDirReadmeContent()
    {
        return Ls_WebCacheMgr_Util::getLscmUserDirReadmeContent();
    }

    /**
     *
     * @since 2.1
     *
     * @param string $url
     * @param array  $postData
     *
     * @return string
     */
    public static function PostToUrl( $url, array $postData = [] )
    {
        $post_string = http_build_query($postData);

        if ( ini_get('allow_url_fopen') ) {
            /**
             * Silence warning when OpenSSL missing.
             */
            $ret1 = @file_get_contents(
                $url,
                false,
                stream_context_create(
                    [
                        'http'  => [
                            'method'  => 'POST',
                            'header'  => 'Content-type: '
                                . "application/x-www-form-urlencoded\n"
                                . 'Content-Length: '
                                . strlen($post_string)
                                . "\n",
                            'content' => $post_string
                        ]
                    ]
                )
            );

            if ( $ret1 !== false ) {
                return $ret1;
            }

        }

        if ( function_exists('curl_version') ) {
            $ch = curl_init();

            curl_setopt_array(
                $ch,
                [
                    CURLOPT_URL            => $url,
                    CURLOPT_POST           => true,
                    CURLOPT_POSTFIELDS     => $post_string,
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1
                ]
            );

            $ret2 = curl_exec($ch);
            curl_close($ch);

            return $ret2;
        }

        exec("curl --data \"$post_string\" $url", $output, $ret3);

        if ( $ret3 === 0 ) {
            return implode("\n", $output);
        }

        return '';
    }

    /**
     *
     * @since 2.2
     *
     * @param string   $url
     * @param string   $method
     * @param string[] $headers
     * @param string   $requestDataString
     *
     * @return array
     */
    private static function requestUrlUsingFileGetContents(
              $url,
              $method,
        array $headers = [],
              $requestDataString = ''
    )
    {
        if ( ini_get('allow_url_fopen') ) {
            /**
             * Silence warning when OpenSSL missing.
             */
            $content = @file_get_contents(
                $url,
                false,
                stream_context_create(
                    [
                        'http' => [
                            'method'        => $method,
                            'header'        => implode("\n", $headers) . "\n",
                            'content'       => $requestDataString,
                            'ignore_errors' => true
                        ]
                    ]
                )
            );

            if ( $content !== false ) {

                if ( isset($http_response_header[0]) ) {
                    $matched = preg_match(
                        '/HTTP\/.+\s(\d+)\s/',
                        $http_response_header[0],
                        $m
                    );

                    if ( $matched == 1 ) {
                        return [
                            'httpCode' => (int)$m[1],
                            'content'  => $content
                        ];
                    }
                }
            }
        }

        return [];
    }

    /**
     *
     * @since 2.2
     *
     * @param string   $url
     * @param string   $method
     * @param string[] $headers
     * @param string   $requestDataString
     *
     * @return array
     */
    private static function requestUrlUsingPhpCurl(
              $url,
              $method,
        array $headers = [],
              $requestDataString = ''
    )
    {
        if ( function_exists('curl_version') ) {
            $ch = curl_init();

            $curlOptions = [
                CURLOPT_URL            => $url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1
            ];

            if ( !empty($headers) ) {
                $curlOptions[CURLOPT_HTTPHEADER] = $headers;
            }

            switch ( $method ) {

                case 'POST':
                    $curlOptions[CURLOPT_POST]       = true;
                    $curlOptions[CURLOPT_POSTFIELDS] = $requestDataString;
                    break;

                case 'PUT':
                    $curlOptions[CURLOPT_CUSTOMREQUEST] = 'PUT';
                    $curlOptions[CURLOPT_POSTFIELDS]    = $requestDataString;
                    break;

                case 'DELETE':
                    $curlOptions[CURLOPT_CUSTOMREQUEST] = 'DELETE';
                    break;

                //no default
            }

            curl_setopt_array($ch, $curlOptions);

            $content  = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);

            if ( $content !== false ) {
                return [
                    'httpCode' => (int)$httpCode,
                    'content'  => $content
                ];
            }
        }

        return [];
    }

    /**
     *
     * @since 2.2
     *
     * @param string   $url
     * @param string   $method
     * @param string[] $headers
     * @param string   $requestDataString
     *
     * @return array
     */
    private static function requestUrlUsingCliCurl(
              $url,
              $method,
        array $headers = [],
              $requestDataString = ''
    )
    {
        $curlCmd = "curl -X $method -w \"HTTP_CODE: %{http_code}\n\"";

        if ( !empty($headers) ) {
            $curlCmd .= ' -H "'
                . implode('" -H "', str_replace('"', '\"', $headers))
                . '"';
        }

        $curlCmd .= " --data \""
            . str_replace('"', '\"', $requestDataString)
            . "\" $url";

        exec($curlCmd, $output, $ret);

        if (
                $ret === 0
                &&
                preg_match(
                    '/(.*)HTTP_CODE: (\d+)\n*/s',
                    implode("\n", $output),
                    $m
                )
                    ==
                    1
        ) {
            return [ 'httpCode' => (int)$m[2], 'content' => $m[1] ];
        }

        return [];
    }

    /**
     *
     * @since 2.2
     *
     * @param string   $url
     * @param string   $method
     * @param string[] $headers
     * @param string   $requestDataString
     *
     * @return array
     */
    public static function makeUrlRequest(
              $url,
              $method,
        array $headers = [],
              $requestDataString = ''
    )
    {
        $ret = self::requestUrlUsingFileGetContents(
            $url,
            $method,
            $headers,
            $requestDataString
        );

        if ( !empty($ret) ) {
            return $ret;
        }

        $ret = self::requestUrlUsingPhpCurl(
            $url,
            $method,
            $headers,
            $requestDataString
        );

        if ( !empty($ret) ) {
            return $ret;
        }

        $ret = self::requestUrlUsingCliCurl(
            $url,
            $method,
            $headers,
            $requestDataString
        );

        if ( !empty($ret) ) {
            return $ret;
        }

        return [];
    }

    /**
     * Wrapper for idn_to_utf8() function call to avoid "undefined" exceptions
     * when PHP intl module is not installed and enabled.
     *
     * @since 2.1.3.4
     *
     * @param string     $domain
     * @param int        $flags
     * @param int|null   $variant
     * @param array|null $idna_info
     *
     * @return false|string
     */
    public static function tryIdnToUtf8(
               $domain,
               $flags = 0,
               $variant = null,
        ?array &$idna_info = null
    )
    {
        if ( empty($domain) || !function_exists('idn_to_utf8') ) {
            return $domain;
        }

        return idn_to_utf8(
            $domain,
            $flags,
            ($variant != null) ? $variant : INTL_IDNA_VARIANT_UTS46,
            $idna_info
        );
    }

    /**
     * Wrapper for idn_to_ascii() function call to avoid "undefined" exceptions
     * when PHP intl module is not installed and enabled.
     *
     * @since 2.1.3.4
     *
     * @param string     $domain
     * @param int|null   $flags
     * @param int|null   $variant
     * @param array|null $idna_info
     *
     * @return false|string
     */
    public static function tryIdnToAscii(
               $domain,
               $flags = null,
               $variant = null,
        ?array &$idna_info = null )
    {
        if ( empty($domain) || !function_exists('idn_to_ascii') ) {
            return $domain;
        }

        return idn_to_ascii(
            $domain,
            ($flags != null)   ? $flags : IDNA_DEFAULT,
            ($variant != null) ? $variant : INTL_IDNA_VARIANT_UTS46,
            $idna_info
        );
    }

}
Back to Directory File Manager