PHP 7bit PDU generator
From D3xt3r01.tk
WHY
Because I needed something to be able to generate PDUs for my GSM modem in PHP. I only did the 7bit part because I wanted the 160 chars and I don't use any weird alphabet. This thing should give you a pretty good idea of how stuff is done !
SOURCE
<?php
function phoneNumberMap($char){
if($char >= "0" && $char <= "9"){
return $char;
}
switch(strtoupper($char)){
case "*":
return "A";
break;
case "#":
return "B";
break;
case "A":
return "C";
break;
case "B":
return "D";
break;
case "C":
return "E";
break;
default:
return 'F';
}
return "F";
}
function semiOctetToString($string){
$strlen = strlen($string);
$out = '';
for($i=0;$i<$strlen;$i += 2){
$temp = substr($string, $i, $i+2);
$out = $out.phoneNumberMap($temp{1}).phoneNumberMap($temp{0});
}
return $out;
}
function getSevenBit($char){
$sevenbitdefault = array('@', '�', '$', '�', '�', '�', '�', '�', '�', '�', '\n', '�', '�', '\r', '�', '�', '\u0394', '_', '\u03a6', '\u0393', '\u039b', '\u03a9', '\u03a0', '\u03a8', '\u03a3', '\u0398', '\u039e', '�', '�', '�', '�', '�', ' ', '!', '"', '#', '�', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7','8', '9', ':', ';', '<', '=', '>', '?', '�', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '�', '�', '�', '�', '�', '�', 'a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '�', '�', '�', '�', '�');
$strlen = count($sevenbitdefault);
for($i=0;$i<$strlen;$i++){
if($sevenbitdefault[$i] == $char){
return $i;
}
}
return 0;
}
function parseInt($string){
if(preg_match('/(\d+)/', $string, $array)){
return $array[1];
}else{
return 0;
}
}
function str2bin($str){
$out = false;
for($a=0; $a < strlen($str); $a++) {
$dec = ord(substr($str,$a,1));
$bin = '';
for($i=7; $i>=0; $i--) {
if ( $dec >= pow(2, $i) ) {
$bin .= "1";
$dec -= pow(2, $i);
} else {
$bin .= "0";
}
}
$out .= $bin;
}
return $out;
}
function intToBin($x, $size){
$base = "2";
$num = parseInt($x);
$bin = decbin($num);
for($i=strlen($bin);$i<$size;$i++){
$bin = "0".$bin;
}
return $bin;
}
function getEightBit($char){
return $char;
}
function get16Bit($char){
return $char;
}
function genPDU($message, $destinationNumber, $smscNumber, $receipt = 0, $validity = 0, $valid_period = "", $mclass = -1){
// mclass : -1,0,1,2,3
// validity : 0,1
// receipt : 0,1
$output = '';
$octetSecond = '';
if(strlen($smscNumber) != 0){
$smsc_number_format = "81";
if(substr($smscNumber, 0, 1) == "+"){
$smsc_number_format = "91";
$smscNumber = substr($smscNumber, 1);
}else if(substr($smscNumber, 0, 1) != "0"){
$smsc_number_format = "91";
}
if(strlen($smscNumber) % 2 != 0){
$smscNumber .= "F";
}
}
$smsc = semiOctetToString($smscNumber);
$smsc_info_length = strlen($smsc_number_format.$smsc)/2;
$smsc_length = $smsc_info_length;
if($smsc_info_length < 10){
$smsc_info_length = "0".$smsc_info_length;
}
if($receipt == 1){
if($validity == 1){
$firstOctet = "3100";
}else{
$firstOctet = "2100";
}
}else{
if($validity == 1){
$firstOctet = "1100";
}else{
$firstOctet = "0100";
}
}
if(strlen($destinationNumber) != 0){
$destination_number_format = "81";
if(substr($destinationNumber, 0, 1) == "+"){
$destination_number_format = "91";
$destinationNumber = substr($destinationNumber, 1);
}else if(substr($destinationNumber, 0, 1) != "0"){
$destination_number_format = "91";
}
$destination_number_length = dechex(strlen($destinationNumber));
if(strlen($destinationNumber) % 2 != 0){
$destinationNumber .= "F";
}
}
if(strlen($destination_number_length) < 10){
$destination_number_length = "0".$destination_number_length;
}
$destinationNumber = semiOctetToString($destinationNumber);
$proto_id = '00';
$dcs = 0;
if($mclass != "-1"){
$dcs = $mclass+16;
}
$data_encoding = dechex($dcs);
if(strlen($data_encoding) == 1){
$data_encoding = "0".$data_encoding;
}
if($validity == 1){
$valid_period = dechex($valid_period);
}
$user_data_size = base_convert(strlen($message), 10, 16);
if(strlen($user_data_size) == 1){
$user_data_size = "0".$user_data_size;
}
$strlen = strlen($message);
$octetSecond = '';
for($i=0;$i<=$strlen;$i++){
if($i == $strlen){
if($octetSecond != ""){
$b2d = dechex(bindec($octetSecond));
if(strlen($b2d) == 1){
$b2d = "0".$b2d;
}
$output = $output.$b2d;
}
break;
}
$current = intToBin(getSevenBit($message{$i}), 7);
if($i != 0 && $i % 8 != 0){
$octetFirst = substr($current,7-($i)%8);
$currentOctet = $octetFirst.$octetSecond;
$d2h = dechex(bindec($currentOctet));
if(strlen($d2h) == 1){
$d2h = "0".$d2h;
}
$output = $output.$d2h;
$octetSecond = substr($current,0,7-($i)%8);
}else{
$octetSecond = substr($current,0,7-($i)%8);
}
}
$header = strtoupper($smsc_info_length.$smsc_number_format.$smsc.$firstOctet.$destination_number_length.$destination_number_format.$destinationNumber.$proto_id.$data_encoding.$valid_period.$user_data_size);
$pdu = $header.$output;
echo "HEADER:\n";
echo "Smsc Info Length: ".$smsc_info_length."\n";
echo "Smsc Number Format: ".$smsc_number_format."\n";
echo "Smsc: ".$smsc."\n";
echo "FirstOctet: ".$firstOctet."\n";
echo "Destination Number Length: ".$destination_number_length."\n";
echo "Destination Number Format: ".$destination_number_format."\n";
echo "Destination Number: ".$destinationNumber."\n";
echo "Proto ID: ".$proto_id."\n";
echo "Data Encoding: ".$data_encoding."\n";
echo "Valid Period: ".$valid_period."\n";
echo "User Data Size: ".$user_data_size."\n";
echo "------------------\n";
echo "DCS: ".$dcs."\n";
echo "Header: ".$header."\n";
echo "Output: ".$output."\n";
echo "PDU: ".strtoupper($pdu)."\n";
echo "AT+CMGS=".(strlen($pdu)/2 - $smsc_length -1)."\n";
}
genPDU($argv[1], "0760905294", "+40766000510", 0, 0, "", 0);
?>
THANKS
Big THANKS go to Rednaxela's Javascript PDU converter.