You are here

mobile_tools.module in Mobile Tools 6.3

Mobile Tools provides a range of functionality assisting in creating a mobile Drupal site . this functionality contains:

  • User Agent detection ('mobile' or 'desktop')
  • automatic redirection towards mobile site or user notification by means of a block message or drupal_set_message
  • Adding a mobile context to the permission system
  • Adding a mobile context to theming (= theme switching or separate configuration for desktop and )
  • ...

For more documentation and examples please go to http://drupal.org/node/459686

File

mobile_tools.module
View source
<?php

/**
 * @file
 * Mobile Tools provides a range of functionality assisting in creating a mobile Drupal site . this functionality contains:
 * - User Agent detection ('mobile' or 'desktop')
 * - automatic redirection towards mobile site or user notification by means of a block message or drupal_set_message
 * - Adding a mobile context to the permission system
 * - Adding a mobile context to theming (= theme switching or separate configuration for desktop and )
 * - ...
 *
 * For more documentation and examples please go to http://drupal.org/node/459686
 */

/* The default messages being displayed to the users . these can be overwritten in
* the configuration panel
*/
define('MOBILE_NOTIFICATION', '<a href="!desktop_url">View full site</a>');
define('DESKTOP_NOTIFICATION', '<a href="!mobile_url">View mobile site</a>');

/**
* Implementation of hook_help($section).
*/
function mobile_tools_help($path, $arg) {
  switch ($path) {
    case 'admin/help#mobile_tools':
      return '<p>' . t('Visit the !documentation for more info', array(
        '!documentation' => l('documentation page', 'http://drupal.org/node/459686'),
      )) . '<p>';
  }
}

/**
 * Implementation of hook_perm().
 */
function mobile_tools_perm() {
  return array(
    'configure Mobile Tools',
  );
}

/**
 * Implementation of hook_menu().
 */
function mobile_tools_menu() {
  $items['admin/settings/mobile-tools'] = array(
    'title' => 'Mobile Tools',
    'description' => t('Configure the detection of the mobile client and the appropriate actions.'),
    'access arguments' => array(
      'configure Mobile Tools',
    ),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'mobile_tools_configuration_form',
    ),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'mobile_tools.admin.inc',
  );
  $items['admin/settings/mobile-tools/device-detection'] = array(
    'title' => 'Notification / redirection',
    'description' => 'Configure the detection of the mobile client and the appropriate actions (notifications or redirection)',
    'access arguments' => array(
      'configure Mobile Tools',
    ),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -4,
    'file' => 'mobile_tools.admin.inc',
  );
  $items['admin/settings/mobile-tools/themes'] = array(
    'title' => 'Theme Switching',
    'page arguments' => array(
      'mobile_tools_themes_configuration_form',
    ),
    'page callback' => 'drupal_get_form',
    'access arguments' => array(
      'configure Mobile Tools',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 0,
    'file' => 'mobile_tools.admin.inc',
  );
  $items['admin/settings/mobile-tools/ext'] = array(
    'title' => 'External modules',
    'page arguments' => array(
      'mobile_tools_external_modules_configuration_form',
    ),
    'page callback' => 'drupal_get_form',
    'access arguments' => array(
      'configure Mobile Tools',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 10,
    'file' => 'mobile_tools.admin.inc',
  );
  $items['mt/desktop/%mobile_tools_menu_link'] = array(
    'title' => 'Full site',
    'page callback' => 'mobile_tools_menu_switch_site',
    'access callback' => 'mobile_tools_menu_link_access',
    'access arguments' => array(
      'desktop',
    ),
  );
  $items['mt/mobile/%mobile_tools_menu_link'] = array(
    'title' => "Mobile Site",
    'page callback' => 'mobile_tools_menu_switch_site',
    'access callback' => 'mobile_tools_menu_link_access',
    'access arguments' => array(
      'mobile',
    ),
  );
  return $items;
}

/**
 *  Access function for the mobile tools menu links. It decides on which link to shown.
 */
function mobile_tools_menu_link_access($target_site) {
  if (preg_match('/admin\\/build\\/menu/', $_GET['q'])) {
    return TRUE;
  }
  $current_site = mobile_tools_site_type();

  // Only show the link if it's target is different then the current site
  if ($target_site == $current_site) {
    return FALSE;
  }
  else {
    return TRUE;
  }
}

/**
 * Implementation of %mobile_tools_menu_link
 */
function mobile_tools_menu_link_to_arg($arg) {
  return $_GET['q'];
}

/**
 * Redirect the user to the right path
 */
function mobile_tools_menu_switch_site() {
  $args = arg();
  array_shift($args);
  $site = array_shift($args);
  $path = implode('/', $args);

  // In case of redirect, we already redirect to the target url
  if (variable_get('mobile_tools_redirect', FALSE)) {
    if ($site == "desktop") {
      $url = variable_get('mobile_tools_desktop_url', '') . '/' . $path;
    }
    else {
      $url = variable_get('mobile_tools_mobile_url', '') . '/' . $path;
    }
  }
  else {
    $url = $path;
  }
  $querystring = drupal_query_string_encode(array_merge($_GET, array(
    'device' => $site,
  )), array(
    'q',
  ));
  drupal_goto($url, $querystring);
}

/**
 * Create the url to go to the desktop/mobile version
 * @param $site
 *   Target site: mobile / desktop
 * @param $path
 *   Current path
 */
function mobile_tools_switch_menu_link($site, $path) {
  return 'mt/' . $site . '/' . $path;
}

/**
 * Implementation of hook_theme()
 */
function mobile_tools_theme() {
  $templates['mobile_tools_header'] = array(
    'template' => 'mobile-tools-header',
    'arguments' => array(),
    'path' => drupal_get_path('module', 'mobile_tools') . '/theme',
  );
  return $templates;
}

/**
 * Implementation of hook_block()
 * Provides the blocks that can be used to show a message to the user to go to the
 * mobile or desktop version.
 */
function mobile_tools_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
      $blocks[0]['info'] = t('Mobile Tools message block');
      $blocks[0]['cache'] = BLOCK_NO_CACHE;
      return $blocks;
      break;
    case 'view':
      $block['content'] = mobile_tools_block_message();
      return $block;
      break;
  }
}

/**
 *  Helper function returning the configurable message for the notification
 */
