You are here

sms.module in SMS Framework 6.2

The core of the SMS Framework. Provides gateway managment and API for sending and receiving SMS messages.

File

sms.module
View source
<?php

/**
 * @file
 * The core of the SMS Framework. Provides gateway managment and API for
 * sending and receiving SMS messages.
 */

// Direction codes
define('SMS_DIR_NONE', 0);
define('SMS_DIR_OUT', 1);
define('SMS_DIR_IN', 2);
define('SMS_DIR_ALL', 4);

// Message status codes
// 0=Unknown, 2xx=Positive, 3xx=Positive/Neutral (context-dependent), 4xx=Negative
define('SMS_MSG_STATUS_UNKNOWN', 0);
define('SMS_MSG_STATUS_OK', 200);
define('SMS_MSG_STATUS_DELIVERED', 202);
define('SMS_MSG_STATUS_QUEUED', 302);
define('SMS_MSG_STATUS_ERROR', 400);
define('SMS_MSG_STATUS_NOCREDIT', 402);
define('SMS_MSG_STATUS_EXPIRED', 408);

// Gateway response codes
// 0=Unknown, 2xx=Positive, 4xx=Negative(likely client err), 5xx=Negative(likely gateway err)
define('SMS_GW_UNKNOWN_STATUS', 0);
define('SMS_GW_OK', 200);
define('SMS_GW_ERR_AUTH', 401);
define('SMS_GW_ERR_INVALID_CALL', 400);
define('SMS_GW_ERR_NOT_FOUND', 404);
define('SMS_GW_ERR_MSG_LIMITS', 413);
define('SMS_GW_ERR_MSG_ROUTING', 502);
define('SMS_GW_ERR_MSG_QUEUING', 408);
define('SMS_GW_ERR_MSG_OTHER', 409);
define('SMS_GW_ERR_SRC_NUMBER', 415);
define('SMS_GW_ERR_DEST_NUMBER', 416);
define('SMS_GW_ERR_CREDIT', 402);
define('SMS_GW_ERR_OTHER', 500);

//
define('SMS_CARRIER_DEFAULT', 0);
define('SMS_CARRIER_OVERRIDDEN', 1);
define('SMS_CARRIER_NORMAL', 3);

/**
 * Implements hook_menu().
 */
function sms_menu() {
  $items = array();
  $items['admin/smsframework'] = array(
    'title' => 'SMS Framework',
    'description' => 'Control how your site uses SMS.',
    'position' => 'right',
    'page callback' => 'system_admin_menu_block_page',
    'access arguments' => array(
      'administer smsframework',
    ),
    'file' => 'system.admin.inc',
    'file path' => drupal_get_path('module', 'system'),
  );
  $items['admin/smsframework/gateways'] = array(
    'title' => 'Gateway configuration',
    'description' => 'Configure gateways and chose the default gateway.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'sms_admin_default_form',
      NULL,
    ),
    'access arguments' => array(
      'administer smsframework',
    ),
    'file' => 'sms.admin.inc',
  );
  $items['admin/smsframework/gateways/%'] = array(
    'title callback' => 'sms_admin_gateway_title',
    'title arguments' => array(
      3,
    ),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'sms_admin_gateway_form',
      3,
    ),
    'access arguments' => array(
      'administer smsframework',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'sms.admin.inc',
  );
  $items['admin/smsframework/carriers'] = array(
    'title' => 'Carrier configuration',
    'description' => 'Configure supported carriers.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'sms_carriers_admin_form',
    ),
    'access arguments' => array(
      'administer smsframework',
    ),
    'file' => 'sms.admin.inc',
  );
  $items['admin/smsframework/carriers/manage'] = array(
    'title' => 'Manage',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -10,
  );
  $items['admin/smsframework/carriers/add'] = array(
    'title' => 'Add',
    'description' => 'Configure supported carriers.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'sms_carriers_edit_form',
    ),
    'access arguments' => array(
      'administer smsframework',
    ),
    'file' => 'sms.admin.inc',
    'type' => MENU_LOCAL_TASK,
  );
  $items['admin/smsframework/carriers/%carrier'] = array(
    'title' => 'Edit carrier',
    'description' => 'Configure supported carriers.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'sms_carriers_edit_form',
      3,
    ),
    'access arguments' => array(
      'administer smsframework',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'sms.admin.inc',
  );
  $items['admin/smsframework/carriers/delete/%carrier'] = array(
    'title' => 'Edit carrier',
    'description' => 'Configure supported carriers.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'sms_carriers_delete_form',
      4,
    ),
    'access arguments' => array(
      'administer smsframework',
    ),
    'type' => MENU_CALLBACK,
    'file' => 'sms.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_perm().
 */
