You are here

sms_track.module in SMS Framework 6

Message tracking feature module for Drupal SMS Framework.

@package sms @subpackage sms_track

File

modules/sms_track/sms_track.module
View source
<?php

/**
 * @file
 * Message tracking feature module for Drupal SMS Framework.
 *
 * @package sms
 * @subpackage sms_track
 */

/**
 * Implement hook_help()
 *
 * @param $path
 *   URI string
 * @param $arg
 *  Page argument array
 *
 * @return
 *   HTML page content string
 */
function sms_track_help($path, $arg) {
  switch ($path) {
    case "admin/help#sms_archive":
      $output = '<p>' . t("<i>TO BE RE-WRITTEN</i> This module simply records all incoming and outgoing SMS messages from the SMS Framework. This can be used to enable an audit trail for your system, so that you can investigate any issues and keen an eye on what is flowing in and out.<br /><br /><strong>Outgoing: </strong>It is important to be aware of your outgoing SMS traffic because user spamming can be expensive for you, and may also expose you to legal issues. A small code error can cause this kind of problem.<br /><br /><strong>Incoming: </strong>The proper handling of inbound messages depends heavily on the quality of your software code. You may find that someone is sending malformed messages to your gateway receiver, which could expose a vulnerability and potentially release sensitive data.<br /><br />This module uses a database table to store messages, and implements Views for reporting.") . '</p>';
      break;
  }
  return $output;
}

/**
 * Implement hook_enable()
 */
function sms_track_enable() {
  if (variable_get('sms_track_archive_dir', SMS_DIR_NONE)) {
    watchdog('sms_track', 'SMS Tracking archive collector enabled');
  }
}

/**
 * Implement hook_disable()
 */
function sms_track_disable() {
  if (variable_get('sms_track_archive_dir', SMS_DIR_NONE)) {
    watchdog('sms_track', 'SMS Tracking archive collector DISABLED');
  }
}

/**
 * Implement hook_cron()
 */
function sms_track_cron() {

  // Ensure that we only run at most once per hour
  $last_run = variable_get('sms_track_archive_cron_last_run', 0);
  $time_an_hour_ago = time() - 3600;
  if ($last_run <= $time_an_hour_ago) {

    // Purge the archive
    sms_track_archive_purge();
    variable_set('sms_track_archive_cron_last_run', time());
  }
}

/**
 * Implement hook_menu()
 *
 * @return
 *   Drupal menu items array
 */
function sms_track_menu() {
  $items = array();
  $items['admin/smsframework/sms_track'] = array(
    'title' => 'Message tracking',
    'description' => 'Options and view for the message archive.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'sms_track_settings_form',
    ),
    'access arguments' => array(
      'administer smsframework',
    ),
    'file' => 'sms_track.admin.inc',
  );
  $items['admin/smsframework/sms_track/settings'] = array(
    'title' => 'Settings',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => 0,
  );
  $items['admin/smsframework/sms_track/view'] = array(
    'title' => 'View the archive',
    'file' => 'sms_track.admin.inc',
    'page callback' => 'sms_track_admin_view',
    'access arguments' => array(
      'administer smsframework',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
    'file' => 'sms_track.admin.inc',
  );
  return $items;
}

/**
 * Implement hook_sms_send()
 */
function sms_track_sms_send($number, $message, &$options, $gateway) {

  // Tracking
  // Place a tracking reference on a sent message if we need to
  if (!array_key_exists('reference', $options)) {
    $options['reference'] = md5($number . $message);
  }
}

/**
 * Implement hook_sms_send_process()
 *
 * @param $op
 *   Operation string (pre process, process, post process)
 * @param $number
 *   MSISDN of recipient
 * @param $message
 *   SMS message body string
 * @param $options
 *   Additional options array including sender
 * @param $gateway
 *   Gateway array for the active gateway
 * @param $result
 *   Result array from the gateway response handler
 */
function sms_track_sms_send_process($op, $number, $message, $options, $gateway, $result) {
  if ($op == 'post process') {

    // Archiving
    $dir = 0;

    // outgoing
    $options['gateway_id'] = $gateway['identifier'];
    $options['result'] = $result;
    $result = sms_track_archive_write($dir, $number, $message, $options);
  }
}

/**
 * Implement hook_sms_incoming()
 *
 * @param $op
 *   SMS incoming operation string (pre process, process, post process)
 * @param $number
 *   MSISDN of sender
 * @param $message
 *   SMS message body string
 * @param $options
 *   Additional options array including receiver MSISDN
 */
function sms_track_sms_incoming($op, $number, $message, $options) {
  if ($op == 'pre process') {

    // Archiving
    $dir = 1;

    // incoming
    sms_track_archive_write($dir, $number, $message, $options);
  }
}