function mobile_tools_block_message() {
  $site = mobile_tools_site_type();
  $querystring = drupal_query_string_encode($_GET, array(
    'q',
    'device',
  ));
  if (!empty($querystring)) {
    $querystring = '?' . $querystring;
  }
  if ($site == 'mobile') {

    // Fix for security issue https://security.drupal.org/node/70779
    $output = filter_xss(variable_get('mobile_notification', MOBILE_NOTIFICATION));
    $desktop_url = filter_xss(mobile_tools_switch_menu_link('desktop', $_GET['q']));
    $output = t($output, array(
      '!desktop_url' => '/' . $desktop_url . $querystring,
    ));
    return $output;
  }
  elseif ($site == 'desktop') {

    // Fix for security issue https://security.drupal.org/node/70779
    $output = filter_xss(variable_get('desktop_notification', DESKTOP_NOTIFICATION));
    $mobile_url = filter_xss(mobile_tools_switch_menu_link('mobile', $_GET['q']));
    $output = t($output, array(
      '!mobile_url' => '/' . $mobile_url . $querystring,
    ));
    return $output;
  }
}

/**
 *  Implementation of hook_boot().
 *  Redirecting if needed
 */
function mobile_tools_boot() {
  global $mobile_tools_device, $conf;

  // Skip everything in case drush is used
  if (php_sapi_name() == 'cli') {
    return;
  }

  // Get the device object
  $mobile_tools_device = mobile_tools_get_device();

  // First call the redirect function. This will redirect the userif needed.
  if (variable_get('mobile_tools_redirect', FALSE)) {
    $redirected = mobile_tools_device_redirect($mobile_tools_device);
  }
  if (mobile_tools_site_type() == 'mobile') {
    $conf['site_frontpage'] = variable_get('site_frontpage_mobile', variable_get('site_frontpage', 'node'));
  }

  // Switch theme if needed
  $theme_switched = mobile_tools_switch_theme($mobile_tools_device);
}

/**
 * Theme switching:
 * - Only for non cached pages!
 */
function mobile_tools_init() {
  global $mobile_tools_device, $conf;

  // Skip everything in case Drush is used
  if (php_sapi_name() == 'cli') {
    return;
  }

  // Some small extras
  if (mobile_tools_site_type() == 'mobile') {
    $conf['default_nodes_main'] = variable_get('default_nodes_main_mobile', variable_get('default_nodes_main', 10));
  }

  /**
   * We set the context
   */
  if (module_exists('context')) {
    $plugin = context_get_plugin('condition', 'mobile');
    if (!empty($plugin) && is_object($plugin)) {
      $device = mobile_tools_get_device();
      $plugin
        ->execute($device['type']);
      $plugin
        ->execute($device['group']);
    }
  }
}

/**
 * Being called in the hook_boot() implementation
 * This function is in charge of redirection or displaying a notification
 * @param $device
 *   The device object array('type' => [mobile/desktop], 'group' => [group])
 */
function mobile_tools_device_redirect($device) {
  global $base_url;

  //only consider redirection if the mobile url and the destkop url are different
  $mobile_url = variable_get('mobile_tools_mobile_url', '');
  $desktop_url = variable_get('mobile_tools_desktop_url', '');
  if ($mobile_url == $desktop_url) {
    return;
  }

  // see if the user is currently requestin the mobile or desktop url
  $current_url_type = mobile_tools_site_type();

  // code takes into account path exceptions in the configuration.
  $pages = variable_get('mobile_tools_redirect_exceptions', '');
  $page_match = FALSE;
  if (isset($_GET['q']) && $pages != '') {

    //check if there is no exception in the redirect path (code comes from block.module)
    include_once './includes/bootstrap.inc';
    drupal_bootstrap(DRUPAL_BOOTSTRAP_PATH);
    $path = drupal_get_path_alias($_GET['q']);

    // Compare with the internal and path alias (if any).
    $page_match = drupal_match_path($path, $pages);
    if ($path != $_GET['q']) {
      $page_match = $page_match || drupal_match_path($_GET['q'], $pages);
    }
  }

  // check if exceptions are pages on which to redirect, or not to redirect
  if (variable_get('mobile_tools_redirect_exceptions_type', 0) == 'only-redirect') {
    $page_match = !$page_match;
  }

  // Redirections
  if (!$page_match) {

    // The case where a mobile user is accessing the desktop site
    if ($device['type'] == 'mobile' && $current_url_type == 'desktop') {
      $destination_url = mobile_tools_get_redirect_url('mobile');
      mobile_tools_goto($destination_url);

      // The case where a desktop user is accessing the mobile site
    }
    elseif ($device['type'] == 'desktop' && $current_url_type == 'mobile') {
      $destination_url = mobile_tools_get_redirect_url('desktop');
      mobile_tools_goto($destination_url);
    }
  }
}

/**
 * Being called in the hook_boot() implementation
 * This function is in charge of changing to the mobile theme
 */
function mobile_tools_switch_theme($device) {
  global $custom_theme, $conf;

  // check if theme switching is forced
  $current_url_type = mobile_tools_site_type();
  if ($current_url_type == 'mobile' && variable_get('mobile-tools-theme-switch', '') == 'mobile-tools-mobile-url' || variable_get('mobile-tools-theme-switch', '') == 'mobile-tools-mobile-device' && $device['type'] == 'mobile') {
    $group = $device['group'];
    $mobile_detection_module = variable_get('mobile-tools-device-detection', 'mobile_tools');
    if (variable_get($mobile_detection_module . '_' . $group . '_enable', '') == 1) {
      $custom_theme = variable_get($mobile_detection_module . '_' . $group . '_theme', $conf['theme_default']);
      return TRUE;
    }
    else {
      $custom_theme = variable_get('mobile_tools_theme_name', $conf['theme_default']);
      return TRUE;
    }
  }
  elseif (!empty($device['group'])) {

    //device groups are independent of device types

    // Allow custom themes for 'desktop' device types
    $group = $device['group'];
    $mobile_detection_module = variable_get('mobile-tools-device-detection', 'mobile_tools');
    if (variable_get($mobile_detection_module . '_' . $group . '_enable', '') == 1) {
      $custom_theme = variable_get($mobile_detection_module . '_' . $group . '_theme', $conf['theme_default']);
      return $custom_theme;
    }
  }
  return FALSE;
}

