# rabbit-loader/2.18.2/inc/public.php

RabbitLoader, version 2.18.2. 451 lines.

- Page: https://pluginprobe.com/plugins/rabbit-loader/2.18.2/code/inc/public.php
- Raw: https://pluginprobe.com/plugins/rabbit-loader/2.18.2/raw/inc/public.php
- Modified: 2023-05-24T14:54:56+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/rabbit-loader/2.18.2/code/inc/public.php#L10-L20`.

```php
<?php

class RabbitLoader_21_Public{

    static $skip_reason = '';
    const skip_reason_pm = "private-mode";
    const skip_reason_or = "rl-origin";
    const skip_reason_ep = "exclude-pattern";
    const no_optimization = "rl-no-optimization";
    static $wp_footer_called = false;
    static $add_action_called = false;
    static $is_origin = false;

    public static function addActions(){
        if(self::$add_action_called){
            return;
        }
        self::$add_action_called = true;
        //is_user_logged_in is a pluggable function and you could get a fatal error if you call it too early.
        add_action('init', 'RabbitLoader_21_Public::init', 10);
        add_action('shutdown', 'RabbitLoader_21_Public::shutdown', 10000);
        add_filter('wp_redirect', 'RabbitLoader_21_Public::wp_redirect', 10, 2);
        add_filter('redirect_canonical', 'RabbitLoader_21_Public::redirect_canonical', 10, 2);
        add_filter('pre_handle_404','RabbitLoader_21_Public::pre_handle_404', 10, 2);
        add_filter('paginate_links', 'RabbitLoader_21_Public::paginate_links', 10, 1);
        add_filter('nonce_life', 'RabbitLoader_21_Public::nonce_life');
        add_action('wp_footer', 'RabbitLoader_21_Public::wp_footer');
        add_action('get_footer', 'RabbitLoader_21_Public::wp_footer');

        RabbitLoader_21_CanonicalUrl::init();
        RabbitLoader_21_Util_WP::init();
        
        //Third party theme hooks
        add_action('kirki_output_inline_styles', function($value){
            #theme developed using kirki framework may generate lots of inline css referring to font files making the page load slow
            #https://github.com/kirki-framework/kirki/blob/3a5d5093b1a99d1c7b813608479fe8fc9348b6a3/packages/kirki-framework/module-css/src/CSS.php
            $value = false;
            return $value;
        }, -1);
    }

    public static function init()
    {  
        if(!empty($_SERVER["HTTP_X_RL_PINGBACK_V2"])){
            self::setup_endpoint();
            return;
        }

        // try{
        //     if(!empty($_SERVER["HTTP_X_RL_SET_OPTION"]) && strcmp($_SERVER["HTTP_X_RL_SET_OPTION"], 'rabbitloader_field_disconnect_reason')===0){
        //         $responses = ['time'=>date('c')];
        //         try{
        //             global $wpdb;
        //             $responses['disconnect_reason'] = $wpdb->get_results("select option_id, option_name from $wpdb->options where option_name in ('rabbitloader_field_disconnect_reason', 'rabbitloader_field_update_time')");
        //         }catch(Throwable $e){
        //             RabbitLoader_21_Core::on_exception($e);
        //         }
        //         RabbitLoader_21_Core::sendJsonResponse($responses);
        //     }
        // }catch(Throwable $e){
        //     RabbitLoader_21_Core::on_exception($e);
        // }

        if (current_user_can( 'manage_options' )) {
            add_action('admin_bar_menu', 'RabbitLoader_21_Public::adminBarMenu', 50);
            add_action('wp_enqueue_scripts', 'RabbitLoader_21_Public::adminBarScript');
        }

        RabbitLoader_21_CDN::init();
    }

    public static function shutdown($cache_served = false)
    {
        try{
            if(!$cache_served){
                self::optimized_version_missing();
                RabbitLoader_21_Core::clean_orphaned_cached_files(300);
            }else{
                RabbitLoader_21_Core::clean_orphaned_cached_files(3600);
            }
        }catch(Throwable $e){
            RabbitLoader_21_Core::on_exception($e);
        }
    }

    private static function can_cache_request($request_uri){
        if(!empty(self::$skip_reason)){
            return false;
        }
        if(RabbitLoader_21_Util_Core::get_request_type()!='get'){
            //Not a GET request, return
            self::$skip_reason = 'method-'.RabbitLoader_21_Util_Core::get_request_type();
            return false;
        }

        if(RabbitLoader_21_Util_WP::is_user_logged_in() || RabbitLoader_21_Util_WP::is_login_page()){
            //we are not serving cached content to logged in users
            self::$skip_reason = 'user-session';
            return false;
        }

        if(RabbitLoader_21_Util_WP::is_ajax()){
            self::$skip_reason = 'ajax';
            return false;
        }
        
        if(!empty($_SERVER["HTTP_X_RL_PINGBACK"]) || RabbitLoader_21_Util_Core::isNoOptimization() || !empty($_SERVER["HTTP_X_RL_DIAGNOSIS"])){
            //its origin pull form ur own server, let it get the original HTML
            self::$skip_reason = self::skip_reason_or;
            self::$is_origin = true;
            return false;
        }

        if(!empty($_COOKIE['woocommerce_items_in_cart'])){
            //TBD- user has some items in cart, in future version we will check how to serve a cached page with cart
            self::$skip_reason = 'cart-items';
            return false;
        }

        if(empty($_SERVER["HTTP_HOST"]) || RabbitLoader_21_Util_WP::is_cli() || !empty($_GET["mwprid"])){
            self::$skip_reason = 'cli';
            return false;
        }

        global $wp_query;
        if (isset($wp_query) && $wp_query->is_404()) {
            self::$skip_reason = '404-not-found';
            return false;
        }

        if (RabbitLoader_21_Util_WP::is_search()) {
            self::$skip_reason = 'search';
            return false;
        }

        if(RabbitLoader_21_Util_WP::is_cart()){
            self::$skip_reason = 'cart';
            return false;
        }

        if(RabbitLoader_21_Util_WP::is_checkout()){
            self::$skip_reason = 'checkout';
            return false;
        }

        RabbitLoader_21_Core::getWpUserOption($user_options);

        if(!empty($user_options['cart_uri']) && strcasecmp(RabbitLoader_21_Util_Core::serverURINoGet(), $user_options['cart_uri'])==0){
            self::$skip_reason = 'cart';
            return false;
        }

        if(!empty($user_options['checkout_uri']) && strcasecmp(RabbitLoader_21_Util_Core::serverURINoGet(), $user_options['checkout_uri'])==0){
            self::$skip_reason = 'checkout';
            return false;
        }

        if(!empty($user_options['exclude_patterns'])){
            $exclude_patterns = explode("\n", $user_options['exclude_patterns']);
            $matched = false;
            if(!empty($exclude_patterns)){
                foreach($exclude_patterns as $i=>$path_pattern){
                    if(!empty($path_pattern)){
                        $matched = fnmatch(trim($path_pattern), $request_uri);
                        if(!$matched){
                            $matched = fnmatch(trim($path_pattern), rawurldecode($request_uri));
                        }
                        if(!$matched){
                            $matched = fnmatch($path_pattern, rawurldecode($request_uri));
                        }
                        if($matched){break;}
                    }
                }
            }
            if($matched){
                self::$skip_reason = self::skip_reason_ep;
                return false;
            }
        }
        if(!empty($user_options['private_mode_val']) && empty($_GET['rltest'])){
            self::$skip_reason = self::skip_reason_pm;
            return false;
        }

        if(!empty(self::$skip_reason)){
            self::$skip_reason = self::$skip_reason;
            return false;
        }

        return true;
    }

    public static function getSkipReason(){
        return self::$skip_reason;
    }

    public static function process_incoming_request($mode='ac'){
        try{
            RabbitLoader_21_Util_Core::get_requested_uri($request_uri, $request_url);
            
            if(!self::can_cache_request($request_uri)){
                if(empty(self::$skip_reason)){self::$skip_reason='unknown';}
                RabbitLoader_21_Core::sendHeader('x-rl-cache: skipped-'.self::$skip_reason, true);
                return;
            }

            if(!empty($request_uri) && $request_uri!="/favicon.ico"){

                RabbitLoader_21_Core::get_cache_file_path($request_url, $cache_file);

                if(self::serve_from_cache_if_available($cache_file)){
                    //ignore buffer and serve from cache
                    self::shutdown(true);
                    exit;
                }

                RabbitLoader_21_Core::sendHeader('x-rl-cache: miss/'.$mode, true);
            }
        }catch(Throwable $e){
            RabbitLoader_21_Core::on_exception($e);
        }
    }

    private static function optimized_version_missing(){

        RabbitLoader_21_Util_Core::get_requested_uri($request_uri, $request_url);
        if(self::can_cache_request($request_uri)){
            $request_url.="\n";
            RabbitLoader_21_Util_Core::fac('cache_missed', $request_url, WP_DEBUG);
        }else if(strcmp(self::$skip_reason,self::skip_reason_pm)===0){
            if(!RabbitLoader_21_Core::cache_exists_for_url($request_url, 0)){
                $request_url.="\n";
                RabbitLoader_21_Util_Core::fac('cache_missed', $request_url, WP_DEBUG);
            }
        }else{
            //error_log($skip_reason.'=>'.$request_uri);
        }
    }

    public static function setup_endpoint(){
        if(empty($_SERVER["HTTP_X_RL_PINGBACK_V2"])){
            return;
        }

        $response = [
            'time'=>date('c')
        ];

        RabbitLoader_21_Core::getWpOption($rl_wp_options);
        $api_key = empty($_SERVER["HTTP_X_RL_APIKEY"]) ? '' : trim($_SERVER["HTTP_X_RL_APIKEY"]);
        $push_key = empty($_SERVER["HTTP_X_RL_PUSH_KEY"]) ? '' : trim($_SERVER["HTTP_X_RL_PUSH_KEY"]);

        $isValidKey1 = (!empty($rl_wp_options['rabbitloader_field_apikey']) && ($rl_wp_options['rabbitloader_field_apikey'] == $api_key));
        $isValidKey2 = (!empty($rl_wp_options['push_key']) && wp_check_password($push_key, $rl_wp_options['push_key']));
        $isValidKey3 = (function_exists('get_option') && !empty($api_key) && ($api_key == get_option('rabbitloader_field_apikey')));
        $isValidKey =  $isValidKey1 || $isValidKey2 || $isValidKey3;

        $rlaction = RabbitLoader_21_Util_Core::get_param('rlaction', true);

        if(!$isValidKey){
            $response['exception'] = 'key mismatch';
            http_response_code(200);
            echo json_encode($response);
            return;
        }

        if(strcasecmp($rlaction, 'warmup')===0){
            $queued_offset = intval($_POST['queued_offset']);
            RabbitLoader_21_Core::run_warmup($queued_offset, $response);
        }else if(strcasecmp($rlaction, 'purge')===0){
            $tp_purge_count = 0;
            RabbitLoader_21_Core::purge_all($purge_count, 'RL_PANEL', $tp_purge_count);
            $response['purged'] = 1;
            $response['purge_count'] = $purge_count;
            $response['tp_purge_count'] = $tp_purge_count;
        }else if(strcasecmp($rlaction, 'diagnosis')===0){
            RabbitLoader_21_Core::run_diagnosis($response);
        }else if(empty($rlaction) || strcasecmp($rlaction, 'savepage')===0){
            
            $cur_id = RabbitLoader_21_Util_Core::get_param('cur_id', true);
            $response['cur_id'] = $cur_id;

            if(class_exists('ZipArchive')){
                try{
                    $zip = new \ZipArchive();
                    if (!empty($cur_id) && !empty($_FILES["content_zip"]["tmp_name"]) && $zip->open($_FILES["content_zip"]["tmp_name"]) === TRUE) {
                        $dir = sys_get_temp_dir();
                        $zip->extractTo($dir);
                        $zip->close();
                        RabbitLoader_21_Core::get_cache_file_path($_POST['canonical_url'], $cache_file);

                        $saved_count = 0;
                        $tp_purge_count = 0;
                        $html_fn = "$dir/$cur_id.html";
                        if(file_exists($html_fn)){
                            $response['zip_opened'] = true;
                            if(self::hasValidClosingTag($html_fn)){
                                if(RabbitLoader_21_Util_Core::move($html_fn, $cache_file.'_c')){
                                    ++$saved_count;
                                }
                                if(RabbitLoader_21_Util_Core::move("$dir/$cur_id.json", $cache_file.'_h')){
                                    ++$saved_count;
                                }
                            }else{
                                $response['eof_missing'] = true;
                            }
                            if($saved_count>0){
                                RabbitLoader_21_TP::purge_url($_POST['canonical_url'], $tp_purge_count);
                            }

                        }else{
                            $response['zip_extract'] = "$html_fn not found";
                        }

                        $response['tmp_dir'] = $dir;
                        $response['saved_count'] = $saved_count;
                        $response['tp_purge_count'] = $tp_purge_count;
                        $response['cache_file'] = $cache_file;
                        $response['cache_filesize'] = filesize($cache_file.'_c');
                        $response['canonical_url'] = $_POST['canonical_url'];
                    }else{
                        $response['zip_opened'] = false;
                    }
                }catch(\Throwable $e){
                    $response['exception'] = $e->getMessage();
                }
            }else{
                $response['exception'] = 'ZipArchive not found';
            }
        }else{
            $response['exception'] = 'invalid action '.$rlaction;
        }
        http_response_code(200);
        echo json_encode($response);
        exit;
    }

    private static function hasValidClosingTag(string $fn){
        $valid = false;
        $handle = fopen($fn, 'r');
        fseek($handle, -8192, SEEK_END); //grab the last 8000 bytes to be safe
        while (($buffer = fgets($handle)) !== false) {
            if (stripos($buffer, '</html>') !== false || stripos($buffer, '</body>') !== false) {
                $valid = true;
                break;
            }      
        }
        fclose($handle);
        return $valid;
    }

    private static function serve_from_cache_if_available($cache_file){
        if(RabbitLoader_21_Core::cache_exists_for_hash($cache_file, 0)){
            //ignore buffer and serve from cache
            if(file_exists($cache_file.'_h')){
                //header is optional
                RabbitLoader_21_Util_Core::send_headers(file_get_contents($cache_file.'_h'));
            }
            RabbitLoader_21_Core::sendHeader('x-rl-cache: hit', true);
            echo file_get_contents($cache_file.'_c');
            return true;
        }
    }

    public static function adminBarMenu($admin_bar){
        $top_menu = array(
            'id' => 'rabbitloader_top_menu',
            'title' => 'RabbitLoader',
            'href' => admin_url( 'options-general.php?page=rabbitloader' )
        );

        $list_menu = array(
            'parent' => 'rabbitloader_top_menu',
            'id'     => 'rabbitloader_purge_page',
            'title'  =>  'Purge cache for this page',
            'href'   =>  "#",
            'meta' => array(
                'class' => 'rabbitloader_purge_page',
            )
        );

        $admin_bar->add_node($top_menu);
        $admin_bar->add_node($list_menu);
    }

    public static function adminBarScript(){
        global $post;

        wp_enqueue_script('rabbitloader-index', RABBITLOADER_PLUG_URL . 'admin/js/index.js', ['jquery'], RABBITLOADER_PLUG_VERSION);
        wp_localize_script( 'rabbitloader-index', 'rabbitloader_local_vars', [
            'admin_ajax' => admin_url( 'admin-ajax.php' ),
            'post_id' => empty($post) ? 0: $post->ID
        ]);
    }

    public static function wp_redirect($location, $status){
        if(!empty($location)){
            self::$skip_reason = 'redirect-'.$status;
        }
        return $location;
    }

    public static function redirect_canonical($redirect_url, $requested_url){
        if(!empty($redirect_url)){self::$skip_reason = 'redirect-canonical';}
        return $redirect_url;
    }

    public static function pre_handle_404($preempt, $wp_query ){
        if($preempt){self::$skip_reason = '404';}
        return $preempt;
    }

    public static function paginate_links($link){
        if(!empty($link)){
            $link = str_ireplace('rl-no-optimization=1','', $link);
            $link = rtrim($link, '?');
            return $link;
        }
    }

    public static function nonce_life($life){
        $referer = empty($_SERVER["HTTP_REFERER"]) ? '' : $_SERVER["HTTP_REFERER"];
        if(RabbitLoader_21_Util_WP::is_user_logged_in()){
            return $life;
        }elseif(intval($life)>RabbitLoader_21_Core::ORPHANED_LONG_AGE_SEC){
            return $life;
        }else if(self::$skip_reason==self::skip_reason_or || self::$is_origin){
            //this also sets if no_optimization is passed
            return RabbitLoader_21_Core::ORPHANED_LONG_AGE_SEC;
        }else if(RabbitLoader_21_Util_WP::is_ajax() && (!empty($_COOKIE["rlCached"]) || stripos($referer, self::no_optimization)!==false)){
            //for ajax, if cookie is set, the page was cached who called the ajax
            //or the referer page had no_optimization that matched the previous else condition
            return RabbitLoader_21_Core::ORPHANED_LONG_AGE_SEC;
        }else{
            //unhandled scenarios
        }
        return $life;
    }

    public static function wp_footer(){
        if(self::$wp_footer_called){
            return;
        }
        self::$wp_footer_called = true;
        echo "<script data-rlskip='1'>let rlCached = window.rlPageData && window.rlPageData.rlCached;
            document.cookie = 'rlCached=' + (rlCached ? '1' : '0') + '; path=/;';
        </script>";
    }
}

?>
```