function sms_perm() {
  return array(
    'administer smsframework',
  );
}

/**
 * Implements hook_theme().
 */
function sms_theme() {
  $items['sms_admin_default_form'] = $items['sms_carriers_admin_form'] = array(
    'arguments' => array(
      'form' => NULL,
    ),
    'file' => 'sms.admin.inc',
  );
  return $items;
}

/**
 * Sends a message using the active gateway.
 *
 * @param $number
 *   The destination number.
 *
 * @param $message
 *   The text of the messsage to send.
 *
 * @param $options
 *   An array of dditional properties as defined by gateway modules.
 */
function sms_send($number, $message, $options = array()) {
  $gateway = sms_default_gateway();
  foreach (module_implements('sms_send') as $module) {
    $function = $module . '_sms_send';
    $function($number, $message, $options, $gateway);
  }
  $response = NULL;
  if (function_exists($gateway['send'])) {
    $response = $gateway['send']($number, $message, $options);
  }
  $result = sms_handle_result($response, $number, $message);

  // Post process hook
  foreach (module_implements('sms_send_process') as $module) {
    $function = $module . '_sms_send_process';
    $function('post process', $number, $message, $options, $gateway, $result);
  }
  return $result;
}

/**
 * Handle the response back from the sms gateway.
 */
function sms_handle_result($result, $number, $message) {
  if ($result['status']) {
    return TRUE;
  }
  else {
    $error_message = 'Sending SMS to %number failed.';
    $variables['%number'] = $number;
    if ($result['message']) {
      $error_message .= ' The gateway said ' . $result['message'];
      if (!empty($result['variables'])) {
        $variables = array_merge($variables, $result['variables']);
      }
    }
    watchdog('sms', $error_message, $variables, WATCHDOG_ERROR);
    return FALSE;
  }
}

/**
 * Callback for incoming messages. Allows gateways modules to pass messages in
 * a standard format for processing.
 *
 * @param $number
 *   The sender's mobile number.
 *
 * @param $message
 *   The content of the text message.
 */
function sms_incoming($number, $message, $options = array()) {
  if (module_exists('rules')) {
    rules_invoke_event('sms_incoming', $number, $message);
  }

  // Execute three phases
  module_invoke_all('sms_incoming', 'pre process', $number, $message, $options);
  module_invoke_all('sms_incoming', 'process', $number, $message, $options);
  module_invoke_all('sms_incoming', 'post process', $number, $message, $options);
}

/**
 * Callback for incoming message receipts. Allows gateways modules to pass
 * message receipts in a standard format for processing, and provides a basic
 * set of status codes for common code handling.
 *
 * Allowed message status codes are defined as constants at the top of this module.
 *
 * The gateway code and string will often be provided in the $options array as
 * 'gateway_message_status' and 'gateway_message_status_text'.
 *
 * @param string $number
 * The sender's mobile number.
 *
 * @param string $reference
 * Unique message reference code, as provided when message is sent.
 *
 * @param string $message_status
 * An SMS Framework message status code, as per the defined constants.
 *
 * @param array $options
 * Extended options passed by the receipt receiver.
 */
function sms_receipt($number, $reference, $message_status = SMS_GW_UNKNOWN_STATUS, $options = array()) {

  // Execute three phases
  module_invoke_all('sms_receipt', 'pre process', $number, $reference, $message_status, $options);
  module_invoke_all('sms_receipt', 'process', $number, $reference, $message_status, $options);
  module_invoke_all('sms_receipt', 'post process', $number, $reference, $message_status, $options);
}

/**
 * Returns the current default gateway.
 */
function sms_default_gateway() {
  return sms_gateways('gateway', variable_get('sms_default_gateway', 'log'));
}

/**
 * Implements hook_gateway_info().
 */
function sms_gateway_info() {
  return array(
    'log' => array(
      'name' => t('Log only'),
      'send' => 'sms_send_log',
    ),
  );
}

/**
 * Log sms message.
 *
 * @param $number
 *   Mobile numbers message sent to.
 * @param $message
 *   Message sent.
 * @param $options
 *   Associative array of options passed to gateway.
 */
function sms_send_log($number, $message, $options) {
  watchdog('sms', 'SMS message sent to %number with the text: @message', array(
    '%number' => $number,
    '@message' => $message,
  ), WATCHDOG_INFO);
  return array(
    'status' => TRUE,
  );
}

/**
 * SMS gateway menutitle callback.
 */
function sms_admin_gateway_title($gateway_id) {
  $gateway = sms_gateways('gateway', $gateway_id);
  return sprintf('%s gateway', $gateway['name']);
}

/**
 * Get a list of all gateways
 *
 * @param $op
 *   The format in which to return the list. When set to 'gateway' or 'name',
 *   only the specified gateway is returned. When set to 'gateways' or 'names',
 *   all gateways are returned.
 *
 * @param $gateway
 *   A gateway identifier string that indicates the gateway to return. Leave at default
 *   value (NULL) to return all gateways.
 *
 * @return
 *   Either an array of all gateways or a single gateway, in a variable format.
 */
function sms_gateways($op = 'gateways', $gateway = NULL) {
  list($_gateways, $_names) = _gateways_build();
  switch ($op) {
    case 'gateways':
      return $_gateways;
    case 'gateway':
      $return = $_gateways[$gateway];
      $return['identifier'] = $gateway;
      return $return;
    case 'names':
      return $_names;
    case 'name':
      return $_names[$gateway];
  }
}
function _gateways_build() {
  $_gateways = array();
  $_names = array();
  $gateway_array = module_invoke_all('gateway_info');
  foreach ($gateway_array as $identifier => $info) {
    $info['configuration'] = variable_get('sms_' . $identifier . '_settings', '');
    $_gateways[$identifier] = $info;
    $_names[$identifier] = $info['name'];
  }
  asort($_names);
  return array(
    $_gateways,
    $_names,
  );
}

/**
 * Form builder for send sms form.
 *
 * Generates a SMS sending form and adds gateway defined elements. The form
 * array that is returned can be merged with an existing form using
 * array_merge().
 *
 * @param $required
 *   Specify if the user is required to provide information for the fields.
 *
 * @see sms_send_form_submit_validate().
 * @see sms_send_form_submit_submit().
 */
function sms_send_form($required = FALSE) {
  $gateway = sms_default_gateway();
  $form['number'] = array(
    '#type' => 'textfield',
    '#title' => t('Phone number'),
    '#size' => 40,
    '#maxlength' => 255,
    '#required' => $required,
  );

  // Add gateway defined fields
  if (function_exists($gateway['send form'])) {
    $form['gateway']['#tree'] = TRUE;
    $form['gateway'] = array_merge($gateway['send form']($required), $form['gateway']);
  }
  return $form;
}

/**
 * Form validation handler for sms_send_form().
 *
 * @see sms_send_form().
 * @see sms_send_form_submit().
 */
function sms_send_form_validate($form, &$form_state) {
  if (!sms_validate_number(sms_formatter($form_state['values']['number']), $form_state['values']['gateway'])) {
    form_set_error('number', t('You must enter a valid phone number.'));
  }
}

/**
 * Form submission handler for sms_send_form().
 *
 * @see sms_send_form().
 * @see sms_send_form_validate().
 */
function sms_send_form_submit($form, &$form_state) {
  $form_state['values']['number'] = sms_formatter($form_state['values']['number']);
  sms_send($form_state['values']['number'], $form_state['values']['message'], $form_state['values']['gateway']);
}