/**
 * Get $device object.
 * Check if the 'device' argument is present or a cookie is set to overwrite the device:
 * - device=mobile =>  mobile view
 * - device=desktop => desktop view
 * - device=[group] => specific group view
 * - device=auto => reset overwrite
 * @return $device
 *  The $device object
 */
function mobile_tools_get_device() {
  global $cookie_domain, $mobile_tools_device;

  // currently the boot method saves the result in a global variable.
  if (isset($mobile_tools_device)) {
    return $mobile_tools_device;
  }

  // Checking the possible arguments
  $session_time = time() + variable_get('mobile_tools_cookie_session', 3600 * 24 * 30);

  //first check if the device type is forced in the device argument
  if (isset($_GET['device'])) {
    switch ($_GET['device']) {
      case 'desktop':
      case 'mobile':
        setCookie('mt_device', $_GET['device'], variable_get('mobile_tools_cookie_lifetime', $session_time), '/', $cookie_domain);
        return array(
          'type' => $_GET['device'],
          'group' => '',
        );
        break;
      case 'auto':
        setCookie('mt_device', '', time() - 3600, '/', $cookie_domain);
        break;
      default:
        $device_groups = mobile_tools_device_groups();
        if (isset($device_groups[$_GET['device']])) {
          setCookie('mt_device', $_GET['device'], variable_get('mobile_tools_cookie_lifetime', $session_time), '/', $cookie_domain);
          return array(
            'type' => 'mobile',
            'group' => $_GET['device'],
          );
        }
    }
  }
  elseif (isset($_COOKIE['mt_device'])) {
    switch ($_COOKIE['mt_device']) {
      case 'desktop':
      case 'mobile':
        return array(
          'type' => $_COOKIE['mt_device'],
          'group' => '',
        );
        break;
      case 'auto':
        setCookie('mt_device', '', time() - 3600, '/');
        break;
      default:
        $device_groups = mobile_tools_device_groups();
        if (isset($device_groups[$_COOKIE['mt_device']])) {
          setCookie('mt_device', $_COOKIE['mt_device'], variable_get('mobile_tools_cookie_lifetime', $session_time), '/');
          return array(
            'type' => 'mobile',
            'group' => $_COOKIE['mt_device'],
          );
        }
    }
  }

  // we default to the real detection
  return mobile_tools_is_mobile_device();
}

/**
 * Detect the device
 * @return $device
 *  The $device object. Other modules can implement the hook_is_mobile_device()
 */
function mobile_tools_is_mobile_device() {
  $device_detection = variable_get('mobile-tools-device-detection', 'mobile_tools');
  drupal_load('module', $device_detection);
  if ($device_detection != 'mobile_tools') {
    return module_invoke($device_detection, 'is_mobile_device');
  }
  else {
    return _mobile_tools_is_mobile_device();
  }
}

/**
 *  Default implementation of hook_is_mobile_device()
 * @return $device
 *  The $device object
 */
