📄 pdu.c
字号:
/*SMS Server Tools 3Copyright (C) Keijo Kasvihttp://smstools3.kekekasvi.com/Based on SMS Server Tools 2 from Stefan Fringshttp://www.meinemullemaus.de/This program is free software unless you got it under another license directlyfrom the author. You can redistribute it and/or modify it under the terms ofthe GNU General Public License as published by the Free Software Foundation.Either version 2 of the License, or (at your option) any later version.*/#include <string.h>#include <stdio.h>#include <stdarg.h>#include <stdlib.h>#include <ctype.h>#include <syslog.h>#include "pdu.h"#include "smsd_cfg.h"#include "logging.h"#include "charset.h" // required for conversions of partial text content.#define MAX_ADDRESS_LENGTH 50#define MAX_SMSC_ADDRESS_LENGTH 30char *err_too_short = "string is too short";char *err_pdu_content = "invalid character(s) in string";int add_warning(char *buffer, char *format, ...){ int result = 1; va_list argp; char text[2048]; char *title = "Warning: "; va_start(argp, format); vsnprintf(text, sizeof(text), format, argp); va_end(argp); if (buffer) { if (strlen(buffer) + strlen(text) +strlen(title) +1/* for \n */ < SIZE_WARNING_HEADERS) sprintf(strchr(buffer, 0), "%s%s\n", title, text); else { result = 0; writelogfile(LOG_ERR, process_title, "PDU %s%s", title, text); } } return result;}void pdu_error(char **err_str, char *title, int position, int length, char *format, ...){ va_list argp; char text[2048]; char *default_title = "PDU ERROR: "; char *used_title; char tmp[51]; va_start(argp, format); vsnprintf(text, sizeof(text), format, argp); va_end(argp); used_title = (title)? title : default_title; if (position >= 0) { if (length > 0) sprintf(tmp, "Position %i,%i: ", position +1, length); else sprintf(tmp, "Position %i: ", position +1); } else *tmp = 0; if (!(*err_str)) { if ((*err_str = (char *)malloc(strlen(tmp) +strlen(text) +strlen(used_title) +2))) *err_str[0] = 0; } else *err_str = (char *)realloc((void *)*err_str, strlen(*err_str) +strlen(used_title) +strlen(tmp) +strlen(text) +2); if (*err_str) sprintf(strchr(*err_str, 0), "%s%s%s\n", used_title, tmp, text);}int isXdigit(char ch){ if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F')) return 1; return 0;}/* Swap every second character */void swapchars(char* string) { int Length; int position; char c; Length=strlen(string); for (position=0; position<Length-1; position+=2) { c=string[position]; string[position]=string[position+1]; string[position+1]=c; }}// Converts an ascii text to a pdu string // text might contain zero values because this is a valid character code in sms// character set. Therefore we need the length parameter.// If udh is not 0, then insert it to the beginning of the message.// The string must be in hex-dump format: "05 00 03 AF 02 01". // The first byte is the size of the UDH.int text2pdu(char* text, int length, char* pdu, char* udh){ char tmp[500]; char octett[10]; int pdubitposition; int pdubyteposition=0; int character; int bit; int pdubitnr; int counted_characters=0; int udh_size_octets; // size of the udh in octets, should equal to the first byte + 1 int udh_size_septets; // size of udh in septets (7bit text characters) int fillbits; // number of filler bits between udh and ud. int counter;#ifdef DEBUGMSG printf("!! text2pdu(text=..., length=%i, pdu=..., udh=%s\n",length,udh);#endif pdu[0]=0; // Check the udh if (udh) { udh_size_octets=(strlen(udh)+2)/3; udh_size_septets=((udh_size_octets)*8+6)/7; fillbits=7-(udh_size_octets % 7); if (fillbits==7) fillbits=0; // copy udh to pdu, skipping the space characters for (counter=0; counter<udh_size_octets; counter++) { pdu[counter*2]=udh[counter*3]; pdu[counter*2+1]=udh[counter*3+1]; } pdu[counter*2]=0;#ifdef DEBUGMSG printf("!! pdu=%s, fillbits=%i\n",pdu,fillbits);#endif } else { udh_size_octets=0; udh_size_septets=0; fillbits=0; } // limit size of the message to maximum allowed size if (length>maxsms_pdu-udh_size_septets) length=maxsms_pdu-udh_size_septets; //clear the tmp buffer for (character=0;character<sizeof(tmp);character++) tmp[character]=0; // Convert 8bit text stream to 7bit stream for (character=0;character<length;character++) { counted_characters++; for (bit=0;bit<7;bit++) { pdubitnr=7*character+bit+fillbits; pdubyteposition=pdubitnr/8; pdubitposition=pdubitnr%8; if (text[character] & (1<<bit)) tmp[pdubyteposition]=tmp[pdubyteposition] | (1<<pdubitposition); else tmp[pdubyteposition]=tmp[pdubyteposition] & ~(1<<pdubitposition); } } tmp[pdubyteposition+1]=0; // convert 7bit stream to hex-dump for (character=0;character<=pdubyteposition; character++) { sprintf(octett,"%02X",(unsigned char) tmp[character]); strcat(pdu,octett); }#ifdef DEBUGMSG printf("!! pdu=%s\n",pdu);#endif return counted_characters+udh_size_septets;}/* Converts binary to PDU string, this is basically a hex dump. */void binary2pdu(char* binary, int length, char* pdu){ int character; char octett[10]; if (length>maxsms_binary) length=maxsms_binary; pdu[0]=0; for (character=0;character<length; character++) { sprintf(octett,"%02X",(unsigned char) binary[character]); strcat(pdu,octett); }}// Make the PDU string from a mesage text and destination phone number.// The destination variable pdu has to be big enough. // alphabet indicates the character set of the message.// flash_sms enables the flash flag.// mode select the pdu version (old or new).// if udh is true, then udh_data contains the optional user data header in hex dump, example: "05 00 03 AF 02 01"void make_pdu(char* number, char* message, int messagelen, int alphabet, int flash_sms, int report, int with_udh, char* udh_data, char* mode, char* pdu, int validity, int replace_msg){ int coding; int flags; char tmp[50]; char tmp2[500]; int numberformat; int numberlength; char *p; int l; if (number[0]=='s') // Is number starts with s, then send it without number format indicator { numberformat=129; strcpy(tmp,number+1); } else { numberformat=145; strcpy(tmp,number); } numberlength=strlen(tmp); // terminate the number with F if the length is odd if (numberlength%2) strcat(tmp,"F"); // Swap every second character swapchars(tmp); flags=1; // SMS-Sumbit MS to SMSC if (with_udh) flags+=64; // User Data Header if (strcmp(mode,"old")!=0) flags+=16; // Validity field if (report>0) flags+=32; // Request Status Report if (alphabet == 1) coding = 4; // 8bit binary else if (alphabet == 2) coding = 8; // 16bit else coding = 0; // 7bit if (flash_sms > 0) coding += 0x10; // Bits 1 and 0 have a message class meaning (class 0, alert) /* Create the PDU string of the message */ if (alphabet==1 || alphabet==2) { // Unicode message can be concatenated: //if (alphabet == 2 && with_udh) // Binary message can be concatenated too: if (with_udh) { strcpy(tmp2, udh_data); while ((p = strchr(tmp2, ' '))) strcpy(p, p +1); l = strlen(tmp2) /2; binary2pdu(message, messagelen, strchr(tmp2, 0)); messagelen += l; } else binary2pdu(message,messagelen,tmp2); } else messagelen=text2pdu(message,messagelen,tmp2,udh_data); /* concatenate the first part of the PDU string */ if (strcmp(mode,"old")==0) sprintf(pdu,"%02X00%02X%02X%s00%02X%02X",flags,numberlength,numberformat,tmp,coding,messagelen); else { if (validity < 0 || validity > 255) validity = validity_period; sprintf(pdu, "00%02X00%02X%02X%s%02X%02X%02X%02X", flags, numberlength, numberformat, tmp, (replace_msg >= 1 && replace_msg <= 7)? 0x40 +replace_msg : 0, coding, validity, messagelen); } /* concatenate the text to the PDU string */ strcat(pdu,tmp2);}int octet2bin(char* octet) /* converts an octet to a 8-Bit value */{ int result=0; if (octet[0]>57) result+=octet[0]-55; else result+=octet[0]-48; result=result<<4; if (octet[1]>57) result+=octet[1]-55; else result+=octet[1]-48; return result;}// Converts an octet to a 8bit value,// returns < in case of error.int octet2bin_check(char *octet){ if (octet[0] == 0) return -1; if (octet[1] == 0) return -2; if (!isXdigit(octet[0])) return -3; if (!isXdigit(octet[1])) return -4; return octet2bin(octet);}// Return value: -1 = error, 0 = not found.// 1 = found 8bit, 2 = found 16bit.// udh must be in header format, "05 00 03 02 03 02 "int get_remove_concatenation(char *udh, int *message_id, int *parts, int *part){ int udh_length; int octets; int idx; char *con_start = NULL; int id; int i; char tmp[10]; if ((udh_length = octet2bin_check(udh)) < 0) return -1; octets = strlen(udh) /3; idx = 1; while (idx < octets) { if ((id = octet2bin_check(udh +idx *2 +idx)) < 0) return -1; if (id == 0x00 || id == 0x08) { // It's here. con_start = udh +idx *2 +idx; if (++idx >= octets) return -1; i = octet2bin_check(udh +idx *2 +idx); if ((id == 0x00 && i != 0x03) || (id == 0x08 && i != 0x04)) return -1; if (++idx >= octets) return -1; if ((*message_id = octet2bin_check(udh +idx *2 +idx)) < 0) return -1; if (id == 0x08) { if (++idx >= octets) return -1; if ((i = octet2bin_check(udh +idx *2 +idx)) < 0) return -1; *message_id = *message_id *0xFF +i; } if (++idx >= octets) return -1; if ((*parts = octet2bin_check(udh +idx *2 +idx)) < 0) return -1; if (++idx >= octets) return -1; if ((*part = octet2bin_check(udh +idx *2 +idx)) < 0) return -1; if (++idx >= octets) *con_start = 0; else strcpy(con_start, udh +idx *2 +idx); i = (id == 0x00)? 5 : 6; udh_length -= i; if (udh_length > 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -