protected function runTest() { echo "\n"; $errors_count = 0; $warnings_count = 0; $lib_time = 0; $lib_max_time = 0; $bc_time = 0; $bc_max_time = 0; $i = 0; foreach ($this->user_agents as $i => $user_agent) { $t = microtime(true); $lib_result = get_browser($user_agent); $ct = microtime(true) - $t; $lib_time += $ct; $lib_max_time = max($lib_max_time, $ct); $t = microtime(true); $bc_result = $this->browscap->getBrowser($user_agent); $ct = microtime(true) - $t; $bc_time += $ct; $bc_max_time = max($bc_max_time, $ct); $errors = array(); if ($user_agent == Browscap::BROWSCAP_VERSION_KEY) { if ($this->browscap->getSourceVersion() != $lib_result->version) { $errors[] = 'Source file version incorrect: ' . $lib_result->version . ' != ' . $this->browscap->getSourceVersion(); } } else { foreach ($this->properties as $bc_prop => $lib_prop) { $lib_value = $lib_result->{$lib_prop}; $bc_value = $bc_result->{$bc_prop}; if ($lib_value != $bc_value) { $errors[] = "{$bc_prop}: {$lib_value} != {$bc_value}"; } } } if ($errors && in_array($user_agent, $this->warnings)) { $warnings_count++; echo "get_browser() error fixed for '{$user_agent}'\n\n"; } elseif ($errors) { $errors_count++; $errors[] = "regex: '{$lib_result->browser_name_regex}' vs '{$bc_result->browser_name_regex}'"; echo "Errors for '{$user_agent}'\n" . implode("\n", $errors) . "\n\n"; } if ($i % 500 == 0 && $i != 0) { $this->printReport($i, $errors_count, $warnings_count, $lib_time, $lib_max_time, $bc_time, $bc_max_time); } } $this->printReport($i, $errors_count, $warnings_count, $lib_time, $lib_max_time, $bc_time, $bc_max_time); }
/** * @dataProvider providerUserAgent */ public function testCompare($userAgent) { $libResult = get_browser($userAgent); $bcResult = $this->object->getBrowser($userAgent); if ($userAgent == Browscap::BROWSCAP_VERSION_KEY) { self::assertSame($libResult->version, $this->object->getSourceVersion(), 'Source file version incorrect: ' . $libResult->version . ' != ' . $this->object->getSourceVersion()); } else { foreach ($this->properties as $bcProp => $libProp) { $libValue = $libResult->{$libProp}; $bcValue = $bcResult->{$bcProp}; self::assertSame($libValue, $bcValue, $bcProp . ': ' . $libValue . ' != ' . $bcValue); } } }
function wp_statistics_download_browscap() { GLOBAL $WP_Statistics; // We need the download_url() function, it should exists on virtually all installs of PHP, but if it doesn't for some reason, bail out. if( !function_exists( 'download_url' ) ) { return ''; } // If browscap is disabled, bail out. if( $WP_Statistics->get_option('browscap') == false ) { return '';} // This is the location of the file to download. $download_url = 'http://browscap.org/stream?q=Full_PHP_BrowsCapINI'; $download_version = 'http://browscap.org/version-number'; // Get the upload directory from WordPress. $upload_dir = wp_upload_dir(); // Check to see if the subdirectory we're going to upload to exists, if not create it. if( !file_exists($upload_dir['basedir'] . '/wp-statistics') ) { mkdir($upload_dir['basedir'] . '/wp-statistics'); } $LocalVersion = 0; // Get the Browscap object, tell it NOT to autoupdate. $bc = new Browscap($upload_dir['basedir'] . '/wp-statistics'); $bc->doAutoUpdate = false; // We don't want to auto update. // If we already have a browscap.ini file (aka we're already done a download in the past) we can get it's version number. // We can't execute this code if no browscap.ini exists as then the library will automatically download a full version, even // though we've told it not to autoupdate above. if( $WP_Statistics->get_option('last_browscap_dl') > 1 ) { // Get the current browser so that the version information is populated. try { $bc->getBrowser(); $LocalVersion = $bc->getSourceVersion(); } catch( Exception $e ) { $crawler = false; $LocalVersion = 0; } } // Get the remote version info from browscap.org. $TempVersionFile = download_url( $download_version ); // Read the version we just downloaded in to a string. $RemoteVersion = file_get_contents($TempVersionFile); // Get rid of the temporary file. unlink( $TempVersionFile ); // If there is a new version, let's go get it. if( intval($RemoteVersion) > $LocalVersion ) { // Download the file from browscap.org, this places it in a temporary location. $TempFile = download_url( $download_url ); // If we failed, through a message, otherwise proceed. if (is_wp_error( $TempFile ) ) { $result = "<div class='updated settings-error'><p><strong>" . sprintf(__('Error downloading browscap database from: %s - %s', 'wp_statistics'), $download_url, $TempFile->get_error_message() ) . "</strong></p></div>"; } else { // Keep the current version just in case by renaming it. if( file_exists( $upload_dir['basedir'] . '/wp-statistics/browscap.old' ) ) { unlink( $upload_dir['basedir'] . '/wp-statistics/browscap.old' ); } if( file_exists( $upload_dir['basedir'] . '/wp-statistics/cache.old' ) ) { unlink( $upload_dir['basedir'] . '/wp-statistics/cache.old' ); } if( file_exists( $upload_dir['basedir'] . '/wp-statistics/browscap.ini' ) ) { rename( $upload_dir['basedir'] . '/wp-statistics/browscap.ini', $upload_dir['basedir'] . '/wp-statistics/browscap.old' ); } if( file_exists( $upload_dir['basedir'] . '/wp-statistics/cache.php' ) ) { rename( $upload_dir['basedir'] . '/wp-statistics/cache.php', $upload_dir['basedir'] . '/wp-statistics/cache.old' ); } // Setup our file handles. $infile = fopen($TempFile, 'r' ); $outfile = fopen($upload_dir['basedir'] . '/wp-statistics/browscap.ini', 'w'); // We're going to need some variables to use as we process the new browscap.ini. // $crawler has three possible settings: // 0 = no setting found // 1 = setting found but not a crawler // 2 = setting found and a crawler $parent = ''; $title = ''; $crawler = 0; $parents = array( '' => false ); // Now read in the browscap.ini file we downloaded one line at a time. while( ( $buffer = fgets($infile) ) !== false) { // Let's get rid of the tailing carriage return extra spaces. $buffer = trim($buffer); // We're going to do some things based on the first charater on the line so let's just get it once. $firstchar = substr( $buffer, 0, 1 ); // The first character will tell us what kind of line we're dealing with. switch( $firstchar ) { // A square bracket means it's a section title. case '[': // We have three sections we need to copy verbatium so don't do the standard processing for them. if( $title != 'GJK_Browscap_Version' && $title != 'DefaultProperties' && $title != '*' && $title != '') { // Write out the section if: // the current section is a crawler and there is no parent // OR // the current section is a crawler, has a parent and the parent is a crawler as well (Note, this will drop some crawlers who's parent's aren't because we haven't written out all the parent's that aren't crawlers this could cause mis-identificaton of some users as crawlers). // OR // the current section isn't a crawler but the parent is // if( ( $crawler == 2 && $parent == '' ) || ( $crawler == 2 && $parent != '' && array_key_exists( $parent, $parents ) ) || ( $crawler == 0 && array_key_exists( $parent, $parents ) ) ) { // Write out the section with just the parent/crawler setting saved. fwrite( $outfile, "[" . $title . "]\n" ); fwrite( $outfile, "Crawler=\"true\"\n" ); } } // Reset our variables. $crawler = 0; $parent = ''; $title = substr( $buffer, 1, strlen($buffer) - 2 ); // We have three sections we need to copy verbatium so write out their headings immediatly instead of waiting to see if they are a crawler. if( $title == 'GJK_Browscap_Version' || $title == 'DefaultProperties' || $title == "*" ) { fwrite($outfile,"[" . $title . "]\n"); } break; // A space or semi-colan means it's a comment. case ' ': case ';': // Since we're hacking out lots of data the only comments we want to keep are the first few in the file before the first section is processed. if( $title == '' ) { fwrite( $outfile, $buffer . "\n" ); } break; // Otherwise its a real setting line. default: // If the setting is for the crawler let's inidicate we found it and it's true. We can also set the parents array. if( $buffer == 'Crawler="true"' ) { $crawler = 2; $parents[$title] = true;} // If the setting for the parent then set it now. if( substr( $buffer, 0, 7 ) == 'Parent=' ) { $parent = substr( $buffer, 8, -1 ); } // We have three sections we need to copy verbatium so write out their settings. if( $title == 'GJK_Browscap_Version' || $title == 'DefaultProperties' || $title == "*" ) { fwrite( $outfile, $buffer . "\n" ); } } } // Close the files. fclose( $outfile ); fclose( $infile ); // Delete the temporary file. unlink( $TempFile ); // Check to see if an old (more than a minute old) lock file exists, if so delete it. $cache_lock = $upload_dir['basedir'] . '/wp-statistics/cache.lock'; if( file_exists( $cache_lock ) ) { if( time() - filemtime( $cache_lock ) > 60 ) { unlink( $cache_lock ); } } // Force the cache to be updated. $bc->updateCache(); // Update the options to reflect the new download. $WP_Statistics->update_option('last_browscap_dl', time()); $WP_Statistics->update_option('update_browscap', false); $result = "<div class='updated settings-error'><p><strong>" . __('browscap database updated successfully!', 'wp_statistics') . "</strong></p></div>"; // Do some sanity checks on the new ini/cache file $ini_fs = filesize( $upload_dir['basedir'] . '/wp-statistics/browscap.ini' ); $cache_fs = filesize( $upload_dir['basedir'] . '/wp-statistics/cache.php' ); $fail = false; // Check to make sure the cache file isn't any more than 15% larger than then ini file if( $cache_fs - $ini_fs > $ini_fs * 0.15 ) { $fail = true; $result = "<div class='updated settings-error'><p><strong>" . __('browscap database updated failed! Cache file too large, reverting to previous browscap.ini.', 'wp_statistics') . "</strong></p></div>"; } else { // Check to make sure we don't resolve a typical user agent as a robot. $test_browser = $bc->getBrowser("Mozilla/5.0 (Windows NT 6.3; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0"); $crawler = $test_browser->Crawler; if( $crawler == true ) { $fail = true; $result = "<div class='updated settings-error'><p><strong>" . __('browscap database updated failed! New browscap.ini is mis-identifing user agents as crawlers, reverting to previous browscap.ini.', 'wp_statistics') . "</strong></p></div>"; } } // If we failed, roll back the update, otherwise just delete the old files. if( $fail == true ) { if( file_exists( $upload_dir['basedir'] . '/wp-statistics/browscap.ini' ) ) { unlink( $upload_dir['basedir'] . '/wp-statistics/browscap.ini' ); } if( file_exists( $upload_dir['basedir'] . '/wp-statistics/cache.php' ) ) { unlink( $upload_dir['basedir'] . '/wp-statistics/cache.php' ); } if( file_exists( $upload_dir['basedir'] . '/wp-statistics/browscap.old' ) ) { rename( $upload_dir['basedir'] . '/wp-statistics/browscap.old', $upload_dir['basedir'] . '/wp-statistics/browscap.ini' ); } if( file_exists( $upload_dir['basedir'] . '/wp-statistics/cache.old' ) ) { rename( $upload_dir['basedir'] . '/wp-statistics/cache.old', $upload_dir['basedir'] . '/wp-statistics/cache.php' ); } } else { if( file_exists( $upload_dir['basedir'] . '/wp-statistics/browscap.old' ) ) { unlink( $upload_dir['basedir'] . '/wp-statistics/browscap.old' ); } if( file_exists( $upload_dir['basedir'] . '/wp-statistics/cache.old' ) ) { unlink( $upload_dir['basedir'] . '/wp-statistics/cache.old' ); } } } } else { // Update the options to reflect the new download. $WP_Statistics->update_option('last_browscap_dl', time()); $WP_Statistics->update_option('update_browscap', false); $result = "<div class='updated settings-error'><p><strong>" . __('browscap already at current version!', 'wp_statistics') . "</strong></p></div>"; } if( $WP_Statistics->get_option('browscap_report') == true ) { $blogname = get_bloginfo('name'); $blogemail = get_bloginfo('admin_email'); $headers[] = "From: $blogname <$blogemail>"; $headers[] = "MIME-Version: 1.0"; $headers[] = "Content-type: text/html; charset=utf-8"; if( $WP_Statistics->get_option('email_list') == '' ) { $WP_Statistics->update_option( 'email_list', $blogemail ); } wp_mail( $WP_Statistics->get_option('email_list'), __('Browscap.ini update on', 'wp_statistics') . ' ' . $blogname, $result, $headers ); } // All of the messages displayed above are stored in a stirng, now it's time to actually output the messages. return $result; }