function _mobile_tools_is_mobile_device() {
  $mobile_browser = array(
    'type' => 'desktop',
    'group' => '',
  );

  // set mobile browser as FALSE till we can prove otherwise
  if (array_key_exists('HTTP_USER_AGENT', $_SERVER)) {
    $user_agent = $_SERVER['HTTP_USER_AGENT'];
  }
  else {
    return FALSE;
  }

  // get the content accept value
  // FIXME: this should be cleaned to ensure no nefarious input gets executed
  if (array_key_exists('HTTP_ACCEPT', $_SERVER)) {
    $accept = $_SERVER['HTTP_ACCEPT'];
  }
  else {
    $accept = '';
  }
  switch (TRUE) {
    case FALSE !== stripos($user_agent, 'ipad'):
      $mobile_browser = array(
        'type' => 'desktop',
        'group' => 'ipad',
      );
      break;
    case FALSE !== stripos($user_agent, 'ipod'):

      // we find the words iphone or ipod in the user agent
      $mobile_browser = array(
        'type' => 'mobile',
        'group' => 'ipod',
      );

      // mobile browser is either TRUE or FALSE depending on the setting of iphone when calling the function
      break;

    // break out and skip the rest if we've had a match on the iphone or ipod
    case FALSE !== stripos($user_agent, 'iphone'):

      // we find the words iphone or ipod in the user agent
      $mobile_browser = array(
        'type' => 'mobile',
        'group' => 'iphone',
      );
      break;
    case FALSE !== stripos($user_agent, 'android'):

      // we find android in the user agent
      $mobile_browser = array(
        'type' => 'mobile',
        'group' => 'android',
      );

      // mobile browser is either TRUE or FALSE depending on the setting of android when calling the function
      break;

    // break out and skip the rest if we've had a match on android
    case FALSE !== stripos($user_agent, 'opera mini'):

      // we find opera mini in the user agent
      $mobile_browser = array(
        'type' => 'mobile',
        'group' => 'opera_mini',
      );

      // mobile browser is either TRUE or FALSE depending on the setting of opera when calling the function
      break;

    // break out and skip the rest if we've had a match on opera
    case FALSE !== stripos($user_agent, 'blackberry'):

      // we find blackberry in the user agent
      $mobile_browser = array(
        'type' => 'mobile',
        'group' => 'blackberry',
      );

      // mobile browser is either TRUE or FALSE depending on the setting of blackberry when calling the function
      break;

    // break out and skip the rest if we've had a match on blackberry
    case preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|vodafone|o2|pocket|kindle|mobile|pda|psp|treo)/i', $user_agent):

      // check if any of the values listed create a match on the user agent - these are some of the most common terms used in agents to identify them as being mobile devices - the i at the end makes it case insensitive
      $mobile_browser = array(
        'type' => 'mobile',
        'group' => '',
      );

      // set mobile browser to TRUE
      break;

    // break out and skip the rest if we've preg_match on the user agent returned TRUE
    case strpos($accept, 'text/vnd.wap.wml') > 0 || strpos($accept, 'application/vnd.wap.xhtml+xml') > 0:

      // is the device showing signs of support for text/vnd.wap.wml or application/vnd.wap.xhtml+xml
      $mobile_browser = array(
        'type' => 'mobile',
        'group' => '',
      );

      // set mobile browser to TRUE
      break;

    // break out and skip the rest if we've had a match on the content accept headers
    case isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE']):

      // is the device giving us a HTTP_X_WAP_PROFILE or HTTP_PROFILE header - only mobile devices would do this
      $mobile_browser = array(
        'type' => 'mobile',
        'group' => '',
      );

      // set mobile browser to TRUE
      break;

    // break out and skip the final step if we've had a return TRUE on the mobile specfic headers
    case in_array(strtolower(substr($user_agent, 0, 4)), array(
      '1207' => '1207',
      '3gso' => '3gso',
      '4thp' => '4thp',
      '501i' => '501i',
      '502i' => '502i',
      '503i' => '503i',
      '504i' => '504i',
      '505i' => '505i',
      '506i' => '506i',
      '6310' => '6310',
      '6590' => '6590',
      '770s' => '770s',
      '802s' => '802s',
      'a wa' => 'a wa',
      'acer' => 'acer',
      'acs-' => 'acs-',
      'airn' => 'airn',
      'alav' => 'alav',
      'asus' => 'asus',
      'attw' => 'attw',
      'au-m' => 'au-m',
      'aur ' => 'aur ',
      'aus ' => 'aus ',
      'abac' => 'abac',
      'acoo' => 'acoo',
      'aiko' => 'aiko',
      'alco' => 'alco',
      'alca' => 'alca',
      'amoi' => 'amoi',
      'anex' => 'anex',
      'anny' => 'anny',
      'anyw' => 'anyw',
      'aptu' => 'aptu',
      'arch' => 'arch',
      'argo' => 'argo',
      'bell' => 'bell',
      'bird' => 'bird',
      'bw-n' => 'bw-n',
      'bw-u' => 'bw-u',
      'beck' => 'beck',
      'benq' => 'benq',
      'bilb' => 'bilb',
      'blac' => 'blac',
      'c55/' => 'c55/',
      'cdm-' => 'cdm-',
      'chtm' => 'chtm',
      'capi' => 'capi',
      'comp' => 'comp',
      'cond' => 'cond',
      'craw' => 'craw',
      'dall' => 'dall',
      'dbte' => 'dbte',
      'dc-s' => 'dc-s',
      'dica' => 'dica',
      'ds-d' => 'ds-d',
      'ds12' => 'ds12',
      'dait' => 'dait',
      'devi' => 'devi',
      'dmob' => 'dmob',
      'doco' => 'doco',
      'dopo' => 'dopo',
      'el49' => 'el49',
      'erk0' => 'erk0',
      'esl8' => 'esl8',
      'ez40' => 'ez40',
      'ez60' => 'ez60',
      'ez70' => 'ez70',
      'ezos' => 'ezos',
      'ezze' => 'ezze',
      'elai' => 'elai',
      'emul' => 'emul',
      'eric' => 'eric',
      'ezwa' => 'ezwa',
      'fake' => 'fake',
      'fly-' => 'fly-',
      'fly_' => 'fly_',
      'g-mo' => 'g-mo',
      'g1 u' => 'g1 u',
      'g560' => 'g560',
      'gf-5' => 'gf-5',
      'grun' => 'grun',
      'gene' => 'gene',
      'go.w' => 'go.w',
      'good' => 'good',
      'grad' => 'grad',
      'hcit' => 'hcit',
      'hd-m' => 'hd-m',
      'hd-p' => 'hd-p',
      'hd-t' => 'hd-t',
      'hei-' => 'hei-',
      'hp i' => 'hp i',
      'hpip' => 'hpip',
      'hs-c' => 'hs-c',
      'htc ' => 'htc ',
      'htc-' => 'htc-',
      'htca' => 'htca',
      'htcg' => 'htcg',
      'htcp' => 'htcp',
      'htcs' => 'htcs',
      'htct' => 'htct',
      'htc_' => 'htc_',
      'haie' => 'haie',
      'hita' => 'hita',
      'huaw' => 'huaw',
      'hutc' => 'hutc',
      'i-20' => 'i-20',
      'i-go' => 'i-go',
      'i-ma' => 'i-ma',
      'i230' => 'i230',
      'iac' => 'iac',
      'iac-' => 'iac-',
      'iac/' => 'iac/',
      'ig01' => 'ig01',
      'im1k' => 'im1k',
      'inno' => 'inno',
      'iris' => 'iris',
      'jata' => 'jata',
      'java' => 'java',
      'kddi' => 'kddi',
      'kgt' => 'kgt',
      'kgt/' => 'kgt/',
      'kpt ' => 'kpt ',
      'kwc-' => 'kwc-',
      'klon' => 'klon',
      'lexi' => 'lexi',
      'lg g' => 'lg g',
      'lg-a' => 'lg-a',
      'lg-b' => 'lg-b',
      'lg-c' => 'lg-c',
      'lg-d' => 'lg-d',
      'lg-f' => 'lg-f',
      'lg-g' => 'lg-g',
      'lg-k' => 'lg-k',
      'lg-l' => 'lg-l',
      'lg-m' => 'lg-m',
      'lg-o' => 'lg-o',
      'lg-p' => 'lg-p',
      'lg-s' => 'lg-s',
      'lg-t' => 'lg-t',
      'lg-u' => 'lg-u',
      'lg-w' => 'lg-w',
      'lg/k' => 'lg/k',
      'lg/l' => 'lg/l',
      'lg/u' => 'lg/u',
      'lg50' => 'lg50',
      'lg54' => 'lg54',
      'lge-' => 'lge-',
      'lge/' => 'lge/',
      'lynx' => 'lynx',
      'leno' => 'leno',
      'm1-w' => 'm1-w',
      'm3ga' => 'm3ga',
      'm50/' => 'm50/',
      'maui' => 'maui',
      'mc01' => 'mc01',
      'mc21' => 'mc21',
      'mcca' => 'mcca',
      'medi' => 'medi',
      'meri' => 'meri',
      'mio8' => 'mio8',
      'mioa' => 'mioa',
      'mo01' => 'mo01',
      'mo02' => 'mo02',
      'mode' => 'mode',
      'modo' => 'modo',
      'mot ' => 'mot ',
      'mot-' => 'mot-',
      'mt50' => 'mt50',
      'mtp1' => 'mtp1',
      'mtv ' => 'mtv ',
      'mate' => 'mate',
      'maxo' => 'maxo',
      'merc' => 'merc',
      'mits' => 'mits',
      'mobi' => 'mobi',
      'motv' => 'motv',
      'mozz' => 'mozz',
      'n100' => 'n100',
      'n101' => 'n101',
      'n102' => 'n102',
      'n202' => 'n202',
      'n203' => 'n203',
      'n300' => 'n300',
      'n302' => 'n302',
      'n500' => 'n500',
      'n502' => 'n502',
      'n505' => 'n505',
      'n700' => 'n700',
      'n701' => 'n701',
      'n710' => 'n710',
      'nec-' => 'nec-',
      'nem-' => 'nem-',
      'newg' => 'newg',
      'neon' => 'neon',
      'netf' => 'netf',
      'noki' => 'noki',
      'nzph' => 'nzph',
      'o2 x' => 'o2 x',
      'o2-x' => 'o2-x',
      'opwv' => 'opwv',
      'owg1' => 'owg1',
      'opti' => 'opti',
      'oran' => 'oran',
      'p800' => 'p800',
      'pand' => 'pand',
      'pg-1' => 'pg-1',
      'pg-2' => 'pg-2',
      'pg-3' => 'pg-3',
      'pg-6' => 'pg-6',
      'pg-8' => 'pg-8',
      'pg-c' => 'pg-c',
      'pg13' => 'pg13',
      'phil' => 'phil',
      'pn-2' => 'pn-2',
      'ppc;' => 'ppc;',
      'pt-g' => 'pt-g',
      'palm' => 'palm',
      'pana' => 'pana',
      'pire' => 'pire',
      'pock' => 'pock',
      'pose' => 'pose',
      'psio' => 'psio',
      'qa-a' => 'qa-a',
      'qc-2' => 'qc-2',
      'qc-3' => 'qc-3',
      'qc-5' => 'qc-5',
      'qc-7' => 'qc-7',
      'qc07' => 'qc07',
      'qc12' => 'qc12',
      'qc21' => 'qc21',
      'qc32' => 'qc32',
      'qc60' => 'qc60',
      'qci-' => 'qci-',
      'qwap' => 'qwap',
      'qtek' => 'qtek',
      'r380' => 'r380',
      'r600' => 'r600',
      'raks' => 'raks',
      'rim9' => 'rim9',
      'rove' => 'rove',
      's55/' => 's55/',
      'sage' => 'sage',
      'sams' => 'sams',
      'sc01' => 'sc01',
      'sch-' => 'sch-',
      'scp-' => 'scp-',
      'sdk/' => 'sdk/',
      'se47' => 'se47',
      'sec-' => 'sec-',
      'sec0' => 'sec0',
      'sec1' => 'sec1',
      'semc' => 'semc',
      'sgh-' => 'sgh-',
      'shar' => 'shar',
      'sie-' => 'sie-',
      'sk-0' => 'sk-0',
      'sl45' => 'sl45',
      'slid' => 'slid',
      'smb3' => 'smb3',
      'smt5' => 'smt5',
      'sp01' => 'sp01',
      'sph-' => 'sph-',
      'spv ' => 'spv ',
      'spv-' => 'spv-',
      'sy01' => 'sy01',
      'samm' => 'samm',
      'sany' => 'sany',
      'sava' => 'sava',
      'scoo' => 'scoo',
      'send' => 'send',
      'siem' => 'siem',
      'smar' => 'smar',
      'smit' => 'smit',
      'soft' => 'soft',
      'sony' => 'sony',
      't-mo' => 't-mo',
      't218' => 't218',
      't250' => 't250',
      't600' => 't600',
      't610' => 't610',
      't618' => 't618',
      'tcl-' => 'tcl-',
      'tdg-' => 'tdg-',
      'telm' => 'telm',
      'tim-' => 'tim-',
      'ts70' => 'ts70',
      'tsm-' => 'tsm-',
      'tsm3' => 'tsm3',
      'tsm5' => 'tsm5',
      'tx-9' => 'tx-9',
      'tagt' => 'tagt',
      'talk' => 'talk',
      'teli' => 'teli',
      'topl' => 'topl',
      'tosh' => 'tosh',
      'up.b' => 'up.b',
      'upg1' => 'upg1',
      'utst' => 'utst',
      'v400' => 'v400',
      'v750' => 'v750',
      'veri' => 'veri',
      'vk-v' => 'vk-v',
      'vk40' => 'vk40',
      'vk50' => 'vk50',
      'vk52' => 'vk52',
      'vk53' => 'vk53',
      'vm40' => 'vm40',
      'vx98' => 'vx98',
      'virg' => 'virg',
      'vite' => 'vite',
      'voda' => 'voda',
      'vulc' => 'vulc',
      'wapj' => 'wapj',
      'wapp' => 'wapp',
      'wapu' => 'wapu',
      'wapm' => 'wapm',
      'wig ' => 'wig ',
      'wapi' => 'wapi',
      'wapr' => 'wapr',
      'wapv' => 'wapv',
      'wapy' => 'wapy',
      'wapa' => 'wapa',
      'waps' => 'waps',
      'wapt' => 'wapt',
      'winc' => 'winc',
      'winw' => 'winw',
      'wonu' => 'wonu',
      'x700' => 'x700',
      'xda2' => 'xda2',
      'xdag' => 'xdag',
      'yas-' => 'yas-',
      'your' => 'your',
      'zte-' => 'zte-',
      'zeto' => 'zeto',
      'acs-' => 'acs-',
      'alav' => 'alav',
      'alca' => 'alca',
      'amoi' => 'amoi',
      'aste' => 'aste',
      'audi' => 'audi',
      'avan' => 'avan',
      'benq' => 'benq',
      'bird' => 'bird',
      'blac' => 'blac',
      'blaz' => 'blaz',
      'brew' => 'brew',
      'brvw' => 'brvw',
      'bumb' => 'bumb',
      'ccwa' => 'ccwa',
      'cell' => 'cell',
      'cldc' => 'cldc',
      'cmd-' => 'cmd-',
      'dang' => 'dang',
      'doco' => 'doco',
      'eml2' => 'eml2',
      'eric' => 'eric',
      'fetc' => 'fetc',
      'hipt' => 'hipt',
      'http' => 'http',
      'ibro' => 'ibro',
      'idea' => 'idea',
      'ikom' => 'ikom',
      'inno' => 'inno',
      'ipaq' => 'ipaq',
      'jbro' => 'jbro',
      'jemu' => 'jemu',
      'java' => 'java',
      'jigs' => 'jigs',
      'kddi' => 'kddi',
      'keji' => 'keji',
      'kyoc' => 'kyoc',
      'kyok' => 'kyok',
      'leno' => 'leno',
      'lg-c' => 'lg-c',
      'lg-d' => 'lg-d',
      'lg-g' => 'lg-g',
      'lge-' => 'lge-',
      'libw' => 'libw',
      'm-cr' => 'm-cr',
      'maui' => 'maui',
      'maxo' => 'maxo',
      'midp' => 'midp',
      'mits' => 'mits',
      'mmef' => 'mmef',
      'mobi' => 'mobi',
      'mot-' => 'mot-',
      'moto' => 'moto',
      'mwbp' => 'mwbp',
      'mywa' => 'mywa',
      'nec-' => 'nec-',
      'newt' => 'newt',
      'nok6' => 'nok6',
      'noki' => 'noki',
      'o2im' => 'o2im',
      'opwv' => 'opwv',
      'palm' => 'palm',
      'pana' => 'pana',
      'pant' => 'pant',
      'pdxg' => 'pdxg',
      'phil' => 'phil',
      'play' => 'play',
      'pluc' => 'pluc',
      'port' => 'port',
      'prox' => 'prox',
      'qtek' => 'qtek',
      'qwap' => 'qwap',
      'rozo' => 'rozo',
      'sage' => 'sage',
      'sama' => 'sama',
      'sams' => 'sams',
      'sany' => 'sany',
      'sch-' => 'sch-',
      'sec-' => 'sec-',
      'send' => 'send',
      'seri' => 'seri',
      'sgh-' => 'sgh-',
      'shar' => 'shar',
      'sie-' => 'sie-',
      'siem' => 'siem',
      'smal' => 'smal',
      'smar' => 'smar',
      'sony' => 'sony',
      'sph-' => 'sph-',
      'symb' => 'symb',
      't-mo' => 't-mo',
      'teli' => 'teli',
      'tim-' => 'tim-',
      'tosh' => 'tosh',
      'treo' => 'treo',
      'tsm-' => 'tsm-',
      'upg1' => 'upg1',
      'upsi' => 'upsi',
      'vk-v' => 'vk-v',
      'voda' => 'voda',
      'vx52' => 'vx52',
      'vx53' => 'vx53',
      'vx60' => 'vx60',
      'vx61' => 'vx61',
      'vx70' => 'vx70',
      'vx80' => 'vx80',
      'vx81' => 'vx81',
      'vx83' => 'vx83',
      'vx85' => 'vx85',
      'wap-' => 'wap-',
      'wapa' => 'wapa',
      'wapi' => 'wapi',
      'wapp' => 'wapp',
      'wapr' => 'wapr',
      'webc' => 'webc',
      'whit' => 'whit',
      'winw' => 'winw',
      'wmlb' => 'wmlb',
      'xda-' => 'xda-',
    )):

      // check against a list of trimmed user agents to see if we find a match
      if (!ereg("w3c_css_validator", strtolower($user_agent))) {
        $mobile_browser = array(
          'type' => 'mobile',
          'group' => '',
        );

        // set mobile browser to TRUE
      }
      break;
  }

  // ends the switch
  $result = $mobile_browser;
  return $result;
}

/**
 *  Detection of the site type . the values comes out the configuration form.
 */
function mobile_tools_site_type() {
  $site_detection = variable_get('mobile-tools-site-type-detection', 'mobile_tools');
  drupal_load('module', $site_detection);
  if ($site_detection == 'mobile_tools') {
    return _mobile_tools_site_detection();
  }
  else {
    return module_invoke($site_detection, 'is_mobile_site');
  }
}

/**
 * Mobile Tools implementation to detect what site is being served now
 * @return
 *  desktop / mobile
 */
function _mobile_tools_site_detection() {
  global $base_url, $mobile_tools_device;

  // Easy detection in case redireciton is disabled and device specific theme switching is enabled
  if (!variable_get('mobile_tools_redirect', 0) && variable_get('mobile-tools-theme-switch', '') == 'mobile-tools-mobile-device') {
    if ($mobile_tools_device['type'] == 'mobile') {
      return 'mobile';
    }
    else {
      return 'desktop';
    }
  }

  // Check if $_SERVER variables are set if not, just return desktop... Still unclear what best solution is:
  if (!isset($_SERVER['HTTP_HOST']) && !isset($_SERVER['SERVER_NAME'])) {
    return 'desktop';
  }
  $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];

  // first check if the url is a m.* or .mobi url. This is robust
  $server_domain_elements = explode('.', $host);
  if (count($server_domain_elements) > 0) {
    if ($server_domain_elements[0] == 'm') {

      // check for m.* domain
      return 'mobile';
    }
    if ($server_domain_elements[count($server_domain_elements) - 1] == 'mobi') {

      // check for *.mobi
      return 'mobile';
    }
  }

  // If this doesn't return an answer, we will have to do a comparison of the mobile and desktop url!
  $mobile = variable_get('mobile_tools_mobile_url', mobile_tools_create_mobile_url($base_url));
  $mobile_url = parse_url($mobile);
  $mobile_url['host'] = mobile_tools_prepare_url($mobile_url['host']);
  $desktop = variable_get('mobile_tools_desktop_url', $base_url);
  $desktop_url = parse_url($desktop);
  $desktop_url['host'] = mobile_tools_prepare_url($desktop_url['host']);
  if (!array_key_exists('path', $desktop_url)) {
    $desktop_url['path'] = '';
  }
  if (!array_key_exists('path', $mobile_url)) {
    $mobile_url['path'] = '';
  }

  // If $_SERVER['HTTP_HOST'] is not set just return desktop
  if (!isset($_SERVER['HTTP_HOST'])) {
    return 'desktop';
  }
  $server_name = mobile_tools_prepare_url($_SERVER['HTTP_HOST']);

  // Check domain first
  if ($mobile_url['host'] == $server_name && $desktop_url['host'] != $server_name) {
    return 'mobile';
  }
  elseif ($mobile_url['host'] != $server_name && $desktop_url['host'] == $server_name) {
    return 'desktop';
  }

  // find longest url
  $longest_url = strlen($mobile) > strlen($desktop) ? $mobile : $desktop;
  $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
  $uri = $protocol . $_SERVER['HTTP_HOST'] . request_uri();
  $pos = strpos($uri, preg_replace('{/$}', '', $longest_url));
  if ($pos === FALSE) {
    return $longest_url == $mobile ? 'desktop' : 'mobile';
  }
  else {
    return $longest_url == $mobile ? 'mobile' : 'desktop';
  }
}