/******************************************************************************
 * SMS Carrier Functions
 *
 * @todo - consider moving this to email gateway, unless there is a reason to
 * have these functions without the email gateway?
 *****************************************************************************/

/**
 * Get a list of all carriers
 */
function sms_carriers($domain = NULL) {
  $default_carriers = module_invoke_all('sms_carriers');
  $enabled_carriers = variable_get('sms_enabled_carriers', array());

  // Load default carriers from code
  foreach ($default_carriers as $id => $carrier) {
    $carriers[$id] = array(
      'name' => $carrier,
      'type' => SMS_CARRIER_DEFAULT,
    );
  }

  // Load overrideen carriers from database
  $result = db_query("SELECT name, domain FROM {sms_carriers}");
  while ($carrier = db_fetch_array($result)) {
    if (in_array($carrier['domain'], array_keys($carriers))) {
      $type = SMS_CARRIER_OVERRIDDEN;
    }
    else {
      $type = SMS_CARRIER_NORMAL;
    }
    $carriers[$carrier['domain']] = array(
      'name' => $carrier['name'],
      'type' => $type,
    );
  }
  foreach ($enabled_carriers as $carrier) {
    if (is_array($carriers[$carrier])) {
      $carriers[$carrier]['status'] = 1;
    }
  }
  if ($domain) {
    $carriers[$domain]['domain'] = $domain;
    return $carriers[$domain];
  }
  return $carriers;
}

/**
 * Load a single carrier
 */
function carrier_load($domain) {
  return sms_carriers($domain);
}

/**
 * Save a carrier.
 */
function carrier_save($domain, $edit) {
  if (!empty($domain)) {
    $carrier = carrier_load($domain);
    if ($carrier['type'] == SMS_CARRIER_DEFAULT) {
      $edit['status'] = 1;
      drupal_write_record('sms_carriers', $edit);
    }
    else {
      if (!empty($edit['domain'])) {
        drupal_write_record('sms_carriers', $edit, 'domain');

        // TODO: we need more logic to figure out when someone is changing the domain name
      }
    }
  }
  else {
    $edit['status'] = 1;
    drupal_write_record('sms_carriers', $edit);
  }
}

/**
 * Implements hook_sms_carriers()
 */
