_debug = true; /* set this to false if you want to suppress debug output. */ $this->_socket = NULL; $this->_command_status = 0; $this->_sequence_number = 1; $this->_source_address = ""; $this->_message_sequence = rand(1,255); } /* For SMS gateways that support sender-ID branding, the method can be used to set the originating address. Parameters: $from : Originating address Example: $smpp->SetSender("31495595392"); */ function SetSender($from) { if (strlen($from) > 20) { $this->debug("Error: sender id too long.\n"); return; } $this->_source_address = $from; } /* This method initiates an SMPP session. It is to be called BEFORE using the Send() method. Parameters: $host : SMPP ip to connect to. $port : port # to connect to. $username : SMPP system ID $password : SMPP passord. $system_type : SMPP System type Returns: true if successful, otherwise false Example: $smpp->Start("smpp.chimit.nl", 2345, "chimit", "my_password", "client01"); */ function Start($host, $port, $username, $password, $system_type) { /* $testarr = stream_get_transports(); $have_tcp = false; reset($testarr); while (list(, $transport) = each($testarr)) { if ($transport == "tcpp") { $have_tcp = true; } } if (!$have_tcp) { $this->debug("No TCP support in this version of PHP.\n"); return false; } */ $this->_socket = fsockopen($host, $port, $errno, $errstr, 20); // todo: sanity check on input parameters if (!$this->_socket) { $this->debug("Error opening SMPP session.\n"); $this->debug("Error was: $errstr.\n"); return; } socket_set_timeout($this->_socket, 1200); $status = $this->SendBindTransmitter($username, $password, $system_type); if ($status != 0) { $this->debug("Error binding to SMPP server. Invalid credentials?\n"); } return ($status == 0); } /* This method sends out one SMS message. Parameters: $to : destination address. $text : text of message to send. $unicode: Optional. Indicates if input string is html encoded unicode. Returns: true if messages sent successfull, otherwise false. Example: $smpp->Send("31649072766", "This is an SMPP Test message."); $smpp->Send("31648072766", "صباحالخير", true); */ function Send($to, $text, $unicode = false) { if (strlen($to) > 20) { $this->debug("to-address too long.\n"); return; } if (!$this->_socket) { $this->debug("Not connected, while trying to send SUBMIT_SM.\n"); // return; } $service_type = ""; //default source TON and NPI for international sender $source_addr_ton = 1; $source_addr_npi = 1; $source_addr = $this->_source_address; if (preg_match('/\D/', $source_addr)) //alphanumeric sender { $source_addr_ton = 5; $source_addr_npi = 0; } elseif (strlen($source_addr) < 11) //national or shortcode sender { $source_addr_ton = 2; $source_addr_npi = 1; } $dest_addr_ton = 1; $dest_addr_npi = 1; $destination_addr = $to; $esm_class = 3; $protocol_id = 0; $priority_flag = 0; $schedule_delivery_time = ""; $validity_period = ""; $registered_delivery_flag = 0; $replace_if_present_flag = 0; $data_coding = 241; $sm_default_msg_id = 0; if ($unicode) { $text = mb_convert_encoding($text, "UCS-2BE", "HTML-ENTITIES"); /* UCS-2BE */ $data_coding = 8; /* UCS2 */ $multi = $this->split_message_unicode($text); } else { $multi = $this->split_message($text); } $multiple = (count($multi) > 1); if ($multiple) { $esm_class += 0x00000040; } $result = true; reset($multi); while (list(, $part) = each($multi)) { $short_message = $part; $sm_length = strlen($short_message); $status = $this->SendSubmitSM($service_type, $source_addr_ton, $source_addr_npi, $source_addr, $dest_addr_ton, $dest_addr_npi, $destination_addr, $esm_class, $protocol_id, $priority_flag, $schedule_delivery_time, $validity_period, $registered_delivery_flag, $replace_if_present_flag, $data_coding, $sm_default_msg_id, $sm_length, $short_message); if ($status != 0) { $this->debug("SMPP server returned error $status.\n"); $result = false; } } return $result; //---------------------------------------------------------------------------------------ALTERADO AQUI } /* This method ends a SMPP session. Parameters: none Returns: true if successful, otherwise false Example: $smpp->End(); */ function End() { if (!$this->_socket) { // not connected return; } $status = $this->SendUnbind(); if ($status != 0) { $this->debug("SMPP Server returned error $status.\n"); } fclose($this->_socket); $this->_socket = NULL; return ($status == 0); } /* This method sends an enquire_link PDU to the server and waits for a response. Parameters: none Returns: true if successfull, otherwise false. Example: $smpp->TestLink() */ function TestLink() { $pdu = ""; $status = $this->SendPDU(CM_ENQUIRELINK, $pdu); return ($status == 0); } /* This method sends a single message to a comma separated list of phone numbers. There is no limit to the number of messages to send. Parameters: $tolist : comma seperated list of phone numbers $text : text of message to send $unicode: Optional. Indicates if input string is html encoded unicode string. Returns: true if messages received by smpp server, otherwise false. Example: $smpp->SendMulti("31777110204,31649072766,...,...", "This is an SMPP Test message."); */ function SendMulti($tolist, $text, $unicode = false) { if (!$this->_socket) { $this->debug("Not connected, while trying to send SUBMIT_MULTI.\n"); // return; } $service_type = ""; $source_addr = $this->_source_address; //default source TON and NPI for international sender $source_addr_ton = 1; $source_addr_npi = 1; $source_addr = $this->_source_address; if (preg_match('/\D/', $source_addr)) //alphanumeric sender { $source_addr_ton = 5; $source_addr_npi = 0; } elseif (strlen($source_addr) < 11) //national or shortcode sender { $source_addr_ton = 2; $source_addr_npi = 1; } $dest_addr_ton = 1; $dest_addr_npi = 1; //$destination_arr = explode(",", $tolist); $destination_arr = $tolist; $esm_class = 3; $protocol_id = 0; $priority_flag = 0; $schedule_delivery_time = ""; $validity_period = ""; $registered_delivery_flag = 0; $replace_if_present_flag = 0; $data_coding = 241; $sm_default_msg_id = 0; if ($unicode) { $text = mb_convert_encoding($text, "UCS-2BE", "HTML-ENTITIES"); $data_coding = 8; /* UCS2 */ $multi = $this->split_message_unicode($text); } else { $multi = $this->split_message($text); } $multiple = (count($multi) > 1); if ($multiple) { $esm_class += 0x00000040; } $result = true; reset($multi); while (list(, $part) = each($multi)) { $short_message = $part; $sm_length = strlen($short_message); $status = $this->SendSubmitMulti($service_type, $source_addr_ton, $source_addr_npi, $source_addr, $dest_addr_ton, $dest_addr_npi, $destination_arr, $esm_class, $protocol_id, $priority_flag, $schedule_delivery_time, $validity_period, $registered_delivery_flag, $replace_if_present_flag, $data_coding, $sm_default_msg_id, $sm_length, $short_message); if ($status != 0) { $this->debug("SMPP server returned error $status.\n"); $result = false; } } return $result; } // private members (not documented): function ExpectPDU($our_sequence_number) { do { $this->debug("Trying to read PDU.\n"); if (feof($this->_socket)) { $this->debug("Socket was closed.!!\n"); } $elength = fread($this->_socket, 4); if (empty($elength)) { $this->debug("Connection lost.\n"); return; } extract(unpack("Nlength", $elength)); $this->debug("Reading PDU : $length bytes.\n"); $stream = fread($this->_socket, $length - 4); $this->debug("Stream len : " . strlen($stream) . "\n"); extract(unpack("Ncommand_id/Ncommand_status/Nsequence_number", $stream)); $command_id &= 0x0fffffff; $this->debug("Command id : $command_id.\n"); $this->debug("Command status : $command_status.\n"); $this->debug("sequence_number : $sequence_number.\n"); $pdu = substr($stream, 12); switch ($command_id) { case CM_BIND_TRANSMITTER: $this->debug("Got CM_BIND_TRANSMITTER_RESP.\n"); $spec = "asystem_id"; extract($this->unpack2($spec, $pdu)); $this->debug("system id : $system_id.\n"); break; case CM_UNBIND: $this->debug("Got CM_UNBIND_RESP.\n"); break; case CM_SUBMIT_SM: $this->debug("Got CM_SUBMIT_SM_RESP.\n"); if ($command_status == 0) { $spec = "amessage_id"; extract($this->unpack2($spec, $pdu)); $this->debug("message id : $message_id.\n"); } break; case CM_SUBMIT_MULTI: $this->debug("Got CM_SUBMIT_MULTI_RESP.\n"); $spec = "amessage_id/cno_unsuccess/"; extract($this->unpack2($spec, $pdu)); $this->debug("message id : $message_id.\n"); $this->debug("no_unsuccess : $no_unsuccess.\n"); break; case CM_ENQUIRELINK: $this->debug("GOT CM_ENQUIRELINK_RESP.\n"); break; default: $this->debug("Got unknown SMPP pdu.\n"); break; } $this->debug("\nReceived PDU: "); for ($i = 0; $i < strlen($stream); $i++) { if (ord($stream[$i]) < 32) $this->debug("(" . ord($stream[$i]) . ")"); else $this->debug($stream[$i]); } $this->debug("\n"); } while ($sequence_number != $our_sequence_number); return $command_status; } function SendPDU($command_id, $pdu) { $length = strlen($pdu) + 16; $header = pack("NNNN", $length, $command_id, $this->_command_status, $this->_sequence_number); $this->debug("Sending PDU, len == $length\n"); $this->debug("Sending PDU, header-len == " . strlen($header) . "\n"); $this->debug("Sending PDU, command_id == " . $command_id . "\n"); fwrite($this->_socket, $header . $pdu, $length); $status = $this->ExpectPDU($this->_sequence_number); $this->_sequence_number = $this->_sequence_number + 1; return $status; } function SendBindTransmitter($system_id, $smpppassword, $system_type) { $system_id = $system_id . chr(0); $system_id_len = strlen($system_id); $smpppassword = $smpppassword . chr(0); $smpppassword_len = strlen($smpppassword); $system_type = $system_type . chr(0); $system_type_len = strlen($system_type); $pdu = pack("a{$system_id_len}a{$smpppassword_len}a{$system_type_len}CCCa1", $system_id, $smpppassword, $system_type, 0x33, 0, 0, chr(0)); $this->debug("Bind Transmitter PDU: "); for ($i = 0; $i < strlen($pdu); $i++) { $this->debug(ord($pdu[$i]) . " "); } $this->debug("\n"); $status = $this->SendPDU(CM_BIND_TRANSMITTER, $pdu); return $status; } function SendUnbind() { $pdu = ""; $status = $this->SendPDU(CM_UNBIND, $pdu); return $status; } function SendSubmitSM($service_type, $source_addr_ton, $source_addr_npi, $source_addr, $dest_addr_ton, $dest_addr_npi, $destination_addr, $esm_class, $protocol_id, $priority_flag, $schedule_delivery_time, $validity_period, $registered_delivery_flag, $replace_if_present_flag, $data_coding, $sm_default_msg_id, $sm_length, $short_message) { $service_type = $service_type . chr(0); $service_type_len = strlen($service_type); $source_addr = $source_addr . chr(0); $source_addr_len = strlen($source_addr); $destination_addr = $destination_addr . chr(0); $destination_addr_len = strlen($destination_addr); $schedule_delivery_time = $schedule_delivery_time . chr(0); $schedule_delivery_time_len = strlen($schedule_delivery_time); $validity_period = $validity_period . chr(0); $validity_period_len = strlen($validity_period); // $short_message = $short_message . chr(0); $message_len = $sm_length; $spec = "a{$service_type_len}cca{$source_addr_len}cca{$destination_addr_len}ccca{$schedule_delivery_time_len}a{$validity_period_len}ccccca{$message_len}"; $this->debug("PDU spec: $spec.\n"); $pdu = pack($spec, $service_type, $source_addr_ton, $source_addr_npi, $source_addr, $dest_addr_ton, $dest_addr_npi, $destination_addr, $esm_class, $protocol_id, $priority_flag, $schedule_delivery_time, $validity_period, $registered_delivery_flag, $replace_if_present_flag, $data_coding, $sm_default_msg_id, $sm_length, $short_message); $status = $this->SendPDU(CM_SUBMIT_SM, $pdu); return $status; } function SendSubmitMulti($service_type, $source_addr_ton, $source_addr_npi, $source_addr, $dest_addr_ton, $dest_addr_npi, $destination_arr, $esm_class, $protocol_id, $priority_flag, $schedule_delivery_time, $validity_period, $registered_delivery_flag, $replace_if_present_flag, $data_coding, $sm_default_msg_id, $sm_length, $short_message) { $service_type = $service_type . chr(0); $service_type_len = strlen($service_type); $source_addr = $source_addr . chr(0); $source_addr_len = strlen($source_addr); $number_destinations = count($destination_arr); $dest_flag = 1; $spec = "a{$service_type_len}cca{$source_addr_len}c"; $pdu = pack($spec, $service_type, $source_addr_ton, $source_addr_npi, $source_addr, $number_destinations ); $dest_flag = 1; reset($destination_arr); while (list(, $destination_addr) = each($destination_arr)) { $destination_addr .= chr(0); $dest_len = strlen($destination_addr); $spec = "ccca{$dest_len}"; $pdu .= pack($spec, $dest_flag, $dest_addr_ton, $dest_addr_npi, $destination_addr); } $schedule_delivery_time = $schedule_delivery_time . chr(0); $schedule_delivery_time_len = strlen($schedule_delivery_time); $validity_period = $validity_period . chr(0); $validity_period_len = strlen($validity_period); $message_len = $sm_length; $spec = "ccca{$schedule_delivery_time_len}a{$validity_period_len}ccccca{$message_len}"; $pdu .= pack($spec, $esm_class, $protocol_id, $priority_flag, $schedule_delivery_time, $validity_period, $registered_delivery_flag, $replace_if_present_flag, $data_coding, $sm_default_msg_id, $sm_length, $short_message); $this->debug("\nMulti PDU: "); for ($i = 0; $i < strlen($pdu); $i++) { if (ord($pdu[$i]) < 32) $this->debug("."); else $this->debug($pdu[$i]); } $this->debug("\n"); $status = $this->SendPDU(CM_SUBMIT_MULTI, $pdu); return $status; } function split_message($text) { $this->debug("In split_message.\n"); $max_len = 153; $res = array(); if (strlen($text) <= 160) { $this->debug("One message: " . strlen($text) . "\n"); $res[] = $text; return $res; } $pos = 0; $msg_sequence = $this->_message_sequence++; $num_messages = ceil(strlen($text) / $max_len); $part_no = 1; while ($pos < strlen($text)) { $ttext = substr($text, $pos, $max_len); $pos += strlen($ttext); $udh = pack("cccccc", 5, 0, 3, $msg_sequence, $num_messages, $part_no); $part_no++; $res[] = $udh . $ttext; $this->debug("Split: UDH = "); for ($i = 0; $i < strlen($udh); $i++) { $this->debug(ord($udh[$i]) . " "); } $this->debug("\n"); $this->debug("Split: $ttext.\n"); } return $res; } function split_message_unicode($text) { $this->debug("In split_message.\n"); $max_len = 134; $res = array(); if (mb_strlen($text) <= 140) { $this->debug("One message: " . mb_strlen($text) . "\n"); $res[] = $text; return $res; } $pos = 0; $msg_sequence = $this->_message_sequence++; $num_messages = ceil(mb_strlen($text) / $max_len); $part_no = 1; while ($pos < mb_strlen($text)) { $ttext = mb_substr($text, $pos, $max_len); $pos += mb_strlen($ttext); $udh = pack("cccccc", 5, 0, 3, $msg_sequence, $num_messages, $part_no); $part_no++; $res[] = $udh . $ttext; $this->debug("Split: UDH = "); for ($i = 0; $i < strlen($udh); $i++) { $this->debug(ord($udh[$i]) . " "); } $this->debug("\n"); $this->debug("Split: $ttext.\n"); } return $res; } function unpack2($spec, $data) { $res = array(); $specs = explode("/", $spec); $pos = 0; reset($specs); while (list(, $sp) = each($specs)) { $subject = substr($data, $pos); $type = substr($sp, 0, 1); $var = substr($sp, 1); switch ($type) { case "N": $temp = unpack("Ntemp2", $subject); $res[$var] = $temp["temp2"]; $pos += 4; break; case "c": $temp = unpack("ctemp2", $subject); $res[$var] = $temp["temp2"]; $pos += 1; break; case "a": $pos2 = strpos($subject, chr(0)) + 1; $temp = unpack("a{$pos2}temp2", $subject); $res[$var] = $temp["temp2"]; $pos += $pos2; break; } } return $res; } function debug($str) { if ($this->_debug) { echo $str; } } }; ?>