/**
 * Calling the device groups, check first if third party module registered
 * for doing the device detection
 * @return $groups
 *  Array containing the device group detected by this module
 */
function mobile_tools_device_groups() {
  $device_detection = variable_get('mobile-tools-device-detection', 'mobile_tools');
  drupal_load('module', $device_detection);
  if ($device_detection != 'mobile_tools') {
    return module_invoke($device_detection, 'device_groups');
  }
  else {
    return _mobile_tools_device_groups();
  }
}

/**
 *  Mobile Tools implementation of the hook_device_groups()
 *  This function returns the different device groups where this module can make a distinction for. This can be used
 *  to select different themes for different device groups.
 */
function _mobile_tools_device_groups() {
  return array(
    'iphone' => 'iPhone',
    'ipod' => 'iPod',
    'ipad' => 'iPad',
    'android' => 'Android',
    'opera_mini' => 'Opera Mini',
    'blackberry' => 'BlackBerry',
  );
}

/**
 * Implementation of hook_devicecapability()
 * This default implementation invokes the responsible module
 */
function mobile_tools_devicecapability($capability) {
  return module_invoke(variable_get('mobile-tools-device-capability', 'wurfl'), 'devicecapability', $capability);
}

/**
 *  This function does some kind of normalisation of the urls when there is no subdomain available in the url
 *  e.g. domain.com becomes www.domain.com . this is because sometimes both www.domain.com and domain.com are the same
 */