function sms_sms_carriers() {
  return array(
    'sms.3rivers.net' => t('3 River Wireless'),
    'airtelkk.com' => t('Airtel (Karnataka, India)'),
    'msg.acsalaska.com' => t('Alaska Communications Systems'),
    'message.alltel.com' => t('Alltel Wireless'),
    'txt.att.net' => t('AT&T/Cingular'),
    'txt.bell.ca' => t('Bell Mobility (Canada)'),
    'myboostmobile.com' => t('Boost Mobile'),
    'mobile.celloneusa.com' => t('Cellular One (Dobson)'),
    'south1.com' => t('Cellular South'),
    'cwemail.com' => t('Centennial Wireless'),
    '139.com' => t('ChinaMobile (139)'),
    'gocbw.com' => t('Cincinnati Bell Wireless'),
    'cingularme.com' => t('Cingular (GoPhone prepaid/7-11 Speakout)'),
    'ideasclaro-ca.com' => t('Claro (Nicaragua)'),
    'mms.claro.com.uy' => t('Claro (Uruguay)'),
    'comcel.com.co' => t('Comcel'),
    'sms.mycricket.com' => t('Cricket'),
    'sms.ctimovil.com.ar' => t('CTI'),
    'emtelworld.net' => t('Emtel (Mauritius)'),
    'smsmail.eplus.de' => t('E-Plus'),
    'fido.ca' => t('Fido (Canada)'),
    'msg.gci.net' => t('General Communications Inc.'),
    'msg.globalstarusa.com' => t('Globalstar'),
    'myhelio.com' => t('Helio'),
    'ivctext.com' => t('Illinois Valley Cellular'),
    'sms.mymeteor.ie' => t('Meteor (Ireland)'),
    'sms.spicenepal.com' => t('Mero Mobile (Nepal)'),
    'mymetropcs.com' => t('MetroPCS'),
    'mobilinkworld.com' => t('Mobilink World'),
    'sms.mobitel.lk' => t('Mobitel (Sri Lanka)'),
    'movimensaje.com.ar' => t('Movicom'),
    'movistar.com.co' => t('Movistar (Colombia)'),
    'sms.co.za' => t('MTN (South Africa)'),
    'text.mtsmobility.com' => t('MTS (Canada)'),
    'nextel.net.ar' => t('Nextel (Argentina)'),
    'orange.fr' => t('Orange (France)'),
    'orange.pl' => t('Orange (Poland)'),
    'orange.net' => t('Orange (UK)'),
    'personal-net.com.ar' => t('Personal (Argentina)'),
    'text.plusgsm.pl' => t('Plus GSM (Poland)'),
    'qwestmp.com' => t('Qwest'),
    'pcs.rogers.com' => t('Rogers (Canada)'),
    'sms.sasktel.com' => t('Sasktel (Canada)'),
    'mas.aw' => t('Setar Mobile email (Aruba)'),
    'page.nextel.com' => t('Sprint (Nextel)'),
    'messaging.sprintpcs.com' => t('Sprint (PCS)'),
    'tms.suncom.com' => t('Suncom'),
    'tmomail.net' => t('T-Mobile'),
    'sms.t-mobile.at' => t('T-Mobile (Austria)'),
    't-mobile-sms.de' => t('T-Mobile Germany'),
    'msg.telus.com' => t('Telus Mobility (Canada)'),
    'sms.thumbcellular.com' => t('Thumb Cellular'),
    'sms.tigo.com.co' => t('Tigo (Formerly Ola)'),
    'utext.com' => t('Unicel'),
    'email.uscc.net' => t('US Cellular'),
    'vtext.com' => t('Verizon'),
    'vmobile.ca' => t('Virgin Mobile (Canada)'),
    'vmobl.com' => t('Virgin Mobile'),
    'vodafone-sms.de' => t('Vodafone Germany'),
    'sms.ycc.ru' => t('YCC'),
    'vmpix.com' => t('Virgin Mobile'),
  );
}

/******************************************************************************
 * HELPER FUNCTIONS
 *****************************************************************************/

/**
 * Formats a number for display.
 */
function sms_format_number(&$number, $options = array()) {
  $gateway = sms_default_gateway();
  if ($gateway['format number'] && function_exists($gateway['format number'])) {
    return $gateway['format number']($number, $options);
  }
  else {
    return $number;
  }
}

/**
 * Converts various sms formats into a common format for use in this module.
 *
 * @param $number
 *   The sms number
 * @param $format
 *   Undefined - @todo: decide if this is needed.
 */
function sms_formatter($number, $format = 1) {

  // Remove non-number characters
  $number = preg_replace("/[^0-9]/", '', $number);

  /*
  @todo - the only length specification in the international numbering plan is that
  numbers should be a maximum of 15 digits.

  http://en.wikipedia.org/wiki/E.164

  if (strlen($number) > 16) {
    if ($number[0] == 1) {
      $number = ltrim($number, 1);
    }
    else {
      return FALSE;
    }
  }
  elseif (strlen($number) < 10) {
    return FALSE;
  }
  */
  return $number;
}

/**
 * Validates a phone number. Passes number to active gateway for further
 * validation if neccessary.
 */
function sms_validate_number(&$number, $options = array()) {
  if (!strlen($number)) {
    return t('The phone number is invalid.');
  }

  // Allow the active gateway to provide number validation
  $gateway = sms_default_gateway();
  if (function_exists($gateway['validate number']) && ($error = $gateway['validate number']($number, $options))) {
    return $error;
  }
}

/**
 * Render a direction code
 *
 * @param $out bool Outgoing allowed or not
 * @param $in  bool Incoming allowed or not
 * @return const The constant that defines this direction combination. Usually an integer value.
 */
function sms_dir($out, $in) {
  if ($out && $in) {
    return SMS_DIR_ALL;
  }
  if ($out && !$in) {
    return SMS_DIR_OUT;
  }
  if (!$out && $in) {
    return SMS_DIR_IN;
  }
  if (!$out && !$in) {
    return SMS_DIR_NONE;
  }
}

