diff --git a/modules/custom/sms_yo_uganda/sms_yo_uganda.module b/modules/custom/sms_yo_uganda/sms_yo_uganda.module
new file mode 100755
index 0000000..abb46ad
--- /dev/null
+++ b/modules/custom/sms_yo_uganda/sms_yo_uganda.module
@@ -0,0 +1,855 @@
+<?php
+
+/**
+ *  Pretty empty
+ */
+
+/**
+ * Implementing hook_menu().
+ */
+function sms_yo_uganda_menu() {
+  $items['admin/config/sms_yo_uganda'] = array(
+    'title' => t("Yo! Uganda settings"),
+    'description' => t("This is the page for various settings for Yo! Uganda."),
+    'position' => 'right',
+    'weight' => -5,
+    'access arguments' => array('administer site configuration'),
+    'page callback' => 'system_admin_menu_block_page',
+    'file' => 'system.admin.inc',
+    'file path' => drupal_get_path('module', 'system'),
+  );
+  $items['admin/config/sms_yo_uganda/settings'] = array(
+    'title' => t('Yo! Uganda Settings'),
+    'description' => t('Set general Yo! Uganda Settings.'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('sms_yo_uganda_settings'),
+    'access arguments' => array('administer site configuration'),
+  );
+  $items['sms/yo_uganda/receive'] = array(
+    'title' => t('Yo Receive'),
+    'page callback' => 'sms_yo_uganda_receive_sms',
+    'description' => t('function for incoming sms from yo'),
+    'access callback' => 'sms_yo_uganda_access_incoming',
+    'type' => MENU_CALLBACK,
+  );
+  return $items;
+}
+
+function sms_yo_uganda_providers() {
+  return array(
+    'MTN' => Array (
+        'name' => 'MTN',
+        'internal' => 'MTN_UGANDA',
+    ),
+    'AIRTEL' => Array (
+        'name' => 'Airtel',
+        'internal' => 'MTN_UGANDA',
+    ),
+    'UTL' => Array (
+        'name' => 'UTL',
+        'internal' => 'MTN_UGANDA',
+    ),
+    'WARID' => Array (
+        'name' => 'Warid',
+        'internal' => 'MTN_UGANDA',
+    ),
+    'ORANGE' => Array (
+        'name' => 'Orange',
+        'internal' => 'MTN_UGANDA',
+    ),
+    'ITEL' => Array (
+        'name' => 'I-Tel',
+        'internal' => 'MTN_UGANDA',
+    ),
+    'SMILE' => Array (
+        'name' => 'Smile',
+        'internal' => 'MTN_UGANDA',
+    ),
+  );
+}
+
+
+/*
+ *   Quite strangely, Yo has 4 more parameters that are unique but cant be set using the interface. Every
+ *   Client gets their own file with values.
+ *   our are
+ *   ybs_autocreate_authorization = c32d86ed21921f3a2c4140ac8e65e188
+ *   sysrid = 5
+ *   type = 1
+ *
+ *   accountnumber = 1000194021 (this one we can set through the interface)
+ *   The IP addresses of the Yo servers are
+ *   41.220.12.205
+ *   212.88.103.182
+ */
+function sms_yo_uganda_settings() {
+
+  $form['sms'] = array (
+    '#type' => 'fieldset',
+    '#title' => 'Yo! SMS',
+  );
+  $form['sms']['sms_yo_uganda_sms_yo_accountnumber'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Yo! SMS Account Number'),
+    '#description' => t('The Yo! SMS Account Number.'),
+    '#size' => 40,
+    '#maxlength' => 255,
+    '#default_value' => variable_get('sms_yo_uganda_sms_yo_accountnumber', ''),
+  );
+  $form['sms']['sms_yo_uganda_sms_yo_username'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Yo! SMS User Name'),
+      '#description' => t('The Yo! SMS User Name.'),
+      '#size' => 40,
+      '#maxlength' => 255,
+      '#default_value' => variable_get('sms_yo_uganda_sms_yo_username', ''),
+  );
+
+  $form['sms']['sms_yo_uganda_sms_yo_password'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Yo! SMS Password'),
+      '#description' => t('The Yo! SMS Password.'),
+      '#size' => 40,
+      '#maxlength' => 255,
+      '#default_value' => variable_get('sms_yo_uganda_sms_yo_password', ''),
+  );  
+  $form['sms']['sms_yo_uganda_sms_incoming_server_ip1'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Incoming Server IP Address 1'),
+    '#description' => t('Will only accept incoming connections from this IP address. It is highly recommended to provide this value.'),
+    '#size' => 15,
+    '#maxlength' => 15,
+    '#default_value' => variable_get('sms_yo_uganda_incoming_server_ip1',''),
+  );
+  $form['sms']['sms_yo_uganda_sms_incoming_server_ip2'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Incoming Server IP Address 2'),
+    '#description' => t('Will only accept incoming connections from this IP address. It is highly recommended to provide this value.'),
+    '#size' => 15,
+    '#maxlength' => 15,
+    '#default_value' => variable_get('sms_yo_uganda_incoming_server_ip2', ''),
+  );
+
+  $form['payment'] = array (
+    '#type' => 'fieldset',
+    '#title' => 'Yo! Payment',
+  );
+  $form['payment']['sms_yo_uganda_payment_username'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Username'),
+    '#description' => t('The Yo! Payment Username.'),
+    '#size' => 40,
+    '#maxlength' => 255,
+    '#default_value' => variable_get('sms_yo_uganda_payment_username', ''),
+  );
+  $form['payment']['sms_yo_uganda_payment_password'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Password'),
+    '#description' => t('The Yo! Payment password.'),
+    '#size' => 40,
+    '#maxlength' => 255,
+    '#default_value' => variable_get('sms_yo_uganda_payment_password', ''),
+  );
+  $form['payment']['sms_yo_uganda_payment_server_1'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Payment Server #1'),
+    '#description' => t('Will try to send payments here. Production value is https://paymentsapi1.yo.co.ug/ybs/task.php Sandbox is https://41.220.12.206/services/yopaymentsdev/task.php'),
+    '#size' => 60,
+    '#maxlength' => 255,
+    '#default_value' => variable_get('sms_yo_uganda_payment_server_1', 'https://41.220.12.206/services/yopaymentsdev/task.php'),
+  );
+  $form['payment']['sms_yo_uganda_payment_server_2'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Payment Server #2'),
+    '#description' => t('Will try to send payments here, too. Production value is https://paymentsapi2.yo.co.ug/ybs/task.php'),
+    '#size' => 60,
+    '#maxlength' => 255,
+    '#default_value' => variable_get('sms_yo_uganda_payment_server_2', 'https://41.220.12.206/services/yopaymentsdev/task.php'),
+  );
+  $form['payment']['sms_yo_uganda_payment_type'] = array(
+    '#type' => 'radios',
+    '#title' => t('Airtime or Mobile Money'),
+    '#description' => t('Type of payment to use (Airtime or Mobile Money).'),
+    '#options' => array('airtime' => 'Airtime', 'mobile money' => 'Mobile Money'),
+    '#default_value' => variable_get('sms_yo_uganda_payment_type', 'airtime'),
+  );
+  $form['payment']['sms_yo_uganda_payment_amount'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Amount'),
+    '#description' => t('Amount to be transferred in UGX. If you choose for Airtime, it will be calculated from this amount.'),
+    '#size' => 10,
+    '#maxlength' => 10,
+    '#default_value' => variable_get('sms_yo_uganda_payment_amount', 2000),
+  );
+  $providers = sms_yo_uganda_providers();
+  $options = Array();
+  foreach ($providers as $key => $provider) {
+    $options[$key] = $provider['name'];
+  };
+  $default = array();
+  $form['payment']['sms_yo_uganda_payment_supported_providers'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Supported Mobile Airtime Providers'),
+    '#description' => t('The Mobile Airtime Providers that are supported by Yo! Uganda.'),
+    '#options' => $options,
+    '#default_value' => variable_get('sms_yo_uganda_payment_supported_providers', $default),
+  );
+
+  return system_settings_form($form);
+}
+
+function sms_yo_uganda_settings_submit($form, $form_state) {
+  // all is fine
+
+}
+
+/**
+ * This function will return an array that maps the external
+ * provider names to the names used internally by Yo! Uganda.
+ *
+ * @param string $termname
+ *   The name of the term/provider used externally.
+ *
+ * Returns the internal name of the term with the provided name.
+ */
+function sms_yo_uganda_get_internal_provider_name($termname) {
+  return variable_get('sms_yo_uganda_payment_internal_provider_name_' . $termname, 'MTN_UGANDA');
+}
+
+/**
+ *   THIS HAS NEVER RAN FOR REAL
+ *   (the code is called, but the yo! api is not
+ *
+ *
+ * @param integer $amount
+ *   Amount of bandwdith to send
+ * @param String $phonenumber
+ *   Phonenumber to send bandwidth to
+ */
+function sms_yo_uganda_send_airtime($phonenumber, $provider, $narrative, $transactionref = NULL, $externalref = NULL) {
+  $method = 'acwithdrawfunds';
+  $internetbundle = FALSE;
+  $paymenttype = variable_get('sms_yo_uganda_payment_type', 'airtime');
+  if ($paymenttype == 'airtime') {
+    $method = 'acsendairtimemobile';
+    $internetbundle = TRUE;
+  }
+  $price_per_mb = 200;
+  $amount = variable_get('sms_yo_uganda_payment_amount', 2000);
+  $bandwidth = $amount / $price_per_mb;
+  watchdog("sms_yo_uganda_send_airtime", "Going to send $bandwidth MB to $phonenumber");
+  module_load_include('inc', 'sms_yo_uganda', 'includes/YoPaymentsAPI');
+  $yo_payment = new YoPaymentAPI (
+    variable_get('sms_yo_uganda_payment_username', ''),
+    variable_get('sms_yo_uganda_payment_password', ''),
+    sms_yo_uganda_get_payment_server()
+  );
+
+  /*
+   * There is a few more settings here than expected (like the message)
+   * It seems a good idea to create a SWITCH settings form, and put the message in there
+   * For creating a settings form, copy that from this module.
+   */
+
+  $internalname = sms_yo_uganda_get_internal_provider_name($provider);
+  $response = $yo_payment->withdrawFunds($method, $amount, $phonenumber, $internetbundle, $internalname, $narrative, NULL, NULL, $transactionref, $externalref);
+
+//watchdog('sms_yo_uganda_send_airtime', 'Response keys = ' . implode(' | ', array_keys((array) $response)));
+//watchdog('sms_yo_uganda_send_airtime', 'Response values = ' . implode(' | ', array_values((array) $response)));
+
+  // Do some basic error reporting and handling here
+  // This may throw a YoException
+  sms_yo_uganda_transaction_error($response);
+
+  return $response;
+}
+
+function sms_yo_uganda_check_status($phonenumber, $transactionref) {
+  watchdog("sms_yo_uganda_check_status", "Checking Yo! Transaction " . $transactionref);
+  module_load_include('inc', 'sms_yo_uganda', 'includes/YoPaymentsAPI');
+  $yo_payment = new YoPaymentAPI (
+    variable_get('sms_yo_uganda_payment_username', ''),
+    variable_get('sms_yo_uganda_payment_password', ''),
+    sms_yo_uganda_get_payment_server()
+  );
+
+  /*
+   * There is a few more settings here than expected (like the message)
+   * It seems a good idea to create a SWITCH settings form, and put the message inthere
+   * For creating a settings form, copy that from this module.
+   *
+   */
+
+  $response = $yo_payment->followUpTransaction($transactionref);
+
+//watchdog('sms_yo_uganda_check_status', 'Response keys = ' . implode(' | ', array_keys((array) $response)));
+//watchdog('sms_yo_uganda_check_status', 'Response values = ' . implode(' | ', array_values((array) $response)));
+
+  // Do some basic error reporting and handling here
+  try {
+    sms_yo_uganda_transaction_error($response);
+  }
+  catch (Exception $e) {
+    throw new Exception('Failed to follow up on transaction. Transaction Reference: ' . $transactionref, $e->getCode(), $e);
+  }
+
+  return $response;
+}
+
+function sms_yo_uganda_get_payment_server() {
+  return variable_get('sms_yo_uganda_payment_server_1', 'https://41.220.12.206/services/yopaymentsdev/task.php');
+}
+
+function sms_yo_uganda_transaction_error($response) {
+  $status = (string) $response['Status'];
+  $statuscode = (string) $response['StatusCode'];
+  $statusmessage = (string) $response['StatusMessage'];
+  $errormessage = (string) $response['ErrorMessage'];
+  $transactionstatus = (string) $response['TransactionStatus'];
+  $transactionreference = (string) $response['TransactionReference'];
+
+
+  if ($response !== "Error") {
+      if ($statuscode == '0') {
+        return;
+      }
+    // We have a response
+    // and the response holds at least a Status and a StatusCode
+    if (!empty($statusmessage)) {
+      watchdog('yo_uganda_transaction_error', $status . ' ' . $statuscode . ': Status Message "' . $statusmessage . '"');
+    }
+    if (!empty($errormessage)) {
+      watchdog('yo_uganda_transaction_error', $status . ' ' . $statuscode . ': Error Message "' . $errormessage . '"');
+    }
+    if (!empty($transactionstatus)) {
+      watchdog('yo_uganda_transaction_error', $status . ' ' . $statuscode . ': Transaction Status "' . $transactionstatus . '"');
+    }
+    if (!empty($transactionreference)) {
+      watchdog('yo_uganda_transaction_error', $status . ' ' . $statuscode . ': Transaction Reference "' . $transactionreference . '"');
+    }
+    if ($statuscode != '0') {
+      throw new YoException($statusmessage, $statuscode, $transactionreference, $errormessage, $transactionstatus);
+    }
+  }
+  else { // $response === "Error"
+    // Service seems to be unavailable.
+    // What you could do to implement this exception in your module:
+    // 1.  Send an email/sms to the administrator.
+    // 2.  Maybe put the website into maintenance mode.
+    // 3.  Put all transaction processing queues on hold.
+    // 4.  Start a separate queue that polls Yo! Uganda to see if the service is available again.
+    // 5.  When the service becomes available again, stop the polling queue, send an email to the administrator and reverse steps 2 and 3.
+    watchdog('yo_uganda_transaction_error', $response . ': Service unavailable. Please contact Yo! Uganda for details.');
+    throw new Exception($response . ': Service unavailable. Please contact Yo! Uganda for details.', 9999);
+  }
+}
+
+/**
+ * Implementation of hook_gateway_info().
+ */
+
+function sms_yo_uganda_gateway_info() {
+  return array(
+      'yo' => array(
+          'name' => 'Yo! Uganda',
+          'configure form' => 'sms_yo_uganda_sms_admin_form',
+          'send' => 'sms_yo_uganda_send',
+          'receive' => TRUE,
+          'format' => 'sms_yo_uganda_format_number',
+          'validate number' => 'sms_yo_uganda_gateway_validate_number',
+      ),
+  );
+}
+
+/**
+ * Callback for sending messages.
+ */
+function sms_yo_uganda_send($number, $message, $options) {
+  require_once(drupal_get_path('module', 'sms_yo_uganda') .'/includes/ybsclientlib.phplib');
+  $gateway = sms_gateways('gateway', 'yo');
+
+  if ($config == NULL) {
+    $config = $gateway['configuration'];
+  }
+
+  $number = '256' . trim ($number, "0");
+  watchdog ('sms_yo_uganda', "Sending message to ". $number);
+
+  return sms_send_via_ybs($message, $number, variable_get('sms_yo_uganda_sms_accountnumber', ''));
+}
+
+/**
+ * Retrieve the Yo Balance
+ * Not implemented
+ * @return unknown
+ */
+function sms_yo_uganda_balance() {
+  require_once(drupal_get_path('module', 'sms_yo_uganda') .'/includes/ybsclientlib.phplib');
+  $result = sms_yo_gateway_command('getbalance');
+  return $result['data'];
+}
+
+
+function sms_yo_uganda_country_codes() {
+  return array(
+      256 => "Uganda",
+  );
+}
+
+
+/**
+ * Converts a string to USC-2 encoding if neccessary.
+ */
+function sms_yo_uganda_unicode($message) {
+  if (function_exists('iconv')) {
+    $latin = @iconv('UTF-8', 'ISO-8859-1', $message);
+    if (strcmp($latin, $message)) {
+      $arr = unpack('H*hex', @iconv('UTF-8', 'UCS-2BE', $message));
+      return strtoupper($arr['hex']) .'&unicode=1';
+    }
+  }
+  return FALSE;
+}
+
+/**
+ * Implements hook_format_number
+ * Not sure what that is supposed to do.
+ * @param unknown_type $number
+ * @param unknown_type $options
+ */
+function sms_yo_uganda_format_number(&$number, $options = array()) {
+  //  drupal_set_message("we are going to format the number ". $number);
+}
+
+
+function sms_yo_uganda_validate_number(&$number, $options = array()) {
+
+  // strip non-numbers
+  $number2 = preg_replace("/[^0-9]/", '', $number);
+  // add 0 if
+  if (strpos($number2, '7') == 0) {
+    $number2 = $number2. '0';
+  }
+
+  // strip 256
+  $position = strpos($number2, '256');
+  if (($position != "") && ($position == 0)) {
+    $number2 = substr($number2, 3);
+  }
+
+
+  if (strpos($number2, '07') != 0) {
+    return ("This number is not a valid Ugandan mobile phonenumber.");
+  }
+
+
+
+  if (strpos($number2, '07') == 0) {
+    $number2 = '256' . ltrim ($number2, '0');
+  }
+
+  $provider = sms_yo_uganda_getprovider($number2);
+  if ((!$provider) || ($provider == 'Unknown')) {
+    return 'The phone number is not a Ugandan number.';
+  }
+
+  $number = $number2;
+}
+
+
+function sms_yo_uganda_access_incoming( ) {
+  $gateway = sms_gateways('gateway', 'yo');
+  $config = $gateway['configuration'];
+
+  if (((isset($config['sms_yo_incoming_server_ip1'])) && ($config['sms_yo_incoming_server_ip1'] != $_SERVER['REMOTE_ADDR']))
+      || ((isset($config['sms_yo_incoming_server_ip2'])) && ($config['sms_yo_incoming_server_ip2'] != $_SERVER['REMOTE_ADDR']))) {
+    //  	return FALSE;
+  }
+  /*    $gateway = sms_gateways('gateway', 'yo');
+   $config = $gateway['configuration'];
+  if (($_REQUEST['username'] != $config['sms_yo_incoming_username']) || ($_REQUEST['password'] != $config['sms_yo_incoming_password'])) {
+  watchdog('sms_yo', 'Authentication failed');
+  return FALSE;
+  }
+  */
+  return TRUE;
+}
+
+function sms_yo_uganda_receive_sms() {
+  $number = $_REQUEST['from'];
+  $message = $_REQUEST['text'];
+  $options = array();
+  if (array_key_exists('to', $_REQUEST) && !empty($_REQUEST['to'])) {
+    $options['receiver'] = $_REQUEST['to'];
+  }
+  if (array_key_exists('from', $_REQUEST) && !empty($_REQUEST['from'])) {
+    $options['sender'] = $_REQUEST['from'];
+  }
+  if (array_key_exists('text', $_REQUEST) && !empty($_REQUEST['text'])) {
+    $options['text'] = $_REQUEST['text'];
+  }
+  if (array_key_exists('encoding', $_REQUEST) && !empty($_REQUEST['encoding'])) {
+    $options['encoding'] = $_REQUEST['encoding'];
+  }
+  if (array_key_exists('provider', $_REQUEST) && !empty($_REQUEST['provider'])) {
+    $options['provider'] = $_REQUEST['provider'];
+  }
+  if (array_key_exists('username', $_REQUEST) && !empty($_REQUEST['username'])) {
+    $options['username'] = $_REQUEST['username'];
+  }
+  if (array_key_exists('password', $_REQUEST) && !empty($_REQUEST['password'])) {
+    $options['password'] = $_REQUEST['password'];
+  }
+
+  // The telco's send us real nast funky encoded message
+  // this is code to fix that for web
+  $message = sms_yo_uganda_utf8RawUrlDecode(html_entity_decode($message, ENT_QUOTES, 'UTF-8'));
+  if ($number && $message) {
+    sms_incoming($number, $message, $options);
+  }
+  else {
+    print("no number, no message");
+  }
+
+}
+
+function sms_yo_uganda_incoming_callback() {
+  // Any necessary processing to extract the number and message
+  sms_incoming($number, $message, $options);
+}
+
+
+function sms_yo_uganda_utf8RawUrlDecode ($source) {
+  $decodedStr = "";
+  $pos = 0;
+  $len = strlen ($source);
+  while ($pos < $len) {
+    $charAt = substr ($source, $pos, 1);
+    if ($charAt == '%') {
+      $pos++;
+      $charAt = substr ($source, $pos, 1);
+      if ($charAt == 'u') {
+        // we got a unicode character
+        $pos++;
+        $unicodeHexVal = substr ($source, $pos, 4);
+        $unicode = hexdec ($unicodeHexVal);
+        $entity = "&#". $unicode . ';';
+        $decodedStr .= utf8_encode ($entity);
+        $pos += 4;
+      }
+      else {
+        // we have an escaped ascii character
+        $hexVal = substr ($source, $pos, 2);
+        $decodedStr .= chr (hexdec ($hexVal));
+        $pos += 2;
+      }
+    } else {
+      $decodedStr .= $charAt;
+      $pos++;
+    }
+  }
+
+  // And this is for all you UTF-16 suckers!! Eat this:
+  $decodedStr = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S','',$decodedStr);
+  $decodedStr = preg_replace('/[^\x00-\x7F]+/S','',$decodedStr);
+
+  return $decodedStr;
+}
+
+
+
+
+
+/**
+ * Define a custom exception class
+ */
+class YoException extends Exception {
+
+  public $status;
+
+  public $statuscode;
+
+  public $errormessage;
+
+  public $transactionreference;
+
+  public $transactionstatus;
+
+  public $statusmessage;
+
+  // should we retry the same command?
+  public $retry;
+
+  // should we keep on checking for the status of $transactionreference ?
+  public $checkstatus;
+
+  // Redefine the exception so message isn't optional
+  public function __construct($message, $statuscode = 0, $transactionreference = NULL, $errormessage = NULL, $transactionstatus =NULL, Exception $previous = null) {
+
+    $this->statuscode = $statuscode;
+    $this->transactionreference = $transactionreference;
+    $this->errormessage = $errormessage;
+    $this->transactionstatus = $transactionstatus;
+
+    $this->statusmessage = $this->_getStatusCodeText($statuscode, $transactionreference = NULL);
+
+    $this->_setRetry();
+    $this->_setCheckStatus();
+
+    // make sure everything is assigned properly
+    parent::__construct($message, $statuscode, $previous);
+  }
+
+  // custom string representation of object
+  public function __toString() {
+    return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
+  }
+
+  public function customFunction() {
+    echo "A custom function for this type of exception\n";
+  }
+
+  private function _setCheckStatus() {
+    if ($this->statuscode < 0) {
+      $this->checkstatus = 'Error';
+    }
+
+    if ($this->statuscode == 0) {
+      $this->checkstatus = 'Success';
+    }
+
+    if ($this->statuscode == 1) {
+      $this->checkstatus = 'Pending';
+    }
+
+    if ($this->statuscode > 1) {
+      $this->checkstatus = 'Indeterminate';
+    }
+  }
+
+
+  private function _setRetry() {
+    /*
+     * Negative values are real errors.
+    */
+    switch ($this->statuscode) {
+      case -30:
+      case -29:
+      case -28:
+      case -27:
+      case -26:
+      case -25:
+      case -24:
+      case -22:
+      case -11:
+      case -10:
+      case -8:
+      case -7:
+      case -5:
+      case -4:
+      case -3:
+      case -2:
+        /*
+         * positive values are indetermined
+         */
+      case 0:
+      case 1:
+      case 4:
+      case 6:
+      case 9:
+      case 12:
+      case 13:
+      case 16:
+      case 17:
+      case 20:
+      case 21:
+      case 23:
+      case 25:
+      case 26:
+      case 27:
+        $this->retry = FALSE;
+        return;
+        break;
+      default:
+        $this->retry = TRUE;
+      return;
+      break;
+    }
+  }
+
+  private function _getStatusCodeText($statuscode, $transactionreference = NULL) {
+    $statuscodes = array(
+        "-9999" => "You have submitted invalid XML, or one or more fields in the XML request you have submitted is missing or invalid. If you get this error code, check the StatusMessage parameter for more detailed information.",
+        "-31" => "There was an internal error processing your request to perform a non-blocking transaction. Please submit your transaction again later.",
+        "-30" => "The transaction was not found in the system. Please verify your transaction reference.",
+        "-29" => "In the acgetministatement request, you have specified a currency code that does not exist or is in DRAFT state or is DISABLED.",
+        "-28" => "In the acgetministatement request, you have specified an invalid start date from which to obtain a statement.",
+        "-27" => "In the acgetministatement request, you have specified an invalid end date up to which to obtain a statement.",
+        "-26" => "In the acgetministatement request, you have specified a start date without specifying the end date.",
+        "-25" => "In the acgetministatement request, you have specified an end date without specifying the start date.",
+        "-24" => "In the acgetministatement request, you have specified an invalid date range, E.g if the start date is after the end date.",
+        "-23" => "This transaction has been declined because you have reached or exceeded one or more of your withdrawal limits.",
+        "-22" => "This transaction requires extra authorization before it may be completed. Requests for authorization have been duly sent. Upon successful authorization by all parties, the transaction shall be processed. DO NOT RE-SUBMIT THIS TRANSACTION UNLESS YOU ARE SURE IT HAS FAILED OR WAS REJECTED.",
+        "-21" => "Your IP address is not permitted to carry out transactions on this account.",
+        "-20" => "Your account was CANCELLED. Please contact your account representative for further advice.",
+        "-19" => "Your account was TERMINATED. Please contact your account representative for further advice.",
+        "-18" => "Your account is SUSPENDED. Please contact your account representative for further advice.",
+        "-13" => "You do not have sufficient funds to complete this transaction.",
+        "-12" => "There was a problem initiating this transaction. This transaction has failed. Please try again later. If this problem persists, contact support services.",
+        "-11" => "Invalid or Unsupported Currency.",
+        "-10" => "The transaction has not been processed. This is the default transaction status for a transaction whose details have been successfully validated but it has not yet been submitted to the transaction processing system.",
+        "-9" => "Error committing initial statement entry. The transaction was not processed, and will not appear in the web interface.",
+        "-8" => "This is likley a duplicate transaction. Please vary your submission parameters such as references, if this is not in error.",
+        "-7" => "Invalid internal reference parameter. If you are sure that the internal reference you have provided is correct then the transaction was archived, or may have been deleted as a result of its old age.",
+        "-6" => "Duplicate transaction code (try again later).",
+        "-5" => "The file specified in 'file_narrative' was not found.",
+        "-4" => "Invalid 'amount' parameter.",
+        "-3" => "Unsupported transaction type parameter.",
+        "-2" => "Unsupported MSISDN Network or Currency.",
+        "-1" => "An internal error occurred. More information in 'ErrorMessage'.",
+        "0" => "The Transaction was Successful.",
+        "1" => "The transaction has been successfully recorded but is pending at the low-level. Use the actransactioncheckstatus API call to poll this transaction.",
+        "2" => "The transaction failed -- see 'ErrorMessage' for more information.",
+        "3" => "The transaction failed but we encountered an error updating the transaction state to mark the transaction as FAILED. The transaction is still in the INDETERMINATE state and will need to be manually marked as FAILED, and for a completion time to be added. If you get this error code, consider your transaction as FAILED. The transaction state will be updated to FAILED within 24 hours. Contact support services if the transaction state is not yet updated within 24 hours of your receiving this message.",
+        "4" => "The transaction succeeded but we encountered an error updating the transaction state to mark the transaction as successful. The transaction is still in the INDETERMINATE state and will need to be manually marked as SUCCEEDED, and for a completion time to be added. Your account may or may not have been credited with the funds. Check your statement on the online interface to verify whether your account was credited or not. If you get this error code, consider your transaction SUCCEEDED but ensure to contact support services if your account statement is not updated within 24 hours.",
+        "5" => "The transaction was rendered indeterminate in as far as our interaction with the network goes, however we failed to update the transaction state to add a completion date/time. The transaction will need to be manually completed and changed to FAILED or SUCCEEDED based on investigations with the mobile network. If you get this error code, contact support services if the transaction state is not definitively resolved within 1 hour. Your transaction may have succeeded or may have failed.",
+        "6" => "The transaction succeeded. However, because of an internal problem, your balance has not yet been updated to reflect the transaction. You shall notice that this transaction is still in the INDETERMINATE state. We shall mark the transaction as SUCCEEDED shortly and update your account balance. If you get this error code, consider your transaction successful. Contact support services if your account statement / balance is not updated to reflect this transaction within 24 hours.",
+        "7" => "Unsupported transaction type ''.The transaction was not processed and will appear in the web interface as a FAILED transaction. If you get this error code, consider your transaction as FAILED.",
+        "8" => "Unsupported transaction type ''.processed but there was a problem marking the transaction as FAILED. The transaction will be manually marked as failed shortly. If this transaction is still in the INDETERMINATE state within 24 hours of receiving this message, please contact support services. If you get this error code, consider your transaction as FAILED.",
+        "9" => "Indeterminate Transaction. The response we got from the mobile network mobile money system was inconclusive. It is not clear whether this transaction succeeded or failed. This situation shall be resolved within 1 hour and your transaction shall be moved to either the SUCCEEDED state or FAILED state, depending on the information from the mobile network mobile money system. If this situation is unresolved within 1 hour of your receipt of this message, kindly contact support services.",
+        "10" => "The transaction failed. There was an error contacting the internal processing gateway. Please try your transaction again later, or contact support services if this error persists.",
+        "11" => "The transaction failed. There was an error contacting the internal processing gateway. However, there was, also, a problem marking this transaction as FAILED. Therefore, you shall notice that this transaction is in the INDETERMINATE state. This shall be resolved within 1 hour of receiving this message. If you get this error code, your transaction failed. Contact support services if this transaction remains in the INDETERMINATE state for more than 1 hour or if this error persists.",
+        "12" => "Indeterminate Transaction. There was an error communicating with the internal processing gateway. Therefore, you shall notice that this transaction is in the INDETERMINATE state. This shall be resolved within 1 hour of your receiving this message. If you get this error code, your transaction may have succeeded or may have failed. Contact support services if this transaction remains in the INDETERMINATE state for more than 1 hour of if this error persists.",
+        "13" => "Indeterminate Transaction. There was an error communicating with the internal processing gateway. However, there was, also, a problem completing this transaction, therefore you shall notice that there is no completion date for this transaction. This situation shall be resolved within 1 hour of your receiving this message. If you get this error code, your transaction may have succeeded or may have failed. Contact support services if this transaction remains in the INDETERMINATE state for more than 1 hour of if this error persists.",
+        "14" => "The OUTBOUND_MSISDN_DEBIT transation failed. Your account balance is unaffected. See 'ErrorMessage' for more information on why the transaction failed.",
+        "15" => "The OUTBOUND_MSISDN_DEBIT transaction failed. However, there was a problem restoring your account balance. Therefore, this transaction is still in the INDETERMINATE state. Your account balance will be restored within 1 hour of your receiving this message. If your account balance is still unrestored after 1 hour, contact support services and provide this reference code: '" . $transactionreference . "'.",
+        "16" => "The OUTBOUND_MSISDN_DEBIT transaction could not be completed because of a problem posting the initial transaction statement. Therefore, this transaction is in the INDETERMINATE state. Your account balance will be restored within 1 hour of your receiving this message. If your account balance is still unrestored after 1 hour, contact support services and provide this reference code: '" . $transactionreference . "'. Please note that while your web interface will indicate SUCCEEDED, the transaction did not completely succeed.",
+        "17" => "The OUTBOUND_MSISDN_DEBIT succeeded, however you need to manually do the following: (a) Mark the transaction with code '" . $transactionreference . "' in the Suspense Account as SUCCEEDED; and (b) Debit the network tracking account for your network with the amount.",
+        "18" => "The transaction failed. There was an error contacting the internal processing gateway. Please try your transaction again later, or contact support services if this error persists.",
+        "19" => "The transaction failed. There was an error contacting the internal processing gateway. However, there was, also, a problem marking this transaction as FAILED. Therefore, you shall notice that this transaction is in the INDETERMINATE state. This shall be resolved within 1 hour of receiving this message. If you get this error code, your transaction failed. Contact support services if this transaction remains in the INDETERMINATE state for more than 1 hour or if this error persists. If you contact support services, provide this reference code: '" . $transactionreference . "'.",
+        "20" => "Indeterminate Transaction. There was an error communicating with the internal processing gateway. Therefore, you shall notice that this transaction is in the INDETERMINATE state. This shall be resolved within 1 hour of your receiving this message. If you get this error code, your transaction may have succeeded or may have failed. Contact support services if this transaction remains in the INDETERMINATE state for more than 1 hour of if this error persists. If you contact support services, provide this reference code: '" . $transactionreference . "'.",
+        "21" => "Indeterminate Transaction. There was an error communicating with the internal processing gateway. However, there was, also, a problem completing this transaction, therefore you shall notice that there is no completion date for this transaction. This situation shall be resolved within 1 hour of your receiving this message. If you get this error code, your transaction may have succeeded or may have failed. Contact support services if this transaction remains in the INDETERMINATE state for more than 1 hour of if this error persists. If you contact support services, provide this reference code: '" . $transactionreference . "'.",
+        "22" => "The transaction failed but we encountered an error updating the transaction state to mark the transaction as FAILED. The transaction is still in the INDETERMINATE state and will need to be manually marked as FAILED, and for a completion time to be added. If you get this error code, consider your transaction as FAILED. The transaction will state will be updated to FAILED within 24 hours. Contact support services if the transaction state is not yet updated within 24 hours of your receiving this message. If you contact support services, provide this reference code: '" . $transactionreference . "'.",
+        "23" => "The transaction was rendered indeterminate in as far as our interaction with the network goes, however we failed to update the transaction state to add a completion date/time. The transaction will need to be manually completed and changed to FAILED or SUCCEEDED based on investigations with the mobile network. If you get this error code, contact support services if the transaction state is not definitively resolved within 1 hour. Your transaction may have succeeded or may have failed. If you contact support services, provide this reference code: '" . $transactionreference . "'.",
+        "24" => "The transaction failed -- see 'ErrorMessage' for more information. Your balance remains unaffected.",
+        "25" => "Indeterminate Transaction. The response we got from the mobile network mobile money system was inconclusive. It is not clear whether this transaction succeeded or failed. This situation shall be resolved within 1 hour and your transaction shall be moved to either the SUCCEEDED state or FAILED state, depending on the information from the mobile network mobile money system. If this situation is unresolved within 1 hour of your receipt of this message, kindly contacts support services. If you contact support services, provide this reference code: '" . $transactionreference . "'.",
+        "26" => "The transaction was declined by the user.",
+        "27" => "The transaction is in a PENDING state but we encountered an error updating the transaction state to mark the transaction as PENDING. The transaction is still in the INDETERMINATE state and will need to be manually marked as PENDING, and for a completion time to be added. If you get this error code, consider your transaction as PENDING. The transaction state will be updated within 24 hours. Contact support services if the transaction state is not yet updated within 24 hours of your receiving this message.",
+        "28" => "Your 'acrequestfundspush' deposit request has expired. No funds related to the request were transferred to the designated mobile money account within 10 minutes from when the request was initiated. This means your push deposit request has subsequently FAILED.",
+    );
+
+    if (in_array($statuscode, array_keys($statuscodes))) {
+      return $statuscodes[$statuscode];
+    }
+    else {
+      return 'Unknown StatusCode. Please contact Yo! Uganda for details.';
+    }
+  }
+}
+
+/**
+ * Returns the term of the Internet Service Provider that belongs to the given phonenumber
+ * @param string $phonenumber
+ *   A 12 digit phone number (e.g. 256789123456)
+ */
+function sms_yo_uganda_getprovider($phonenumber) {
+  $provider = &drupal_static(__FUNCTION__);
+  if (isset($provider[$phonenumber])) {
+    return $provider[$phonenumber];
+  }
+
+    switch (substr($phonenumber, 3, 3)) {
+      case '700':
+      case '701':
+      case '702':
+      case '703':
+      case '704':
+      case '705':
+        $provider[$phonenumber] = 'Warid';
+        break;
+      case '710':
+      case '711':
+      case '712':
+      case '713':
+      case '714':
+      case '715':
+      case '716':
+      case '717':
+      case '718':
+      case '719':
+        $provider[$phonenumber] = 'UTL';
+        break;
+      case '750':
+      case '751':
+      case '752':
+      case '753':
+      case '754':
+      case '755':
+      case '756':
+      case '757':
+      case '758':
+      case '759':
+        $provider[$phonenumber] = 'Airtel';
+        break;
+      case '760':
+        $provider[$phonenumber] = 'I-Tel';
+        break;
+      case '762':
+        $provider[$phonenumber] = 'Smile';
+        break;
+      case '770':
+      case '771':
+      case '772':
+      case '773':
+      case '774':
+      case '775':
+      case '776':
+      case '777':
+      case '778':
+      case '779':
+      case '780':
+      case '781':
+      case '782':
+      case '783':
+      case '784':
+      case '785':
+      case '786':
+      case '787':
+      case '788':
+      case '789':
+        $provider[$phonenumber] = 'MTN';
+        break;
+      case '790':
+      case '791':
+      case '792':
+      case '793':
+      case '794':
+        $provider[$phonenumber] = 'Orange';
+        break;
+      default:
+        $provider[$phonenumber] = 'Unknown';
+    }
+    return $provider[$phonenumber];
+}
+
+/*
+ * Checks if an ISP is supported by the Yo integration
+*/
+function sms_yo_uganda_provider_is_supported($provider) {
+  // Sorry, we needed to hardcode this, as it was not working.
+  if (($provider == 'Airtel') || ($provider == 'MTN') || ($provider == 'Orange')) {
+    watchdog('switch_provider_is_supported', $provider . " is supported.");
+    //return TRUE;
+  }
+  else {
+    watchdog('switch_provider_is_supported', $provider . " is NOT supported.");
+    return 'We are sorry but ' . $provider . ' is currently not supported.';
+  }
+
+  /*
+   $supported_providers = variable_get('yo_uganda_payment_supported_providers', array());
+
+    if (!in_array($provider, $supported_providers)) {
+    return 'We are sorry but ' . $provider . ' is currently not supported.';
+    }*/
+  }