function mobile_tools_prepare_url($url) {
  $_url = parse_url($url);
  $_url = $url['host'];
  $_url = explode(".", $_url);
  if (count($_url) == 2) {
    return 'www' . implode(".", $_url);
  }
  else {
    return $url;
  }
}

/**
 * Creation of the redirect url. Special care to create the correct url that will
 * cause the Global Redirect module not to redirect!
 */
function mobile_tools_get_redirect_url($destination_site) {
  include_once './includes/bootstrap.inc';
  drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
  $destination_url = $destination_site == 'mobile' ? variable_get('mobile_tools_mobile_url', '') : ($destination = variable_get('mobile_tools_desktop_url', ''));

  // collect query parameters
  if (drupal_is_front_page()) {
    return $destination_url;
  }
  $query = array();
  foreach ($_GET as $key => $value) {
    if ($key != 'q') {
      $query[] = $key . '=' . $value;
    }
  }
  $query = count($query) > 0 ? implode('&', $query) : '';

  //create the path and reassemble
  $base = preg_replace('{/$}', '', $destination_url);
  $currentUrl = url($_GET['q'], array(
    'query' => $query,
  ));
  $currentPath = str_replace(base_path(), "/", $currentUrl);
  $url = $base . $currentPath;
  return $url;
}

/**
 * Helper function to assist in making a mobile url (m.*) from a given url
 *
 * @parm $url
 *  orginal url
 * @return
 *  the mobile url
 */
function mobile_tools_create_mobile_url($url) {
  $url_parsed = parse_url($url);
  if (!array_key_exists('path', $url_parsed)) {
    $url_parsed['path'] = "";
  }
  $url = $url_parsed['host'];
  $url = explode('.', $url);
  if (count($url) == 3) {
    $url[0] = 'm';
    return 'http://' . implode('.', $url) . $url_parsed['path'];
  }
  elseif (count($url) == 2) {
    return 'http://m.' . implode('.', $url) . $url_parsed['path'];
  }
  else {
    return 'http://' . implode('.', $url) . $url_parsed['path'] . '/mobile';
  }
}

/**
 * Alteration to global setting form
 */
function mobile_tools_form_alter(&$form, $form_state, $form_id) {
  switch ($form_id) {
    case 'node_configure':
      $form['default_nodes_main_mobile'] = array(
        '#type' => 'select',
        '#title' => t('Number of posts on main page for the mobile version'),
        '#default_value' => variable_get('default_nodes_main_mobile', variable_get('default_nodes_main', 10)),
        '#options' => array(
          1 => 1,
          2 => 2,
          3 => 3,
          4 => 4,
          5 => 5,
          6 => 6,
          7 => 7,
          8 => 8,
          9 => 9,
          10 => 10,
          15 => 15,
          20 => 20,
          25 => 25,
          30 => 30,
        ),
        '#description' => t('The default maximum number of posts to display per page on overview pages such as the main page (on Mobile).'),
      );
      break;
  }
}

/**
 * Implementation of hook_footer()
 *  - inserting some javascript to hide navigation bar
 */
function mobile_tools_footer() {
  $output = '';
  $site = mobile_tools_site_type();
  if (variable_get('mobile_tools_hide_address_bar', 1) && $site == 'mobile') {
    $output .= '<script type="text/javascript" charset="utf-8">';
    $output .= <<<EOF
    addEventListener('load', function() {
    \tsetTimeout(hideAddressBar, 0);
    }, false);
    function hideAddressBar() {
    \twindow.scrollTo(0, 1);
    }
EOF;
    $output .= '</script>';
  }
  return $output;
}
function mobile_tools_preprocess_page(&$vars) {
  $site = mobile_tools_site_type();
  if (variable_get('mobile_tools_add_header', 1) && $site == 'mobile') {
    $vars['head'] = $vars['head'] . theme('mobile_tools_header');
  }
}

/**
 * copy of drupal_goto, since this is called in hook_boot, while the function is not yet available
 */
function mobile_tools_goto($path = '', $query = NULL, $fragment = NULL, $http_response_code = 302) {
  $url = $path;

  // Make the given path or URL absolute
  if (!preg_match('/^[a-z]+:\\/\\//', $url)) {
    global $base_url;
    $url = $base_url . '/' . $url;
  }
  $url .= empty($query) ? '' : '?' . $query;
  $url .= empty($fragment) ? '' : '#' . $fragment;

  // Remove newlines from the URL to avoid header injection attacks.
  $url = str_replace(array(
    "\n",
    "\r",
  ), '', $url);

  // Before the redirect, allow modules to react to the end of the page request.
  bootstrap_invoke_all('exit');

  // Even though session_write_close() is registered as a shutdown function, we
  // need all session data written to the database before redirecting.
  session_write_close();
  header('Location: ' . $url, TRUE, $http_response_code);

  // The "Location" header sends a REDIRECT status code to the http
  // daemon. In some cases this can go wrong, so we make sure none
  // of the code below the drupal_goto() call gets executed when we redirect.
  exit;
}