/**
 * Returns an array of E.164 international country calling codes
 *
 * @return array Associative array of country calling codes and country names.
 */
function sms_country_codes() {
  return array(
    93 => "Afghanistan",
    355 => "Albania",
    213 => "Algeria",
    376 => "Andorra",
    244 => "Angola",
    1264 => "Anguilla",
    1268 => "Antigua & Barbuda",
    54 => "Argentina",
    374 => "Armenia",
    297 => "Aruba",
    61 => "Australia",
    43 => "Austria",
    994 => "Azerbaijan",
    1242 => "Bahamas",
    973 => "Bahrain",
    880 => "Bangladesh",
    1246 => "Barbados",
    375 => "Belarus",
    32 => "Belgium",
    501 => "Belize",
    229 => "Benin",
    1441 => "Bermuda",
    975 => "Bhutan",
    591 => "Bolivia",
    387 => "Bosnia-Herzegovina",
    267 => "Botswana",
    55 => "Brazil",
    1284 => "British Virgin Islands",
    673 => "Brunei",
    359 => "Bulgaria",
    226 => "Burkina Faso",
    257 => "Burundi",
    855 => "Cambodia",
    237 => "Cameroon",
    34 => "Canary Islands",
    238 => "Cape Verde",
    1345 => "Cayman Islands",
    236 => "Central African Republic",
    235 => "Chad",
    56 => "Chile",
    86 => "China",
    57 => "Colombia",
    269 => "Comoros",
    242 => "Congo",
    243 => "Democratic Republic Congo",
    682 => "Cook Islands",
    385 => "Croatia",
    53 => "Cuba",
    357 => "Cyprus",
    420 => "Czech Republic",
    45 => "Denmark",
    253 => "Djibouti",
    1767 => "Dominica",
    670 => "East Timor",
    593 => "Ecuador",
    20 => "Egypt",
    503 => "El Salvador",
    240 => "Equatorial Guinea",
    372 => "Estonia",
    251 => "Ethiopia",
    500 => "Falkland Islands",
    298 => "Faroe Islands",
    679 => "Fiji",
    358 => "Finland",
    33 => "France",
    594 => "French Guiana",
    689 => "French Polynesia",
    241 => "Gabon",
    220 => "Gambia",
    995 => "Georgia",
    49 => "Germany",
    233 => "Ghana",
    350 => "Gibraltar",
    881 => "Global Mobile Satellite",
    30 => "Greece",
    299 => "Greenland",
    1473 => "Grenada",
    590 => "Guadeloupe",
    1671 => "Guam",
    502 => "Guatemala",
    224 => "Guinea",
    592 => "Guyana",
    509 => "Haiti",
    504 => "Honduras",
    852 => "HongKong",
    36 => "Hungary",
    354 => "Iceland",
    91 => "India",
    62 => "Indonesia",
    98 => "Iran",
    964 => "Iraq",
    353 => "Ireland",
    972 => "Israel",
    39 => "Italy / Vatican City State",
    225 => "Ivory Coast",
    1876 => "Jamaica",
    81 => "Japan",
    962 => "Jordan",
    254 => "Kenya",
    82 => "Korea (South)",
    965 => "Kuwait",
    996 => "Kyrgyzstan",
    856 => "Lao",
    371 => "Latvia",
    961 => "Lebanon",
    266 => "Lesotho",
    231 => "Liberia",
    218 => "Libya",
    423 => "Liechtenstein",
    370 => "Lithuania",
    352 => "Luxembourg",
    853 => "Macau",
    389 => "Macedonia",
    261 => "Madagascar",
    265 => "Malawi",
    60 => "Malaysia",
    960 => "Maldives",
    223 => "Mali",
    356 => "Malta",
    596 => "Martinique",
    222 => "Mauritania",
    230 => "Mauritius",
    269 => "Mayotte Island (Comoros)",
    52 => "Mexico",
    373 => "Moldova",
    377 => "Monaco (Kosovo)",
    976 => "Mongolia",
    382 => "Montenegro",
    1664 => "Montserrat",
    212 => "Morocco",
    258 => "Mozambique",
    95 => "Myanmar",
    264 => "Namibia",
    977 => "Nepal",
    31 => "Netherlands",
    599 => "Netherlands Antilles",
    687 => "New Caledonia",
    64 => "New Zealand",
    505 => "Nicaragua",
    227 => "Niger",
    234 => "Nigeria",
    47 => "Norway",
    968 => "Oman",
    92 => "Pakistan",
    970 => "Palestine (+970)",
    9725 => "Palestine (+9725)",
    507 => "Panama",
    675 => "Papua New Guinea",
    595 => "Paraguay",
    51 => "Peru",
    63 => "Philippines",
    48 => "Poland",
    351 => "Portugal",
    974 => "Qatar",
    262 => "Reunion",
    40 => "Romania",
    7 => "Russia / Kazakhstan",
    250 => "Rwanda",
    1670 => "Saipan",
    1684 => "Samoa (American)",
    685 => "Samoa (Western)",
    378 => "San Marino",
    882 => "Satellite-Thuraya",
    966 => "Saudi Arabia",
    221 => "Senegal",
    381 => "Serbia",
    248 => "Seychelles",
    232 => "Sierra Leone",
    65 => "Singapore",
    421 => "Slovakia",
    386 => "Slovenia",
    252 => "Somalia",
    27 => "South Africa",
    34 => "Spain",
    94 => "Sri Lanka",
    1869 => "St. Kitts And Nevis",
    1758 => "St. Lucia",
    1784 => "St. Vincent",
    249 => "Sudan",
    597 => "Suriname",
    268 => "Swaziland",
    46 => "Sweden",
    41 => "Switzerland",
    963 => "Syria",
    886 => "Taiwan",
    992 => "Tajikistan",
    255 => "Tanzania",
    66 => "Thailand",
    228 => "Togo",
    676 => "Tonga Islands",
    1868 => "Trinidad and Tobago",
    216 => "Tunisia",
    90 => "Turkey",
    993 => "Turkmenistan",
    1649 => "Turks and Caicos Islands",
    256 => "Uganda",
    44 => "UK / Isle of Man / Jersey / Guernsey",
    380 => "Ukraine",
    971 => "United Arab Emirates",
    598 => "Uruguay",
    1 => "USA / Canada / Dominican Rep. / Puerto Rico",
    998 => "Uzbekistan",
    678 => "Vanuatu",
    58 => "Venezuela",
    84 => "Vietnam",
    967 => "Yemen",
    260 => "Zambia",
    255 => "Zanzibar",
    263 => "Zimbabwe",
  );
}