/**
 * Implement hook_sms_receipt()
 *
 * @param $op
 *   Operation string
 * @param $number
 *   MSISDN
 * @param $reference
 *   Reference code of the message
 * @param $message_status
 *   Message status code. See sms constants
 * @param $options
 *   Additional options array
 */
function sms_track_sms_receipt($op, $number, $reference, $status, $options) {
  if ($op == 'pre process') {

    // Tracking
    sms_track_update_message($reference, $status);
  }
}

/**
 * Write a record to the DB table
 *
 * @param $direction
 *   Direction integer of message (0=outgoing, 1=incoming)
 * @param $number
 *   MSISDN of remote
 * @param $message
 *   SMS message body string
 * @param $options
 *   Array of additional options
 * @return
 *   DB Query result
 */
function sms_track_archive_write($dir, $number, $message, $options = array()) {
  $archive_dir = variable_get('sms_track_archive_dir', SMS_DIR_NONE);
  if ($dir == 0) {

    // Outgoing
    if ($archive_dir == SMS_DIR_ALL || $archive_dir == SMS_DIR_OUT) {
      $reference = array_key_exists('reference', $options) ? $options['reference'] : NULL;

      // Status code may be provided by send result handler
      $status = is_array($options['result']) ? $options['result']['status_code'] : NULL;

      // Or render a status code from a simple true/false result
      if (!$status) {
        if ($options['result']) {
          $status = SWS_GW_OK;
        }
        else {
          $status = SMS_GW_ERR_OTHER;
        }
      }
    }
    else {
      return;
    }
  }
  elseif ($dir == 1) {

    // Incoming
    if ($archive_dir == SMS_DIR_ALL || $archive_dir == SMS_DIR_IN) {
      $reference = NULL;

      // Inbound message status is always the same
      $status = SMS_MSG_STATUS_OK;
    }
    else {
      return;
    }
  }
  $gw_number = array_key_exists('gw_number', $options) ? $options['gw_number'] : NULL;
  $created = time();
  $options_z = serialize($options);
  $result = db_query("INSERT INTO {sms_track} (reference, dir, number,\n    gw_number, message, status, created, options) VALUES\n    ('%s', %d, '%s', '%s', '%s', %d, %d, '%s')", $reference, $dir, $number, $gw_number, $message, $status, $created, $options_z);
  if (!$result) {
    $to_from = $dir == 0 ? 'To' : 'From';
    watchdog('sms_track', 'Failed to record message: ' . $to_from . ' ' . $number . ': ' . $message);
  }
}

/**
 * Update a message with a new status code
 *
 * @param $reference
 *   Message reference code
 * @param $status
 *   Message status code. See sms constants
 *
 * @todo Log record handling
 */
function sms_track_update_message($reference, $status) {
  $updated = time();
  watchdog('sms_track', $reference . ' ' . $status . ' ' . $updated);
  $result = db_query('UPDATE {sms_track} SET status = %d, updated = %d WHERE reference = \'%s\'', $status, $updated, $reference);
  if ($result) {
    watchdog('sms_track', 'Affected rows: ' . db_affected_rows($result));
  }
}

/**
 * Implement hook_views_api()
 *
 * @return
 *   Views API required information array
 */
function sms_track_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'sms_track') . '/views',
  );
}

/**
 * Purge all archived messages after a certain number of days
 *
 * @param $max_age_days
 *   Maximum age of tracked messages in days
 */
function sms_track_archive_purge($max_age_days = NULL) {

  // Get the configured max_age from the variable table if not given
  if (is_null($max_age_days)) {
    $max_age_days = variable_get('sms_track_archive_max_age_days', 0);
  }

  // Purge with no survivors
  if ($max_age_days > 0) {
    $max_age_secs = $max_age_days * 86400;
    $oldest = time() - $max_age_secs;
    $result = db_query("DELETE FROM {sms_track} WHERE created < %d", $oldest);
  }
}

Functions

Namesort descending Description
sms_track_archive_purge Purge all archived messages after a certain number of days
sms_track_archive_write Write a record to the DB table
sms_track_cron Implement hook_cron()
sms_track_disable Implement hook_disable()
sms_track_enable Implement hook_enable()
sms_track_help Implement hook_help()
sms_track_menu Implement hook_menu()
sms_track_sms_incoming Implement hook_sms_incoming()
sms_track_sms_receipt Implement hook_sms_receipt()
sms_track_sms_send Implement hook_sms_send()
sms_track_sms_send_process Implement hook_sms_send_process()
sms_track_update_message Update a message with a new status code
sms_track_views_api Implement hook_views_api()