browscap.module in Browscap 5
Same filename and directory in other branches
Replacement for PHP's get_browser() function
File
browscap.moduleView source
<?php
/**
* @file
* Replacement for PHP's get_browser() function
*/
/**
* ******************** Drupal Hooks ************************
*/
/**
* Implementation of hook_menu().
*
* @return array
*/
function browscap_menu($may_cache) {
$items = array();
$access = user_access('access administration pages');
if ($may_cache) {
// LOG PAGES
$items[] = array(
'path' => 'admin/logs/browscap',
'title' => t('Browscap'),
'description' => t('Browser-specific site statistics.'),
'callback' => 'browscap_top_useragents',
'callback arguments' => array(
'all',
),
'access' => $access,
'weight' => 5,
);
$items[] = array(
'path' => 'admin/logs/browscap/useragents',
'title' => t('All user agents'),
'access' => $access,
'weight' => 1,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items[] = array(
'path' => 'admin/logs/browscap/browsers',
'callback' => 'browscap_top_useragents',
'callback arguments' => array(
'browsers',
),
'title' => t('Browsers'),
'access' => $access,
'weight' => 2,
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => 'admin/logs/browscap/crawlers',
'callback' => 'browscap_top_useragents',
'callback arguments' => array(
'crawlers',
),
'title' => t('Crawlers'),
'access' => $access,
'weight' => 3,
'type' => MENU_LOCAL_TASK,
);
// SETTINGS PAGE
$items[] = array(
'path' => 'admin/settings/browscap',
'title' => t('Browscap'),
'description' => t('Enable browscap site statistics.'),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'browscap_settings',
),
'access' => user_access('administer site configuration'),
);
$items[] = array(
'path' => 'admin/settings/browscap/refresh',
'title' => t('Browscap Refresh'),
'callback' => 'browscap_refresh',
'access' => user_access('administer site configuration'),
'type' => MENU_CALLBACK,
);
}
else {
if (arg(0) == 'admin' && arg(1) == 'logs' && arg(2) == 'browscap' && arg(3) == 'useragent' && arg(4)) {
// INFORMATION ABOUT A USERAGENT
$items[] = array(
'path' => 'admin/logs/browscap/useragent',
'callback' => 'browscap_useragent_properties',
'title' => 'Useragent details',
'access' => $access,
'weight' => 5,
'type' => MENU_LOCAL_TASK,
);
}
}
return $items;
}
/**
* Implementation of hook_exit().
*
* Keep tabs on browsers that visit
*/
function browscap_exit() {
// If monitoring is enabled, record the browser
if (variable_get('browscap_monitor', FALSE)) {
$browser = browscap_get_browser();
$browserstring = substr(trim($browser['parent']), 0, 255);
if ($browserstring == '' or $browserstring == 'Default Browser') {
$browserstring = trim($_SERVER['HTTP_USER_AGENT']);
}
db_query("UPDATE {browscap_statistics} SET counter = counter + 1, is_crawler=%d " . "WHERE parent='%s'", $browser['crawler'], $browserstring);
// If we affected 0 rows, this is the first time we've seen this browser
if (!db_affected_rows()) {
// We must create a new row to store counters for the new browser.
db_query('INSERT INTO {browscap_statistics} (parent,counter,is_crawler) ' . "VALUES('%s', 1, %d)", $browserstring, $browser['crawler']);
}
}
}
/**
* Implementation of hook_cron().
*/
function browscap_cron() {
// Has it been a week since the last (attempt to) import?
$last_imported = variable_get('browscap_imported', 0);
if ($last_imported + 60 * 60 * 24 * 7 < time()) {
_browscap_import();
variable_set('browscap_imported', time());
}
}
/**
* ******************** Menu Callbacks ************************
*/
/**
* Callback for settings form
* Turn monitoring on or off
*
* @return array
*/
function browscap_settings() {
$form['browscap_monitor'] = array(
'#type' => 'checkbox',
'#prefix' => t('<p>Browscap data current as of %fileversion. [<a href="!refresh">Refresh now</a>]</p>', array(
'%fileversion' => variable_get('browscap_version', t('Never fetched')),
'!refresh' => url('admin/settings/browscap/refresh'),
)),
'#title' => t('Monitor browsers'),
'#default_value' => variable_get('browscap_monitor', FALSE),
'#description' => t('Monitor all user agents visiting the site.'),
);
return system_settings_form($form);
}
function browscap_refresh() {
_browscap_import(FALSE);
drupal_goto('admin/settings/browscap');
}
/**
* Menu callback; presents the user agents monitoring page.
*
* @param $view
* - "browsers": Only display "real" browsers
* - "crawlers": Only display search engine crawlers
* - "all": Display all user agents.
*/
function browscap_top_useragents($view = 'all') {
if ($view == 'all') {
$result = db_query('SELECT SUM(counter) FROM {browscap_statistics}');
$total = db_result($result);
if (!$total) {
$total = 1;
}
$query = "SELECT parent,counter,(100*counter)/{$total} as percent,is_crawler FROM {browscap_statistics}";
$query_cnt = 'SELECT COUNT(parent) FROM {browscap_statistics}';
$title = t('Top user agents');
$header = array(
array(
'data' => t('User agent'),
'field' => 'parent',
),
array(
'data' => t('Count'),
'field' => 'counter',
'sort' => 'desc',
),
array(
'data' => t('Percent'),
'field' => 'percent',
),
array(
'data' => t('Crawler?'),
'field' => 'is_crawler',
),
);
}
elseif ($view == 'browsers') {
$result = db_query('SELECT SUM(counter) FROM {browscap_statistics} WHERE is_crawler=0');
$total = db_result($result);
if (!$total) {
$total = 1;
}
$query = "SELECT parent,counter,(100*counter)/{$total} as percent FROM {browscap_statistics} WHERE is_crawler=0";
$query_cnt = 'SELECT COUNT(parent) FROM {browscap_statistics} WHERE is_crawler=0';
$title = t('Top browsers');
$header = array(
array(
'data' => t('Browser'),
'field' => 'parent',
),
array(
'data' => t('Count'),
'field' => 'counter',
'sort' => 'desc',
),
array(
'data' => t('Percent'),
'field' => 'percent',
),
);
}
else {
$result = db_query('SELECT SUM(counter) FROM {browscap_statistics} WHERE is_crawler=1');
$total = db_result($result);
if (!$total) {
$total = 1;
}
$query = "SELECT parent,counter,(100*counter)/{$total} as percent FROM {browscap_statistics} WHERE is_crawler=1";
$query_cnt = 'SELECT COUNT(parent) FROM {browscap_statistics} WHERE is_crawler=1';
$title = t('Top crawlers');
$header = array(
array(
'data' => t('Crawler'),
'field' => 'parent',
),
array(
'data' => t('Count'),
'field' => 'counter',
'sort' => 'desc',
),
array(
'data' => t('Percent'),
'field' => 'percent',
),
);
}
drupal_set_title($title);
$query .= tablesort_sql($header);
$result = pager_query($query, 50, 0, $query_cnt);
while ($useragent = db_fetch_object($result)) {
if (db_result(db_query_range('SELECT useragent FROM {browscap} WHERE useragent = "%s"', $useragent->parent, 0, 1))) {
$parent = l($useragent->parent, 'admin/logs/browscap/useragent/' . urlencode($useragent->parent));
}
else {
$parent = check_plain($useragent->parent);
}
if ($view == 'all') {
if ($useragent->is_crawler) {
$is_crawler = t('Yes');
}
else {
$is_crawler = t('No');
}
$rows[] = array(
$parent,
$useragent->counter,
$useragent->percent,
$is_crawler,
);
}
else {
$rows[] = array(
$parent,
$useragent->counter,
$useragent->percent,
);
}
}
if ($pager = theme('pager', NULL, 50, 0)) {
$rows[] = array(
array(
'data' => $pager,
'colspan' => 2,
),
);
}
$output .= theme('table', $header, $rows);
print theme('page', $output, $title);
}
function browscap_get_browser($useragent = NULL) {
if (!$useragent) {
$useragent = $_SERVER['HTTP_USER_AGENT'];
}
// Cache the results
$cacheid = $useragent;
$cache = cache_get($cacheid, 'cache_browscap');
if (!empty($cache) and $cache->created > time() - 60 * 60 * 24) {
// Found a fresh entry in the cache
$browserinfo = unserialize($cache->data);
}
else {
// Note the 'backwards' use of LIKE - the useragent column contains
// the wildcarded pattern to match against our full-length string
// The ORDER BY chooses the most-specific matching pattern
$browserinfo = db_fetch_object(db_query_range("SELECT * from {browscap} WHERE '%s' LIKE useragent ORDER BY LENGTH(useragent) DESC", $useragent, 0, 1));
// A couple of fieldnames not in our database, provided for
// compatibility with PHP's get_browser()
//$browserinfo->tables = $browserinfo->htmltables;
cache_set($cacheid, 'cache_browscap', serialize($browserinfo));
}
$info = unserialize($browserinfo->data);
$info['useragent'] = $useragent;
$info['browser_name_pattern'] = strtr($browserinfo->useragent, '%_', '*?');
return $info;
}
// A numeric interpretation of browscap.csv's TRUE/FALSE/default fields
function _browscap_boolean($value) {
switch ($value) {
case 'TRUE':
case 'true':
return 1;
case 'FALSE':
case 'false':
case 'default':
default:
return 0;
}
}
/**
* If there's a new version of browscap.csv, fetch it and update the
* database.
*/
function _browscap_import($cron = TRUE) {
// Politely check the version for updates before fetching the file
$versionpage = drupal_http_request('http://browsers.garykeith.com/versions/version-number.asp');
if ($versionpage->error) {
watchdog('browscap', t("Couldn't check version: ") . $versionpage->error);
if (!$cron) {
drupal_set_message(t("Couldn't check version: ") . $versionpage->error, 'error');
}
return;
}
$browscapversion = trim($versionpage->data);
$oldversion = variable_get('browscap_version', 'Never fetched');
if ($browscapversion == $oldversion) {
// No update, nothing to do here
watchdog('browscap', t('No new version of browscap to import'));
if (!$cron) {
drupal_set_message(t('No new version of browscap to import'));
}
return;
}
// Fetch the new version, and dump it in the temp directory
$server = $_SERVER['SERVER_NAME'];
$path = variable_get('file_directory_temp', '/tmp');
$browscapfile = "{$path}/browscap_{$server}.ini";
$browscap = drupal_http_request('http://browsers.garykeith.com/stream.asp?PHP_BrowsCapINI');
if ($browscap->error or !trim($browscap->data)) {
watchdog('browscap', t("Couldn't retrieve updated browscap: ") . $browscap->error);
if (!$cron) {
drupal_set_message(t("Couldn't retrieve updated browscap: ") . $browscap->error);
}
return;
}
$browscapfp = fopen($browscapfile, "w");
fwrite($browscapfp, $browscap->data);
fclose($browscapfp);
$a = parse_ini_file($browscapfile, TRUE);
if ($a) {
// the first entry in the array is the version info
$version = array_shift($a);
foreach ($a as $key => $vals) {
$e = $vals;
// some recursive magic!
$last_parent = array();
while ($vals['Parent'] && $vals['Parent'] !== $last_parent) {
$vals = $a[$vals['Parent']];
$e = array_merge((array) $vals, (array) $e);
$last_parent = $vals;
}
$useragent = strtr($key, '*?', '%_');
$e = array_change_key_case($e);
db_query("REPLACE INTO {browscap} (useragent, data) VALUES('%s','%s')", $useragent, serialize($e));
}
cache_clear_all('*', 'cache_browscap', TRUE);
variable_set('browscap_version', $browscapversion);
watchdog('browscap', t("New version of browscap imported: ") . $browscapversion);
if (!$cron) {
drupal_set_message(t("New version of browscap imported: ") . $browscapversion);
}
}
}
/*
* Undo a recorded browser visit by request
*
* This function serves the statistics_filter module, enabling it
* to ignore visits from specified roles.
*/
function browscap_unmonitor() {
// No point if statistics aren't enabled
if (!module_exists('statistics')) {
return;
}
// If monitoring is enabled, unrecord the browser
if (variable_get('browscap_monitor', FALSE)) {
$browser = browscap_get_browser();
$browserstring = trim($browser->parent);
if ($browserstring == '' or $browserstring == 'Default Browser') {
$browserstring = trim($_SERVER['HTTP_USER_AGENT']);
}
db_query("UPDATE {browscap_statistics} SET counter = counter - 1, is_crawler=%d " . "WHERE parent='%s'", $browser->crawler, $browserstring);
}
}
/**
* Page callback to show details about known useragents.
*
* @param string $useragent a useragent, taken from the url.
* @return string an HTMl blob representing the data about this useragent.
*/
function browscap_useragent_properties($useragent = NULL) {
drupal_set_title(check_plain(arg(4)));
if ($useragent == NULL) {
drupal_not_found();
return;
}
$row = db_fetch_object(db_query('SELECT * FROM {browscap} WHERE useragent = "%s"', $useragent));
if (!$row) {
drupal_not_found();
return;
}
$data = unserialize($row->data);
$headers = array(
t('property'),
t('value'),
);
foreach ($data as $key => $val) {
$rows[] = array(
check_plain($key),
check_plain($val),
);
}
$output = theme('table', $headers, $rows);
return $output;
}
Functions
Name | Description |
---|---|
browscap_cron | Implementation of hook_cron(). |
browscap_exit | Implementation of hook_exit(). |
browscap_get_browser | |
browscap_menu | Implementation of hook_menu(). |
browscap_refresh | |
browscap_settings | Callback for settings form Turn monitoring on or off |
browscap_top_useragents | Menu callback; presents the user agents monitoring page. |
browscap_unmonitor | |
browscap_useragent_properties | Page callback to show details about known useragents. |
_browscap_boolean | |
_browscap_import | If there's a new version of browscap.csv, fetch it and update the database. |