Plugin Directory

Changeset 978150


Ignore:
Timestamp:
09/03/2014 07:42:03 PM (12 years ago)
Author:
yorman
Message:

Added. Heartbeat options and dates in local time

Location:
sucuri-scanner/trunk
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • sucuri-scanner/trunk/inc/css/sucuriscan-default-css.css

    r967131 r978150  
    182182.sucuriscan-monitoring-logs .sucuriscan-monitoring-date-form select + select + select{width:60px}
    183183.sucuriscan-monitoring-logs .sucuriscan-target-date{font-size:12px;color:#999;margin-right:5px}
     184.sucuriscan-monitoring-logs .sucuriscan-denial-type{font-size:14px}
     185.sucuriscan-monitoring-logs .sucuriscan-denial-type-date{font-style:italic;color:#999}
    184186/* Monitoring AccessLog Styles */
    185187.sucuriscan-request-summary{margin:-15px;margin-top:-3px}
    186 .sucuriscan-request-summary ul{margin:0}
    187 .sucuriscan-request-summary label, .sucuriscan-request-summary span{display:inline-block;font-size:14px}
    188 .sucuriscan-request-summary label{width:200px;font-weight:bold}
    189 .sucuriscan-request-summary span{max-width:395px;font-family:monospace;vertical-align:top;word-break:break-all}
     188.sucuriscan-request-summary td{font-size:14px}
     189.sucuriscan-request-summary tr td:first-child{font-weight:bold}
     190.sucuriscan-request-summary td+td{font-family:monospace;word-break:break-all}
    190191/* Hardening Status */
    191192.sucuriscan-hstatus{position:relative;margin:0 -12px;padding:10px 12px;border:1px solid transparent}
     
    220221.sucuriscan-maincontent .sucuriscan-settings{margin-top:0}
    221222.sucuriscan-maincontent .sucuriscan-settings form{display:inline-block}
    222 .sucuriscan-maincontent .sucuriscan-settings select, .sucuriscan-maincontent .sucuriscan-settings .input-text{min-width:220px}
     223.sucuriscan-maincontent .sucuriscan-settings select, .sucuriscan-maincontent .sucuriscan-settings .input-text{width:220px}
    223224.sucuriscan-maincontent .sucuriscan-settings-notifications{margin-top:0}
     225.sucuriscan-maincontent .sucuriscan-settings-heartbeat{}
    224226.sucuriscan-maincontent .sucuriscan-wpcron-list{margin-top:0}
    225227/* Responsive Styles */
  • sucuri-scanner/trunk/inc/tpl/lastlogins-all.html.tpl

    r956731 r978150  
    44        <tr>
    55            <th colspan="6" class="thead-with-button">
    6                 <span>User last logins</span>
    7                 <span class="thead-topright-action sucuriscan-lastlogin-outof">
    8                     %%SUCURI.UserList.Limit%% per page out of %%SUCURI.UserList.Total%%
     6                <span>User last logins (%%SUCURI.UserList.Total%%)</span>
     7                <span class="thead-topright-action">
     8                    <form action="%%SUCURI.URL.Lastlogins%%" method="post">
     9                        <input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
     10                        <button type="submit" name="sucuriscan_reset_lastlogins" class="button button-primary">Reset logs</button>
     11                    </form>
    912                </span>
    1013            </th>
  • sucuri-scanner/trunk/inc/tpl/lastlogins-loggedin.html.tpl

    r956731 r978150  
    88            <th>ID</th>
    99            <th>Username</th>
    10             <th>Last Activity (GMT/UTC)</th>
    11             <th>Registered (GMT/UTC)</th>
     10            <th>Last Activity</th>
     11            <th>Registered</th>
    1212            <th>IP Address</th>
    1313            <th>&nbsp;</th>
  • sucuri-scanner/trunk/inc/tpl/monitoring-logs.html.tpl

    r945045 r978150  
    4646
    4747        <tr>
    48             <th>Denial Type</th>
    49             <th>Time</th>
    50             <th>Remote Address</th>
     48            <th width="250">Denial Type</th>
     49            <th width="120">Remote Address</th>
    5150            <th>Request Path</th>
    5251        </tr>
  • sucuri-scanner/trunk/inc/tpl/monitoring-logs.snippet.tpl

    r939379 r978150  
    11
    22<tr class="%%SUCURI.AuditLog.CssClass%%">
    3     <td>%%SUCURI.AuditLog.SucuriBlockReason%%</td>
    43    <td>
    5         <span class="sucuriscan-monospace" title="%%SUCURI.AuditLog.RequestDate%% %%SUCURI.AuditLog.RequestTime%% %%SUCURI.AuditLog.RequestTimezone%%">
    6             %%SUCURI.AuditLog.RequestTime%% %%SUCURI.AuditLog.RequestTimezone%%
    7         </span>
     4        <span class="sucuriscan-denial-type">%%SUCURI.AuditLog.SucuriBlockReason%%</span><br>
     5        <span class="sucuriscan-denial-type-date">Date/Time: %%SUCURI.AuditLog.LocalRequestTime%%</span>
    86    </td>
    97    <td><span class="sucuriscan-monospace">%%SUCURI.AuditLog.RemoteAddr%%</span></td>
     
    1715        <div id="sucuriscan-reqsummary-%%SUCURI.AuditLog.Id%%" style="display:none">
    1816            <div class="sucuriscan-request-summary">
    19                 <ul class="sucuriscan-list-as-table">
    20                     <li>
    21                         <label>Blocked Reason:</label>
    22                         <span>%%SUCURI.AuditLog.SucuriBlockReason%%</span>
    23                     </li>
    24                     <li>
    25                         <label>Remote Address:</label>
    26                         <span>%%SUCURI.AuditLog.RemoteAddr%%</span>
    27                     </li>
    28                     <li>
    29                         <label>Date/Time (Timezone)</label>
    30                         <span>%%SUCURI.AuditLog.RequestDate%% %%SUCURI.AuditLog.RequestTime%% (%%SUCURI.AuditLog.RequestTimezone%%)</span>
    31                     </li>
    32                     <li>
    33                         <label>Resource Path:</label>
    34                         <span>%%SUCURI.AuditLog.ResourcePath%%</span>
    35                     </li>
    36                     <li>
    37                         <label>Request Method:</label>
    38                         <span>%%SUCURI.AuditLog.RequestMethod%%</span>
    39                     </li>
    40                     <li>
    41                         <label>HTTP Protocol:</label>
    42                         <span>%%SUCURI.AuditLog.HttpProtocol%%</span>
    43                     </li>
    44                     <li>
    45                         <label>HTTP Status:</label>
    46                         <span>%%SUCURI.AuditLog.HttpStatus%% %%SUCURI.AuditLog.HttpStatusTitle%%</span>
    47                     </li>
    48                     <li>
    49                         <label>HTTP Bytes Sent:</label>
    50                         <span>%%SUCURI.AuditLog.HttpBytesSent%%</span>
    51                     </li>
    52                     <li>
    53                         <label>HTTP Referer:</label>
    54                         <span>%%SUCURI.AuditLog.HttpReferer%%</span>
    55                     </li>
    56                     <li>
    57                         <label>HTTP User Agent:</label>
    58                         <span>%%SUCURI.AuditLog.HttpUserAgent%%</span>
    59                     </li>
    60                 </ul>
     17                <table class="wp-list-table widefat">
     18                    <thead>
     19                        <tr>
     20                            <th width="200">Information</th>
     21                            <th>&nbsp;</th>
     22                        </tr>
     23                    </thead>
     24
     25                    <tbody>
     26                        <tr class="alternate">
     27                            <td>Blocked Reason</td>
     28                            <td>%%SUCURI.AuditLog.SucuriBlockReason%%</td>
     29                        </tr>
     30                        <tr>
     31                            <td>Remote Address</td>
     32                            <td>%%SUCURI.AuditLog.RemoteAddr%%</td>
     33                        </tr>
     34                        <tr class="alternate">
     35                            <td>Date &amp; Time (Local Time)</td>
     36                            <td>%%SUCURI.AuditLog.LocalRequestTime%%</td>
     37                        </tr>
     38                        <tr>
     39                            <td>Resource Path</td>
     40                            <td>%%SUCURI.AuditLog.ResourcePath%%</td>
     41                        </tr>
     42                        <tr class="alternate">
     43                            <td>Request Method</td>
     44                            <td>%%SUCURI.AuditLog.RequestMethod%%</td>
     45                        </tr>
     46                        <tr>
     47                            <td>HTTP Protocol</td>
     48                            <td>%%SUCURI.AuditLog.HttpProtocol%%</td>
     49                        </tr>
     50                        <tr class="alternate">
     51                            <td>HTTP Status</td>
     52                            <td>%%SUCURI.AuditLog.HttpStatus%% %%SUCURI.AuditLog.HttpStatusTitle%%</td>
     53                        </tr>
     54                        <tr>
     55                            <td>HTTP Bytes Sent</td>
     56                            <td>%%SUCURI.AuditLog.HttpBytesSent%%</td>
     57                        </tr>
     58                        <tr class="alternate">
     59                            <td>HTTP Referer</td>
     60                            <td>%%SUCURI.AuditLog.HttpReferer%%</td>
     61                        </tr>
     62                        <tr>
     63                            <td>HTTP User Agent</td>
     64                            <td>%%SUCURI.AuditLog.HttpUserAgent%%</td>
     65                        </tr>
     66                    </tbody>
     67                </table>
    6168            </div>
    6269        </div>
  • sucuri-scanner/trunk/inc/tpl/settings-general.html.tpl

    r965266 r978150  
    66        <tr>
    77            <th colspan="3" class="thead-with-button">
    8                 <span>Plugin Settings</span>
     8                <span>General Settings</span>
    99                <form action="%%SUCURI.URL.Settings%%" method="post" class="thead-topright-action">
    1010                    <input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
     
    2626                    monitoring tool forever even if you remove the API key and generate it again.
    2727                </p>
     28
     29                <div class="sucuriscan-inline-alert-warning sucuriscan-%%SUCURI.InvalidDomainVisibility%%">
     30                    <p>
     31                        Your domain <code>%%SUCURI.CleanDomain%%</code> does not seems to have a DNS
     32                        <code>A</code> record so it will be considered as <em>invalid</em> by the API
     33                        interface when you request the generation of a new key. Adding <code>www</code>
     34                        at the beginning of the domain name may fix this issue.
     35                    </p>
     36                </div>
    2837            </td>
    2938        </tr>
     
    108117
    109118        <tr>
     119            <td>API request timeout</td>
     120            <td>%%SUCURI.RequestTimeout%%</td>
     121            <td class="td-with-button">
     122                <form action="%%SUCURI.URL.Settings%%" method="post">
     123                    <input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
     124                    <input type="text" name="sucuriscan_request_timeout" class="input-text" placeholder="Timeout in seconds..." />
     125                    <button type="submit" class="button-primary">Change</button>
     126                </form>
     127            </td>
     128        </tr>
     129
     130        <tr class="alternate">
    110131            <td>Filesystem scanner</td>
    111132            <td>%%SUCURI.FsScannerStatus%%</td>
     
    119140        </tr>
    120141
    121         <tr class="alternate">
     142        <tr>
    122143            <td>Scan modified files</td>
    123144            <td>%%SUCURI.ScanModfilesStatus%%</td>
     
    131152        </tr>
    132153
    133         <tr>
     154        <tr class="alternate">
    134155            <td>Integrity checking</td>
    135156            <td>%%SUCURI.ScanChecksumsStatus%%</td>
     
    143164        </tr>
    144165
    145         <tr class="alternate">
     166        <tr>
    146167            <td>Last Scanning</td>
    147168            <td><span class="sucuriscan-monospace">%%SUCURI.ScanningRuntimeHuman%%</span></td>
     
    154175        </tr>
    155176
    156         <tr>
     177        <tr class="alternate">
    157178            <td>Scanning frequency</td>
    158179            <td>%%SUCURI.ScanningFrequency%%</td>
     
    168189        </tr>
    169190
    170         <tr class="alternate sucuriscan-%%SUCURI.ScanningInterfaceVisibility%%">
     191        <tr class="sucuriscan-%%SUCURI.ScanningInterfaceVisibility%%">
    171192            <td>Scanning interface</td>
    172193            <td>%%SUCURI.ScanningInterface%%</td>
  • sucuri-scanner/trunk/inc/tpl/settings.html.tpl

    r956731 r978150  
    1010        <li>
    1111            <a href="#" data-tabname="settings-ignorerules">Ignore Notifications</a>
     12        </li>
     13        <li>
     14            <a href="#" data-tabname="settings-heartbeat">Heartbeat</a>
    1215        </li>
    1316    </ul>
     
    2528            %%SUCURI.Settings.IgnoreRules%%
    2629        </div>
     30
     31        <div id="sucuriscan-settings-heartbeat">
     32            %%SUCURI.Settings.Heartbeat%%
     33        </div>
    2734    </div>
    2835</div>
  • sucuri-scanner/trunk/sucuri.php

    r968714 r978150  
    320320    add_action( $sucuriscan_admin_notice_name, 'SucuriScanInterface::setup_notice' );
    321321
     322    /**
     323     * Heartbeat API
     324     *
     325     * Update the settings of the Heartbeat API according to the values set by an
     326     * administrator. This tool may cause an increase in the CPU usage, a bad
     327     * configuration may cause low account to run out of resources, but in better
     328     * cases it may improve the performance of the site by reducing the quantity of
     329     * requests sent to the server per session.
     330     */
     331    add_filter( 'init', 'SucuriScanHeartbeat::register_script', 1 );
     332    add_filter( 'heartbeat_settings', 'SucuriScanHeartbeat::update_settings' );
     333    add_filter( 'heartbeat_send', 'SucuriScanHeartbeat::respond_to_send', 10, 3 );
     334    add_filter( 'heartbeat_received', 'SucuriScanHeartbeat::respond_to_received', 10, 3 );
     335    add_filter( 'heartbeat_nopriv_send', 'SucuriScanHeartbeat::respond_to_send', 10, 3 );
     336    add_filter( 'heartbeat_nopriv_received', 'SucuriScanHeartbeat::respond_to_received', 10, 3 );
     337
    322338}
    323339
     
    573589
    574590    /**
     591     * Get the clean version of the current domain.
     592     *
     593     * @return string The domain of the current site.
     594     */
     595    public static function get_domain(){
     596        if( function_exists('get_site_url') ){
     597            $site_url = get_site_url();
     598        } else {
     599            if( !isset($_SERVER['HTTP_HOST']) ){
     600                $_SERVER['HTTP_HOST'] = 'localhost';
     601            }
     602
     603            $site_url = $_SERVER['HTTP_HOST'];
     604        }
     605
     606        $pattern = '/([fhtps]+:\/\/)?([^:]+)(:[0-9:]+)?/';
     607        $domain_name =  preg_replace( $pattern, '$2', $site_url );
     608
     609        return $domain_name;
     610    }
     611
     612    /**
    575613     * Check whether the site is behing the Sucuri CloudProxy network.
    576614     *
     
    579617     */
    580618    public static function is_behind_cloudproxy( $verbose=FALSE ){
    581         if( isset($_SERVER['SERVER_NAME']) ){
    582             $http_host = preg_replace('/^(.*):[0-9]+/', '$1', $_SERVER['SERVER_NAME']);
    583         } else {
    584             $http_host = 'localhost';
    585         }
    586 
     619        $http_host = self::get_domain();
    587620        $host_by_name = @gethostbyname($http_host);
    588621        $host_by_addr = @gethostbyaddr($host_by_name);
     
    599632
    600633        return $status;
     634    }
     635
     636    /**
     637     * Get the email address set by the administrator to receive the notifications
     638     * sent by the plugin, if the email is missing the WordPress email address is
     639     * chosen by default.
     640     *
     641     * @return string The administrator email address.
     642     */
     643    public static function get_site_email(){
     644        $email = get_option('admin_email');
     645
     646        if( self::is_valid_email($email) ){
     647            return $email;
     648        }
     649
     650        return FALSE;
     651    }
     652
     653    /**
     654     * Retrieve the date in localized format, based on timestamp.
     655     *
     656     * If the locale specifies the locale month and weekday, then the locale will
     657     * take over the format for the date. If it isn't, then the date format string
     658     * will be used instead.
     659     *
     660     * @param  integer $timestamp Unix timestamp.
     661     * @return string             The date, translated if locale specifies it.
     662     */
     663    public static function datetime( $timestamp=0 ){
     664        if( is_numeric($timestamp) && $timestamp > 0 ){
     665            $date_format = get_option('date_format');
     666            $time_format = get_option('time_format');
     667            $timezone_format = sprintf( '%s %s', $date_format, $time_format );
     668
     669            return date_i18n( $timezone_format, $timestamp );
     670        }
     671
     672        return NULL;
    601673    }
    602674
     
    717789
    718790        return $text;
     791    }
     792
     793    /**
     794     * Check whether an list is a multidimensional array or not.
     795     *
     796     * @param  array   $list An array or multidimensional array of different values.
     797     * @return boolean       TRUE if the list is multidimensional, FALSE otherwise.
     798     */
     799    public static function is_multi_list( $list=array() ){
     800        if( !empty($list) ){
     801            foreach( $list as $item ){
     802                if( is_array($item) ){
     803                    return TRUE;
     804                }
     805            }
     806        }
     807
     808        return FALSE;
     809    }
     810
     811    /**
     812     * Join array elements with a string no matter if it is multidimensional.
     813     *
     814     * @param  string $separator Character that will act as a separator, default to an empty string.
     815     * @param  array  $list      The array of strings to implode.
     816     * @return string            String of all the items in the list, with the separator between them.
     817     */
     818    public static function implode( $separator='', $list=array() ){
     819        if( self::is_multi_list($list) ){
     820            $pieces = array();
     821
     822            foreach( $list as $items ){
     823                $pieces[] = @implode( $separator, $items );
     824            }
     825
     826            $joined_pieces = '(' . implode( '), (', $pieces ) . ')';
     827
     828            return $joined_pieces;
     829        } else {
     830            return implode( $separator, $list );
     831        }
    719832    }
    720833
     
    16781791
    16791792    /**
     1793     * Default values for the plugin options.
     1794     *
     1795     * @return array Default plugin option values.
     1796     */
     1797    private static function get_default_option_values(){
     1798        $defaults = array(
     1799            'sucuriscan_api_key' => FALSE,
     1800            'sucuriscan_account' => '',
     1801            'sucuriscan_fs_scanner' => 'enabled',
     1802            'sucuriscan_scan_frequency' => 'hourly',
     1803            'sucuriscan_scan_interface' => 'spl',
     1804            'sucuriscan_scan_modfiles' => 'enabled',
     1805            'sucuriscan_scan_checksums' => 'enabled',
     1806            'sucuriscan_runtime' => 0,
     1807            'sucuriscan_lastlogin_redirection' => 'enabled',
     1808            'sucuriscan_notify_to' => '',
     1809            'sucuriscan_emails_sent' => 0,
     1810            'sucuriscan_emails_per_hour' => 5,
     1811            'sucuriscan_last_email_at' => time(),
     1812            'sucuriscan_prettify_mails' => 'enabled',
     1813            'sucuriscan_notify_success_login' => 'enabled',
     1814            'sucuriscan_notify_failed_login' => 'enabled',
     1815            'sucuriscan_notify_post_publication' => 'enabled',
     1816            'sucuriscan_notify_theme_editor' => 'enabled',
     1817            'sucuriscan_maximum_failed_logins' => 30,
     1818            'sucuriscan_ignored_events' => '',
     1819            'sucuriscan_verify_ssl_cert' => 'true',
     1820            'sucuriscan_request_timeout' => 90,
     1821            'sucuriscan_heartbeat' => 'enabled',
     1822            'sucuriscan_heartbeat_pulse' => 15,
     1823            'sucuriscan_heartbeat_interval' => 'standard',
     1824            'sucuriscan_heartbeat_autostart' => 'enabled',
     1825        );
     1826
     1827        return $defaults;
     1828    }
     1829
     1830    /**
     1831     * Retrieve the default values for some specific options.
     1832     *
     1833     * @param  string|array $settings Either an array that will be complemented or a string with the name of the option.
     1834     * @return string|array           The default values for the specified options.
     1835     */
     1836    private static function get_default_options( $settings='' ){
     1837        $default_options = self::get_default_option_values();
     1838
     1839        // Use framework built-in function.
     1840        if( function_exists('get_option') ){
     1841            $admin_email = get_option('admin_email');
     1842            $default_options['sucuriscan_account'] = $admin_email;
     1843            $default_options['sucuriscan_notify_to'] = $admin_email;
     1844        }
     1845
     1846        if( is_array($settings) ){
     1847            foreach( $default_options as $option_name => $option_value ){
     1848                if( !isset($settings[$option_name]) ){
     1849                    $settings[$option_name] = $option_value;
     1850                }
     1851            }
     1852
     1853            return $settings;
     1854        }
     1855
     1856        if( is_string($settings) ){
     1857            if( isset($default_options[$settings]) ){
     1858                return $default_options[$settings];
     1859            }
     1860        }
     1861
     1862        return FALSE;
     1863    }
     1864
     1865    /**
    16801866     * Retrieve specific options from the database.
    16811867     *
     
    18302016
    18312017        return $option_value;
    1832     }
    1833 
    1834     /**
    1835      * Retrieve the default values for some specific options.
    1836      *
    1837      * @param  string|array $settings Either an array that will be complemented or a string with the name of the option.
    1838      * @return string|array           The default values for the specified options.
    1839      */
    1840     private static function get_default_options( $settings='' ){
    1841         $admin_email = '';
    1842 
    1843         // Use framework built-in function.
    1844         if( function_exists('get_option') ){
    1845             $admin_email = get_option('admin_email');
    1846         }
    1847 
    1848         $default_options = array(
    1849             'sucuriscan_api_key' => FALSE,
    1850             'sucuriscan_account' => $admin_email,
    1851             'sucuriscan_fs_scanner' => 'enabled',
    1852             'sucuriscan_scan_frequency' => 'hourly',
    1853             'sucuriscan_scan_interface' => 'spl',
    1854             'sucuriscan_scan_modfiles' => 'enabled',
    1855             'sucuriscan_scan_checksums' => 'enabled',
    1856             'sucuriscan_runtime' => 0,
    1857             'sucuriscan_lastlogin_redirection' => 'enabled',
    1858             'sucuriscan_notify_to' => $admin_email,
    1859             'sucuriscan_emails_sent' => 0,
    1860             'sucuriscan_emails_per_hour' => 5,
    1861             'sucuriscan_last_email_at' => time(),
    1862             'sucuriscan_prettify_mails' => 'enabled',
    1863             'sucuriscan_notify_success_login' => 'enabled',
    1864             'sucuriscan_notify_failed_login' => 'enabled',
    1865             'sucuriscan_notify_post_publication' => 'enabled',
    1866             'sucuriscan_notify_theme_editor' => 'enabled',
    1867             'sucuriscan_maximum_failed_logins' => 30,
    1868             'sucuriscan_ignored_events' => '',
    1869             'sucuriscan_verify_ssl_cert' => 'true',
    1870         );
    1871 
    1872         if( is_array($settings) ){
    1873             foreach( $default_options as $option_name => $option_value ){
    1874                 if( !isset($settings[$option_name]) ){
    1875                     $settings[$option_name] = $option_value;
    1876                 }
    1877             }
    1878 
    1879             return $settings;
    1880         }
    1881 
    1882         if( is_string($settings) ){
    1883             if( isset($default_options[$settings]) ){
    1884                 return $default_options[$settings];
    1885             }
    1886         }
    1887 
    1888         return FALSE;
    18892018    }
    18902019
     
    19792108
    19802109        return FALSE;
    1981     }
    1982 
    1983     /**
    1984      * Get the email address set by the administrator to receive the notifications
    1985      * sent by the plugin, if the email is missing the WordPress email address is
    1986      * chosen by default.
    1987      *
    1988      * @return string The administrator email address.
    1989      */
    1990     public static function get_site_email(){
    1991         $email = self::get_option('admin_email');
    1992 
    1993         if( self::is_valid_email($email) ){
    1994             return $email;
    1995         }
    1996 
    1997         return FALSE;
    1998     }
    1999 
    2000     /**
    2001      * Get the clean version of the current domain.
    2002      *
    2003      * @return string The domain of the current site.
    2004      */
    2005     public static function get_domain(){
    2006         $http_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
    2007         $domain_name =  preg_replace( '/^www\./', '', $http_host );
    2008 
    2009         return $domain_name;
    20102110    }
    20112111
     
    21412241        if( $runtime > 0 ){
    21422242            if( $format ){
    2143                 return date( 'd/M/Y H:i:s', $runtime );
     2243                return SucuriScan::datetime($runtime);
    21442244            }
    21452245
     
    23702470            }
    23712471
    2372             $title = sprintf( 'Sucuri notification (%s)', str_replace('_', chr(32), $event) );
     2472            $title = str_replace('_', chr(32), $event);
    23732473            $mail_sent = SucuriScanMail::send_mail( $email, $title, $content, $email_params );
    23742474
     
    31143214
    31153215    /**
     3216     * Seconds before consider a HTTP request as timeout.
     3217     *
     3218     * @return integer Seconds to consider a HTTP request timeout.
     3219     */
     3220    public static function request_timeout(){
     3221        return intval( self::get_option(':request_timeout') );
     3222    }
     3223
     3224    /**
    31163225     * Generate an user-agent for the HTTP requests.
    31173226     *
     
    31463255        $req_args = array(
    31473256            'method' => $method,
    3148             'timeout' => 90,
     3257            'timeout' => self::request_timeout(),
    31493258            'redirection' => 2,
    31503259            'httpversion' => '1.0',
     
    32193328    public static function set_plugin_key( $api_key='', $validate=FALSE ){
    32203329        if( $validate ){
    3221             if( !preg_match('/^([a-z0-9]{32})$/', $api_key) ){
     3330            if( !preg_match('/^[a-z0-9]{32}$/', $api_key) ){
    32223331                SucuriScanInterface::error( 'Invalid API key format' );
    32233332                return FALSE;
     
    36023711        );
    36033712
    3604         if( preg_match('/^([0-9]{4})\-([0-9]{2})\-([0-9]{2})$/', $date) ){
     3713        if( preg_match('/^[0-9]{4}(\-[0-9]{2}){2}$/', $date) ){
    36053714            $params['date'] = $date;
    36063715        }
     
    38964005        $headers = array();
    38974006        $subject = ucwords(strtolower($subject));
    3898         $wp_domain = SucuriScanOption::get_domain();
     4007        $wp_domain = self::get_domain();
    38994008        $force = FALSE;
    39004009        $debug = FALSE;
     
    39314040            if( $debug ){ die($message); }
    39324041
     4042            $subject = sprintf( 'Sucuri Alert, %s, %s', $wp_domain, $subject );
     4043
    39334044            $email_sent = wp_mail(
    39344045                $email,
    3935                 "Sucuri WP Notification: {$wp_domain} - {$subject}",
     4046                $subject,
    39364047                $message,
    39374048                $headers
     
    40744185        $params['PageNonce'] = wp_create_nonce('sucuriscan_page_nonce');
    40754186        $params['PageStyleClass'] = isset($params['PageStyleClass']) ? $params['PageStyleClass'] : 'base';
    4076         $params['CleanDomain'] = SucuriScanOption::get_domain();
    4077         $params['AdminEmail'] = SucuriScanOption::get_site_email();
     4187        $params['CleanDomain'] = self::get_domain();
     4188        $params['AdminEmail'] = self::get_site_email();
    40784189
    40794190        return $params;
     
    43624473
    43634474        return $html_links;
     4475    }
     4476
     4477}
     4478
     4479/**
     4480 * Heartbeat library.
     4481 *
     4482 * The purpose of the Heartbeat API is to simulate bidirectional connection
     4483 * between the browser and the server. Initially it was used for autosave, post
     4484 * locking and log-in expiration warning while a user is writing or editing. The
     4485 * idea was to have an API that sends XHR (XML HTTP Request) requests to the
     4486 * server every fifteen seconds and triggers events (or callbacks) on receiving
     4487 * data.
     4488 *
     4489 * @see https://core.trac.wordpress.org/ticket/23216
     4490 */
     4491class SucuriScanHeartbeat extends SucuriScanOption {
     4492
     4493    /**
     4494     * Stop execution of the heartbeat API in certain parts of the site.
     4495     *
     4496     * @return void
     4497     */
     4498    public static function register_script(){
     4499        global $pagenow;
     4500
     4501        $status = SucuriScanOption::get_option(':heartbeat');
     4502
     4503        // Enable heartbeat everywhere.
     4504        if( $status == 'enabled' ){ /* do_nothing */ }
     4505
     4506        // Disable heartbeat everywhere.
     4507        elseif( $status == 'disabled' ){
     4508            wp_deregister_script('heartbeat');
     4509        }
     4510
     4511        // Disable heartbeat only on the dashboard and home pages.
     4512        elseif(
     4513            $status == 'dashboard'
     4514            && $pagenow == 'index.php'
     4515        ){
     4516            wp_deregister_script('heartbeat');
     4517        }
     4518
     4519        // Disable heartbeat everywhere except in post edition.
     4520        elseif(
     4521            $status == 'addpost'
     4522            && $pagenow != 'post.php'
     4523            && $pagenow != 'post-new.php'
     4524        ){
     4525            wp_deregister_script('heartbeat');
     4526        }
     4527    }
     4528
     4529    /**
     4530     * Update the settings of the Heartbeat API according to the values set by an
     4531     * administrator. This tool may cause an increase in the CPU usage, a bad
     4532     * configuration may cause low account to run out of resources, but in better
     4533     * cases it may improve the performance of the site by reducing the quantity of
     4534     * requests sent to the server per session.
     4535     *
     4536     * @param  array $settings Heartbeat settings.
     4537     * @return array           Updated version of the heartbeat settings.
     4538     */
     4539    public static function update_settings( $settings=array() ){
     4540        $pulse = SucuriScanOption::get_option(':heartbeat_pulse');
     4541        $autostart = SucuriScanOption::get_option(':heartbeat_autostart');
     4542
     4543        if( $pulse < 15 || $pulse > 60 ){
     4544            SucuriScanOption::delete_option(':heartbeat_pulse');
     4545            $pulse = 15;
     4546        }
     4547
     4548        $settings['interval'] = $pulse;
     4549        $settings['autostart'] = ( $autostart == 'disabled' ? FALSE : TRUE );
     4550
     4551        return $settings;
     4552    }
     4553
     4554    /**
     4555     * Respond to the browser according to the data received.
     4556     *
     4557     * @param  array  $response  Response received.
     4558     * @param  array  $data      Data received from the beat.
     4559     * @param  string $screen_id Identifier of the screen the heartbeat occurred on.
     4560     * @return array             Response with new data.
     4561     */
     4562    public static function respond_to_received( $response=array(), $data=array(), $screen_id='' ) {
     4563        $interval = SucuriScanOption::get_option(':heartbeat_interval');
     4564
     4565        if(
     4566            $interval == 'slow'
     4567            || $interval == 'fast'
     4568            || $interval == 'standard'
     4569        ){
     4570            $response['heartbeat_interval'] = $interval;
     4571        } else {
     4572            SucuriScanOption::delete_option(':heartbeat_interval');
     4573        }
     4574
     4575        return $response;
     4576    }
     4577
     4578    /**
     4579     * Respond to the browser according to the data sent.
     4580     *
     4581     * @param  array  $response  Response sent.
     4582     * @param  string $screen_id Identifier of the screen the heartbeat occurred on.
     4583     * @return array             Response with new data.
     4584     */
     4585    public static function respond_to_send( $response=array(), $screen_id='' ) {
     4586        return $response;
     4587    }
     4588
     4589    /**
     4590     * Allowed values for the heartbeat status.
     4591     *
     4592     * @return array Allowed values for the heartbeat status.
     4593     */
     4594    public static function statuses_allowed(){
     4595        return array(
     4596            'enabled' => 'Enable everywhere',
     4597            'disabled' => 'Disable everywhere',
     4598            'dashboard' => 'Disable on dashboard page',
     4599            'addpost' => 'Everywhere except post addition',
     4600        );
     4601    }
     4602
     4603    /**
     4604     * Allowed values for the heartbeat intervals.
     4605     *
     4606     * @return array Allowed values for the heartbeat intervals.
     4607     */
     4608    public static function intervals_allowed(){
     4609        return array(
     4610            'slow' => 'Slow interval',
     4611            'fast' => 'Fast interval',
     4612            'standard' => 'Standard interval',
     4613        );
     4614    }
     4615
     4616    /**
     4617     * Allowed values for the heartbeat pulses.
     4618     *
     4619     * @return array Allowed values for the heartbeat pulses.
     4620     */
     4621    public static function pulses_allowed(){
     4622        $pulses = array();
     4623
     4624        for( $i=15; $i<=60; $i++ ){
     4625            $pulses[$i] = sprintf( 'Run every %d seconds', $i );
     4626        }
     4627
     4628        return $pulses;
    43644629    }
    43654630
     
    46654930    // Will be TRUE only if the scanning results were retrieved from the cache.
    46664931    $display_results = (bool) $res;
    4667     $clean_domain = SucuriScanOption::get_domain();
     4932    $clean_domain = SucuriScan::get_domain();
    46684933
    46694934    // If the results are not cached, then request a new scanning.
     
    51415406            if( $clear_cache_resp ){
    51425407                if( isset($clear_cache_resp->messages[0]) ){
     5408                    // Clear W3 Total Cache if it is installed.
     5409                    if( function_exists('w3tc_flush_all') ){ w3tc_flush_all(); }
     5410
    51435411                    SucuriScanInterface::info($clear_cache_resp->messages[0]);
    51445412                } else {
     
    53155583    }
    53165584
    5317     $template_variables['AuditLogs.TargetDate'] = htmlentities($date);
     5585    $template_variables['AuditLogs.TargetDate'] = SucuriScan::escape($date);
    53185586    $template_variables['AuditLogs.DateYears'] = sucuriscan_monitoring_dates('years', $date);
    53195587    $template_variables['AuditLogs.DateMonths'] = sucuriscan_monitoring_dates('months', $date);
     
    53385606            'request_time',
    53395607            'request_timezone',
     5608            'request_timestamp',
     5609            'local_request_time',
    53405610            'remote_addr',
    53415611            'sucuri_block_reason',
     
    53995669                if( isset($access_log->{$attr_name}) ){
    54005670                    $attr_value = $access_log->{$attr_name};
     5671
     5672                    if(
     5673                        empty($attr_value)
     5674                        && $attr_name == 'sucuri_block_reason'
     5675                    ){
     5676                        $attr_value = 'Unknown';
     5677                    }
    54015678                }
    54025679
    5403                 $audit_log_snippet[$attr_title] = $attr_value;
     5680                elseif( $attr_name == 'local_request_time' ){
     5681                    $attr_value = SucuriScan::datetime($access_log->request_timestamp);
     5682                }
     5683
     5684                $audit_log_snippet[$attr_title] = SucuriScan::escape($attr_value);
    54045685            }
    54055686
     
    54285709            if( !array_key_exists($access_log->sucuri_block_reason, $types) ){
    54295710                $denial_type_k = SucuriScan::human2var($access_log->sucuri_block_reason);
    5430                 $types[$denial_type_k] = $access_log->sucuri_block_reason;
     5711                $denial_type_v = $access_log->sucuri_block_reason;
     5712                if( empty($denial_type_v) ){ $denial_type_v = 'Unknown'; }
     5713                $types[$denial_type_k] = $denial_type_v;
    54315714            }
    54325715        }
     
    57356018                }
    57366019
    5737                 SucuriScanInterface::info('Hardening reverted for upload directory <code>/wp-content/uploads/</code>');
     6020                SucuriScanInterface::info('Hardening reverted for upload directory.');
    57386021            } else {
    57396022                SucuriScanInterface::error(
     
    57696052    $cp = 1;
    57706053    $upmsg = NULL;
    5771     $htaccess_upload = ABSPATH . '/wp-content/.htaccess';
     6054    $htaccess_upload = WP_CONTENT_DIR . '/.htaccess';
    57726055
    57736056    if( !is_readable($htaccess_upload) ){
     
    57906073                $upmsg = SucuriScanInterface::error('Unable to create <code>.htaccess</code> file, folder destination is not writable.');
    57916074            } else {
    5792                 $upmsg = SucuriScanInterface::info('Hardening applied successfully to content directory <code>/wp-content/</code>');
     6075                $upmsg = SucuriScanInterface::info('Hardening applied successfully to content directory.');
    57936076                $cp = 1;
    57946077            }
     
    58076090                }
    58086091
    5809                 SucuriScanInterface::info('Hardening reverted for content directory <code>/wp-content/</code>');
     6092                SucuriScanInterface::info('Hardening reverted for content directory.');
    58106093            } else {
    58116094                SucuriScanInterface::info(
    5812                     'File <code>/wp-content/.htaccess</code> does not exists or is not writable,
    5813                     you will need to remove the following code manually from there:
     6095                    'File <code>' . WP_CONTENT_DIR . '/.htaccess</code> does not exists or is not
     6096                    writable, you will need to remove the following code manually from there:
    58146097                    <code>&lt;Files *.php&gt;deny from all&lt;/Files&gt;</code>'
    58156098                );
     
    58206103    $description = 'This option blocks direct PHP access to any file inside wp-content. If you experience '
    58216104        . 'any issue after this with a theme or plugin in your site, like for example images not displaying, '
    5822         . 'remove the <code>.htaccess</code> file located at the <code>/wp-content/</code> directory.'
     6105        . 'remove the <code>.htaccess</code> file located in the content directory.'
    58236106        . '</p><p><b>Note:</b> Many <em>(insecure)</em> themes and plugins use a PHP file in this directory '
    58246107        . 'to generate images like thumbnails and captcha codes, this is intentional so it is recommended '
     
    58706153                $upmsg = SucuriScanInterface::error('Unable to create <code>.htaccess</code> file, folder destination is not writable.');
    58716154            } else {
    5872                 $upmsg = SucuriScanInterface::info('Hardening applied successfully to library\'s directory <code>/wp-includes/</code>');
     6155                $upmsg = SucuriScanInterface::info('Hardening applied successfully to library\'s directory.');
    58736156                $cp = 1;
    58746157            }
     
    58886171                    @file_put_contents($htaccess_upload, $htaccess_content, LOCK_EX);
    58896172                }
    5890                 SucuriScanInterface::info('Hardening reverted for library\'s directory <code>/wp-includes/</code>');
     6173                SucuriScanInterface::info('Hardening reverted for library\'s directory.');
    58916174            } else {
    58926175                SucuriScanInterface::error(
     
    63386621                $snippet_data = array(
    63396622                    'AuditLog.CssClass' => $css_class,
    6340                     'AuditLog.DateTime' => date( 'd/M/Y H:i:s', $audit_log['timestamp'] ),
    6341                     'AuditLog.Account' => $audit_log['account'],
    6342                     'AuditLog.Message' => $audit_log['message'],
     6623                    'AuditLog.DateTime' => SucuriScan::datetime($audit_log['timestamp']),
     6624                    'AuditLog.Account' => SucuriScan::escape($audit_log['account']),
     6625                    'AuditLog.Message' => SucuriScan::escape($audit_log['message']),
    63436626                    'AuditLog.Extra' => '',
    63446627                );
     
    63496632                    $snippet_data['AuditLog.Extra'] .= '<ul class="sucuriscan-list-as-table ' . $css_scrollable . '">';
    63506633                    foreach( $audit_log['extra'] as $log_extra ){
    6351                         $snippet_data['AuditLog.Extra'] .= '<li>' . $log_extra . '</li>';
     6634                        $snippet_data['AuditLog.Extra'] .= '<li>' . SucuriScan::escape($log_extra) . '</li>';
    63526635                    }
    63536636                    $snippet_data['AuditLog.Extra'] .= '</ul>';
     
    66596942                        'ModifiedFiles.CheckSum' => $file_info['checksum'],
    66606943                        'ModifiedFiles.FilePath' => $file_path,
    6661                         'ModifiedFiles.DateTime' => $mod_date
     6944                        'ModifiedFiles.DateTime' => SucuriScan::datetime($mod_date),
    66626945                    ));
    66636946                    $counter += 1;
     
    68207103        foreach( $user_list as $user ){
    68217104            $user->user_registered_timestamp = strtotime($user->user_registered);
    6822             $user->user_registered_formatted = date('D, M/Y H:i', $user->user_registered_timestamp);
     7105            $user->user_registered_formatted = SucuriScan::datetime($user->user_registered_timestamp);
    68237106            $css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
    68247107
     
    69797262    SucuriScanInterface::check_permissions();
    69807263
     7264    // Reset the file with the last-logins logs.
     7265    if(
     7266        SucuriScanInterface::check_nonce()
     7267        && SucuriScanRequest::post(':reset_lastlogins') !== FALSE
     7268    ){
     7269        $file_path = sucuriscan_lastlogins_datastore_filepath();
     7270
     7271        if( unlink($file_path) ){
     7272            sucuriscan_lastlogins_datastore_exists();
     7273            SucuriScanInterface::info( 'Last-Logins logs were reset successfully.' );
     7274        } else {
     7275            SucuriScanInterface::error( 'Could not reset the last-logins logs.' );
     7276        }
     7277    }
     7278
    69817279    // Page pseudo-variables initialization.
    69827280    $template_variables = array(
     
    70247322            $user_snippet['AdminUsers.NoLastLogins'] = 'hidden';
    70257323            $user_snippet['AdminUsers.NoLastLoginsTable'] = 'visible';
    7026             $user_snippet['AdminUsers.RegisteredAt'] = $admin->user_registered;
     7324            $user_snippet['AdminUsers.RegisteredAt'] = 'Unknown';
    70277325            $counter = 0;
    70287326
    7029             foreach( $admin->lastlogins as $lastlogin ){
     7327            foreach( $admin->lastlogins as $i => $lastlogin ){
     7328                if( $i == 0 ){
     7329                    $user_snippet['AdminUsers.RegisteredAt'] = SucuriScan::datetime($lastlogin->user_registered_timestamp);
     7330                }
     7331
    70307332                $css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
    70317333                $user_snippet['AdminUsers.LastLogins'] .= SucuriScanTemplate::get_snippet('lastlogins-admins-lastlogin', array(
    70327334                    'AdminUsers.RemoteAddr' => SucuriScan::escape($lastlogin->user_remoteaddr),
    7033                     'AdminUsers.Datetime' => SucuriScan::escape($lastlogin->user_lastlogin),
     7335                    'AdminUsers.Datetime' => SucuriScan::datetime($lastlogin->user_lastlogin_timestamp),
    70347336                    'AdminUsers.CssClass' => $css_class,
    70357337                ));
     
    72647566                if( preg_match('/^a:[0-9]+:.+/', $line) ){
    72657567                    $last_login = @unserialize($line);
     7568                    $last_login['user_lastlogin_timestamp'] = strtotime($last_login['user_lastlogin']);
     7569                    $last_login['user_registered_timestamp'] = 0;
    72667570
    72677571                    // Only administrators can see all login stats.
     
    72847588                        foreach( $user_account->data as $var_name=>$var_value ){
    72857589                            $last_login[$var_name] = $var_value;
     7590
     7591                            if( $var_name == 'user_registered' ){
     7592                                $last_login['user_registered_timestamp'] = strtotime($var_value);
     7593                            }
    72867594                        }
    72877595                    }
     
    72907598                    $last_logins['entries'][] = (object) $last_login;
    72917599                    $parsed_lines += 1;
     7600                }
     7601
     7602                else {
     7603                    $last_logins['total'] -= 1;
    72927604                }
    72937605
     
    73467658                $row = $last_logins['entries'][1];
    73477659
    7348                 $message_tpl = 'Last time you logged in was at <code>%s</code> from <code>%s</code> - <code>%s</code>';
    7349                 $lastlogin_message = sprintf( $message_tpl, date('d/M/Y H:i'), $row->user_remoteaddr, $row->user_hostname );
     7660                $lastlogin_message = sprintf(
     7661                    'Last time you logged in was at <code>%s</code> from <code>%s</code> - <code>%s</code>',
     7662                    date('d/M/Y H:i'), $row->user_remoteaddr, $row->user_hostname
     7663                );
    73507664                $lastlogin_message .= chr(32).'(<a href="'.SucuriScanTemplate::get_url('lastlogins').'">view all logs</a>)';
    73517665                SucuriScanInterface::info( $lastlogin_message );
     
    73777691        foreach( (array) $logged_in_users as $logged_in_user ){
    73787692            $counter += 1;
    7379             $logged_in_user['last_activity_datetime'] = date('d/M/Y H:i', $logged_in_user['last_activity']);
    7380             $logged_in_user['user_registered_datetime'] = date('d/M/Y H:i', strtotime($logged_in_user['user_registered']));
     7693            $logged_in_user['last_activity_datetime'] = SucuriScan::datetime($logged_in_user['last_activity']);
     7694            $logged_in_user['user_registered_datetime'] = SucuriScan::datetime( strtotime($logged_in_user['user_registered']) );
    73817695
    73827696            $template_variables['LoggedInUsers.List'] .= SucuriScanTemplate::get_snippet('lastlogins-loggedin', array(
     
    75857899                'FailedLogins.Username' => SucuriScan::escape($login_data['user_login']),
    75867900                'FailedLogins.RemoteAddr' => SucuriScan::escape($login_data['remote_addr']),
    7587                 'FailedLogins.Datetime' => date('d/M/Y H:i', $login_data['attempt_time']),
     7901                'FailedLogins.Datetime' => SucuriScan::datetime($login_data['attempt_time']),
    75887902                'FailedLogins.UserAgent' => SucuriScan::escape($login_data['user_agent']),
    75897903            ));
     
    78218135        'Settings.Notifications' => sucuriscan_settings_notifications(),
    78228136        'Settings.IgnoreRules' => sucuriscan_settings_ignore_rules(),
     8137        'Settings.Heartbeat' => sucuriscan_settings_heartbeat(),
    78238138    );
    78248139
     
    79718286        }
    79728287
     8288        // Update the API request timeout.
     8289        if( $request_timeout = SucuriScanRequest::post(':request_timeout', '[0-9]+') ){
     8290            SucuriScanOption::update_option(':request_timeout', $request_timeout);
     8291            SucuriScanInterface::info( 'API request timeout set to <code>' . $request_timeout . '</code> seconds.' );
     8292        }
     8293
    79738294        // Update the notification settings.
    79748295        if( SucuriScanRequest::post(':save_notification_settings') !== FALSE ){
     
    80298350        }
    80308351
     8352        // Update the settings for the heartbeat API.
     8353        if( $heartbeat_status = SucuriScanRequest::post(':heartbeat_status') ){
     8354            $statuses_allowed = SucuriScanHeartbeat::statuses_allowed();
     8355
     8356            if( array_key_exists($heartbeat_status, $statuses_allowed) ){
     8357                SucuriScanOption::update_option(':heartbeat', $heartbeat_status);
     8358                SucuriScanInterface::info( 'Heartbeat status set to <code>' . $heartbeat_status . '</code>' );
     8359            } else {
     8360                SucuriScanInterface::error( 'Heartbeat status not allowed.' );
     8361            }
     8362        }
     8363
     8364        // Update the value of the heartbeat pulse.
     8365        if( $heartbeat_pulse = SucuriScanRequest::post(':heartbeat_pulse') ){
     8366            $pulses_allowed = SucuriScanHeartbeat::pulses_allowed();
     8367
     8368            if( array_key_exists($heartbeat_pulse, $pulses_allowed) ){
     8369                SucuriScanOption::update_option(':heartbeat_pulse', $heartbeat_pulse);
     8370                SucuriScanInterface::info( 'Heartbeat pulse set to <code>' . $heartbeat_pulse . '</code> seconds.' );
     8371            } else {
     8372                SucuriScanInterface::error( 'Heartbeat pulse not allowed.' );
     8373            }
     8374        }
     8375
     8376        // Update the value of the heartbeat interval.
     8377        if( $heartbeat_interval = SucuriScanRequest::post(':heartbeat_interval') ){
     8378            $intervals_allowed = SucuriScanHeartbeat::intervals_allowed();
     8379
     8380            if( array_key_exists($heartbeat_interval, $intervals_allowed) ){
     8381                SucuriScanOption::update_option(':heartbeat_interval', $heartbeat_interval);
     8382                SucuriScanInterface::info( 'Heartbeat interval set to <code>' . $heartbeat_interval . '</code>' );
     8383            } else {
     8384                SucuriScanInterface::error( 'Heartbeat interval not allowed.' );
     8385            }
     8386        }
     8387
     8388        // Enable or disable the auto-start execution of heartbeat.
     8389        if( $heartbeat_autostart = SucuriScanRequest::post(':heartbeat_autostart', '(en|dis)able') ){
     8390            $action_d = $heartbeat_autostart . 'd';
     8391            SucuriScanOption::update_option(':heartbeat_autostart', $action_d);
     8392            SucuriScanInterface::info( 'Heartbeat auto-start was <code>' . $action_d . '</code>' );
     8393        }
    80318394    }
    80328395}
     
    80828445    $runtime_scan_human = SucuriScanOption::get_filesystem_runtime(TRUE);
    80838446
     8447    // Check whether the domain name is valid or not.
     8448    if( !$api_key ){
     8449        $clean_domain = SucuriScan::get_domain();
     8450        $domain_address = @gethostbyname($clean_domain);
     8451        $invalid_domain = ( $domain_address == $clean_domain ) ? TRUE : FALSE;
     8452    }
     8453
    80848454    // Generate the HTML code for the option list in the form select fields.
    80858455    $scan_freq_options = SucuriScanTemplate::get_select_options( $sucuriscan_schedule_allowed, $scan_freq );
     
    80948464        'APIKey.ManualKeyFormVisibility' => SucuriScanTemplate::visibility($display_manual_key_form),
    80958465        'APIKey.RemoveVisibility' => SucuriScanTemplate::visibility($api_key),
     8466        'InvalidDomainVisibility' => SucuriScanTemplate::visibility($invalid_domain),
    80968467        /* Filesystem scanner */
    80978468        'FsScannerStatus' => 'Enabled',
     
    81258496        'VerifySSLCert' => 'Undefined',
    81268497        'VerifySSLCertOptions' => $verify_ssl_cert_options,
     8498        'RequestTimeout' => SucuriScanOption::get_option(':request_timeout') . ' seconds',
    81278499        'ModalWhenAPIRegistered' => $api_registered_modal,
    81288500    );
     
    82288600            if( array_key_exists($post_type, $ignored_events) ){
    82298601                $is_ignored_text = 'YES';
    8230                 $was_ignored_at = @date('d/M/Y - H:i:s', $ignored_events[$post_type]);
     8602                $was_ignored_at = SucuriScan::datetime($ignored_events[$post_type]);
    82318603                $is_ignored_class = 'danger';
    82328604                $button_action = 'remove';
     
    82588630
    82598631    return SucuriScanTemplate::get_section('settings-ignorerules', $template_variables);
     8632}
     8633
     8634/**
     8635 * Read and parse the content of the heartbeat settings template.
     8636 *
     8637 * @return string Parsed HTML code for the ignored-rules settings panel.
     8638 */
     8639function sucuriscan_settings_heartbeat(){
     8640    // Current values set in the options table.
     8641    $heartbeat_status = SucuriScanOption::get_option(':heartbeat');
     8642    $heartbeat_pulse = SucuriScanOption::get_option(':heartbeat_pulse');
     8643    $heartbeat_interval = SucuriScanOption::get_option(':heartbeat_interval');
     8644    $heartbeat_autostart = SucuriScanOption::get_option(':heartbeat_autostart');
     8645
     8646    // Allowed values for each setting.
     8647    $statuses_allowed = SucuriScanHeartbeat::statuses_allowed();
     8648    $pulses_allowed = SucuriScanHeartbeat::pulses_allowed();
     8649    $intervals_allowed = SucuriScanHeartbeat::intervals_allowed();
     8650
     8651    // HTML select form fields.
     8652    $heartbeat_options = SucuriScanTemplate::get_select_options( $statuses_allowed, $heartbeat_status );
     8653    $heartbeat_pulse_options = SucuriScanTemplate::get_select_options( $pulses_allowed, $heartbeat_pulse );
     8654    $heartbeat_interval_options = SucuriScanTemplate::get_select_options( $intervals_allowed, $heartbeat_interval );
     8655
     8656    $template_variables = array(
     8657        'HeartbeatStatus' => 'Undefined',
     8658        'HeartbeatPulse' => 'Undefined',
     8659        'HeartbeatInterval' => 'Undefined',
     8660        /* Heartbeat Options. */
     8661        'HeartbeatStatusOptions' => $heartbeat_options,
     8662        'HeartbeatPulseOptions' => $heartbeat_pulse_options,
     8663        'HeartbeatIntervalOptions' => $heartbeat_interval_options,
     8664        /* Heartbeat Auto-Start. */
     8665        'HeartbeatAutostart' => 'Enabled',
     8666        'HeartbeatAutostartSwitchText' => 'Disable',
     8667        'HeartbeatAutostartSwitchValue' => 'disable',
     8668        'HeartbeatAutostartSwitchCssClass' => 'button-danger',
     8669    );
     8670
     8671    if( array_key_exists($heartbeat_status, $statuses_allowed) ){
     8672        $template_variables['HeartbeatStatus'] = $statuses_allowed[$heartbeat_status];
     8673    }
     8674
     8675    if( array_key_exists($heartbeat_pulse, $pulses_allowed) ){
     8676        $template_variables['HeartbeatPulse'] = $pulses_allowed[$heartbeat_pulse];
     8677    }
     8678
     8679    if( array_key_exists($heartbeat_interval, $intervals_allowed) ){
     8680        $template_variables['HeartbeatInterval'] = $intervals_allowed[$heartbeat_interval];
     8681    }
     8682
     8683    if( $heartbeat_autostart == 'disabled' ){
     8684        $template_variables['HeartbeatAutostart'] = 'Disabled';
     8685        $template_variables['HeartbeatAutostartSwitchText'] = 'Enable';
     8686        $template_variables['HeartbeatAutostartSwitchValue'] = 'enable';
     8687        $template_variables['HeartbeatAutostartSwitchCssClass'] = 'button-success';
     8688    }
     8689
     8690    return SucuriScanTemplate::get_section('settings-heartbeat', $template_variables);
    82608691}
    82618692
     
    84978928    $cronjobs = _get_cron_array();
    84988929    $schedules = wp_get_schedules();
    8499     $date_format = _x('M j, Y - H:i', 'Publish box date format', 'cron-view' );
    85008930    $counter = 0;
    85018931
     
    85038933        foreach( (array) $cronhooks as $hook => $events ){
    85048934            foreach( (array) $events as $key => $event ){
     8935                if( empty($event['args']) ){
     8936                    $event['args'] = array( '<em>empty</em>' );
     8937                }
     8938
    85058939                $template_variables['Cronjobs.Total'] += 1;
    85068940                $template_variables['Cronjobs.List'] .= SucuriScanTemplate::get_snippet('infosys-cronjobs', array(
    85078941                    'Cronjob.Hook' => $hook,
    85088942                    'Cronjob.Schedule' => $event['schedule'],
    8509                     'Cronjob.NextTime' => date_i18n($date_format, $timestamp),
    8510                     'Cronjob.Arguments' => !empty($event['args']) ? implode(', ', $event['args']) : '<em>empty</em>',
     8943                    'Cronjob.NextTime' => SucuriScan::datetime($timestamp),
     8944                    'Cronjob.Arguments' => SucuriScan::implode(', ', $event['args']),
    85118945                    'Cronjob.CssClass' => ( $counter % 2 == 0 ) ? '' : 'alternate',
    85128946                ));
Note: See TracChangeset for help on using the changeset viewer.