Functions

Namesort descending Description
carrier_load Load a single carrier
carrier_save Save a carrier.
sms_admin_gateway_title SMS gateway menutitle callback.
sms_carriers Get a list of all carriers
sms_country_codes Returns an array of E.164 international country calling codes
sms_default_gateway Returns the current default gateway.
sms_dir Render a direction code
sms_formatter Converts various sms formats into a common format for use in this module.
sms_format_number Formats a number for display.
sms_gateways Get a list of all gateways
sms_gateway_info Implements hook_gateway_info().
sms_handle_result Handle the response back from the sms gateway.
sms_incoming Callback for incoming messages. Allows gateways modules to pass messages in a standard format for processing.
sms_menu Implements hook_menu().
sms_perm Implements hook_perm().
sms_receipt Callback for incoming message receipts. Allows gateways modules to pass message receipts in a standard format for processing, and provides a basic set of status codes for common code handling.
sms_send Sends a message using the active gateway.
sms_send_form Form builder for send sms form.
sms_send_form_submit Form submission handler for sms_send_form().
sms_send_form_validate Form validation handler for sms_send_form().
sms_send_log Log sms message.
sms_sms_carriers Implements hook_sms_carriers()
sms_theme Implements hook_theme().
sms_validate_number Validates a phone number. Passes number to active gateway for further validation if neccessary.
_gateways_build

Constants