/**
 * Implementation of hook_ctools_plugin_directory() to let the system know
 * we implement access plugins.
 */
function mobile_tools_ctools_plugin_directory($module, $plugin) {
  if ($plugin == 'access') {
    return 'plugins/' . $plugin;
  }
}

/**
 * Adding support for Node Displays build modes
 * See http://drupal.org/project/nd
 */

/**
* Implementation of hook_nodeapi
*/
function mobile_tools_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  if ($op == 'load' && mobile_tools_site_type() == 'mobile' && variable_get('mobile_tools_enable_build_mode', 0)) {
    $node->build_mode = 'mobile';
  }
}

/**
 * Implementation of hook_content_build_modes
 */
function mobile_tools_content_build_modes() {
  $groups = mobile_tools_device_groups();
  $modes = array();
  foreach ($groups as $group => $title) {
    $modes[$group] = array(
      'title' => $title,
      'views style' => TRUE,
    );
  }
  $build_modes = array();

  // Needs some more thought in combining groups and types. We need to detect which build mode takes the lead

  /*  $build_modes['mobile_tools_groups'] = array(
      'title' => 'Mobile Groups',
      'build modes' => $modes,
    );
  */
  $build_modes['mobile_tools_types'] = array(
    'title' => 'Mobile Device',
    'build modes' => array(
      'mobile' => array(
        'title' => 'Mobile',
        'views style' => TRUE,
      ),
    ),
  );
  return $build_modes;
}

/**
 * Implementation of hook_context_plugins
 * We create mobile contexts
 */
function mobile_tools_context_plugins() {
  $plugins = array();
  $plugins['mobile_tools_context_condition_mobile'] = array(
    'handler' => array(
      'path' => drupal_get_path('module', 'mobile_tools') . '/plugins',
      'file' => 'mobile_tools_context_condition_mobile.inc',
      'class' => 'mobile_tools_context_condition_mobile',
      'parent' => 'context_condition',
    ),
  );
  return $plugins;
}
function mobile_tools_context_registry() {
  return array(
    'conditions' => array(
      'mobile' => array(
        'title' => t('Context for mobile devices'),
        'plugin' => 'mobile_tools_context_condition_mobile',
        'description' => 'Choose for which device type or device group this context must apply',
      ),
    ),
  );
}

/**
 * Implementation of hook_views_api
 */
function mobile_tools_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'mobile_tools') . '/views',
  );
}

/**
 *  Views access check as used by the mobile access check for views
 */
function mobile_tools_views_check_access($device, $perms, $rids) {
  global $user;

  // first check device permission
  $current_device = mobile_tools_site_type();

  // general case of mobile site
  if ($device[$current_device]) {
    $access = TRUE;
  }
  else {
    return FALSE;
  }

  // Additional check
  if (!empty($perms)) {
    foreach ($perms as $perm) {
      $access = $access && user_access($perm);
    }
  }
  $account = isset($account) ? $account : $user;
  $roles = array_keys($account->roles);
  $roles[] = $account->uid ? DRUPAL_AUTHENTICATED_RID : DRUPAL_ANONYMOUS_RID;
  if ($rids) {
    $access = $access && (user_access('access all views', $account) || array_intersect(array_filter($rids), $roles));
  }
  return $access;
}

Functions

Namesort descending Description
mobile_tools_block Implementation of hook_block() Provides the blocks that can be used to show a message to the user to go to the mobile or desktop version.
mobile_tools_block_message Helper function returning the configurable message for the notification
mobile_tools_boot Implementation of hook_boot(). Redirecting if needed
mobile_tools_content_build_modes Implementation of hook_content_build_modes
mobile_tools_context_plugins Implementation of hook_context_plugins We create mobile contexts
mobile_tools_context_registry
mobile_tools_create_mobile_url Helper function to assist in making a mobile url (m.*) from a given url
mobile_tools_ctools_plugin_directory Implementation of hook_ctools_plugin_directory() to let the system know we implement access plugins.
mobile_tools_devicecapability Implementation of hook_devicecapability() This default implementation invokes the responsible module
mobile_tools_device_groups Calling the device groups, check first if third party module registered for doing the device detection
mobile_tools_device_redirect Being called in the hook_boot() implementation This function is in charge of redirection or displaying a notification
mobile_tools_footer Implementation of hook_footer()
mobile_tools_form_alter Alteration to global setting form
mobile_tools_get_device Get $device object. Check if the 'device' argument is present or a cookie is set to overwrite the device:
mobile_tools_get_redirect_url Creation of the redirect url. Special care to create the correct url that will cause the Global Redirect module not to redirect!
mobile_tools_goto copy of drupal_goto, since this is called in hook_boot, while the function is not yet available
mobile_tools_help Implementation of hook_help($section).
mobile_tools_init Theme switching:
mobile_tools_is_mobile_device Detect the device
mobile_tools_menu Implementation of hook_menu().
mobile_tools_menu_link_access Access function for the mobile tools menu links. It decides on which link to shown.
mobile_tools_menu_link_to_arg Implementation of %mobile_tools_menu_link
mobile_tools_menu_switch_site Redirect the user to the right path
mobile_tools_nodeapi Implementation of hook_nodeapi
mobile_tools_perm Implementation of hook_perm().
mobile_tools_prepare_url This function does some kind of normalisation of the urls when there is no subdomain available in the url e.g. domain.com becomes www.domain.com . this is because sometimes both www.domain.com and domain.com are the same
mobile_tools_preprocess_page
mobile_tools_site_type Detection of the site type . the values comes out the configuration form.
mobile_tools_switch_menu_link Create the url to go to the desktop/mobile version
mobile_tools_switch_theme Being called in the hook_boot() implementation This function is in charge of changing to the mobile theme
mobile_tools_theme Implementation of hook_theme()
mobile_tools_views_api Implementation of hook_views_api
mobile_tools_views_check_access Views access check as used by the mobile access check for views
_mobile_tools_device_groups Mobile Tools implementation of the hook_device_groups() This function returns the different device groups where this module can make a distinction for. This can be used to select different themes for different device groups.
_mobile_tools_is_mobile_device Default implementation of hook_is_mobile_device()
_mobile_tools_site_detection Mobile Tools implementation to detect what site is being served now

Constants