00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "asterisk.h"
00026
00027 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 107461 $")
00028
00029 #include <stdlib.h>
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <unistd.h>
00033 #include <errno.h>
00034 #include <dirent.h>
00035 #include <ctype.h>
00036 #include <sys/types.h>
00037 #include <sys/stat.h>
00038
00039 #include "asterisk/lock.h"
00040 #include "asterisk/file.h"
00041 #include "asterisk/logger.h"
00042 #include "asterisk/options.h"
00043 #include "asterisk/channel.h"
00044 #include "asterisk/pbx.h"
00045 #include "asterisk/module.h"
00046 #include "asterisk/alaw.h"
00047 #include "asterisk/callerid.h"
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 static volatile unsigned char message_ref;
00059 static volatile unsigned int seq;
00060
00061 static char log_file[255];
00062 static char spool_dir[255];
00063
00064 static char *app = "SMS";
00065
00066 static char *synopsis = "Communicates with SMS service centres and SMS capable analogue phones";
00067
00068 static char *descrip =
00069 " SMS(name|[a][s]): SMS handles exchange of SMS data with a call to/from SMS capabale\n"
00070 "phone or SMS PSTN service center. Can send and/or receive SMS messages.\n"
00071 "Works to ETSI ES 201 912 compatible with BT SMS PSTN service in UK\n"
00072 "Typical usage is to use to handle called from the SMS service centre CLI,\n"
00073 "or to set up a call using 'outgoing' or manager interface to connect\n"
00074 "service centre to SMS()\n"
00075 "name is the name of the queue used in /var/spool/asterisk/sms\n"
00076 "Arguments:\n"
00077 " a: answer, i.e. send initial FSK packet.\n"
00078 " s: act as service centre talking to a phone.\n"
00079 "Messages are processed as per text file message queues.\n"
00080 "smsq (a separate software) is a command to generate message\n"
00081 "queues and send messages.\n";
00082
00083 static signed short wave[] = {
00084 0, 392, 782, 1167, 1545, 1913, 2270, 2612, 2939, 3247, 3536, 3802, 4045, 4263, 4455, 4619, 4755, 4862, 4938, 4985,
00085 5000, 4985, 4938, 4862, 4755, 4619, 4455, 4263, 4045, 3802, 3536, 3247, 2939, 2612, 2270, 1913, 1545, 1167, 782, 392,
00086 0, -392, -782, -1167,
00087 -1545, -1913, -2270, -2612, -2939, -3247, -3536, -3802, -4045, -4263, -4455, -4619, -4755, -4862, -4938, -4985, -5000,
00088 -4985, -4938, -4862,
00089 -4755, -4619, -4455, -4263, -4045, -3802, -3536, -3247, -2939, -2612, -2270, -1913, -1545, -1167, -782, -392
00090 };
00091
00092 #ifdef OUTALAW
00093 static unsigned char wavea[80];
00094 #endif
00095
00096
00097
00098 static const unsigned short defaultalphabet[] = {
00099 0x0040, 0x00A3, 0x0024, 0x00A5, 0x00E8, 0x00E9, 0x00F9, 0x00EC,
00100 0x00F2, 0x00E7, 0x000A, 0x00D8, 0x00F8, 0x000D, 0x00C5, 0x00E5,
00101 0x0394, 0x005F, 0x03A6, 0x0393, 0x039B, 0x03A9, 0x03A0, 0x03A8,
00102 0x03A3, 0x0398, 0x039E, 0x00A0, 0x00C6, 0x00E6, 0x00DF, 0x00C9,
00103 ' ', '!', '"', '#', 164, '%', '&', 39, '(', ')', '*', '+', ',', '-', '.', '/',
00104 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?',
00105 161, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
00106 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 196, 214, 209, 220, 167,
00107 191, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
00108 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 228, 246, 241, 252, 224,
00109 };
00110
00111 static const unsigned short escapes[] = {
00112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x000C, 0, 0, 0, 0, 0,
00113 0, 0, 0, 0, 0x005E, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00114 0, 0, 0, 0, 0, 0, 0, 0, 0x007B, 0x007D, 0, 0, 0, 0, 0, 0x005C,
00115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x005B, 0x007E, 0x005D, 0,
00116 0x007C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00118 0, 0, 0, 0, 0, 0x20AC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00120 };
00121
00122 #define SMSLEN 160
00123
00124 typedef struct sms_s
00125 {
00126 unsigned char hangup;
00127 unsigned char err;
00128 unsigned char smsc:1;
00129 unsigned char rx:1;
00130 char queue[30];
00131 char oa[20];
00132 char da[20];
00133 time_t scts;
00134 unsigned char pid;
00135 unsigned char dcs;
00136 short mr;
00137 int udl;
00138 int udhl;
00139 unsigned char srr:1;
00140 unsigned char udhi:1;
00141 unsigned char rp:1;
00142 unsigned int vp;
00143 unsigned short ud[SMSLEN];
00144 unsigned char udh[SMSLEN];
00145 char cli[20];
00146 unsigned char ophase;
00147 unsigned char ophasep;
00148 unsigned char obyte;
00149 unsigned int opause;
00150 unsigned char obitp;
00151 unsigned char osync;
00152 unsigned char obytep;
00153 unsigned char obyten;
00154 unsigned char omsg[256];
00155 unsigned char imsg[200];
00156 signed long long ims0,
00157 imc0,
00158 ims1,
00159 imc1;
00160 unsigned int idle;
00161 unsigned short imag;
00162 unsigned char ips0,
00163 ips1,
00164 ipc0,
00165 ipc1;
00166 unsigned char ibitl;
00167 unsigned char ibitc;
00168 unsigned char iphasep;
00169 unsigned char ibitn;
00170 unsigned char ibytev;
00171 unsigned char ibytep;
00172 unsigned char ibytec;
00173 unsigned char ierr;
00174 unsigned char ibith;
00175 unsigned char ibitt;
00176
00177 } sms_t;
00178
00179
00180 #define is7bit(dcs) (((dcs)&0xC0)?(!((dcs)&4)):(!((dcs)&12)))
00181 #define is8bit(dcs) (((dcs)&0xC0)?(((dcs)&4)):(((dcs)&12)==4))
00182 #define is16bit(dcs) (((dcs)&0xC0)?0:(((dcs)&12)==8))
00183
00184 static void *sms_alloc (struct ast_channel *chan, void *params)
00185 {
00186 return params;
00187 }
00188
00189 static void sms_release (struct ast_channel *chan, void *data)
00190 {
00191 return;
00192 }
00193
00194 static void sms_messagetx (sms_t * h);
00195
00196
00197 static void numcpy (char *d, char *s)
00198 {
00199 if (*s == '+')
00200 *d++ = *s++;
00201 while (*s) {
00202 if (isdigit (*s))
00203 *d++ = *s;
00204 s++;
00205 }
00206 *d = 0;
00207 }
00208
00209
00210 static char * isodate (time_t t)
00211 {
00212 static char date[20];
00213 strftime (date, sizeof (date), "%Y-%m-%dT%H:%M:%S", localtime (&t));
00214 return date;
00215 }
00216
00217
00218
00219
00220 static long utf8decode (unsigned char **pp)
00221 {
00222 unsigned char *p = *pp;
00223 if (!*p)
00224 return 0;
00225 (*pp)++;
00226 if (*p < 0xC0)
00227 return *p;
00228 if (*p < 0xE0) {
00229 if (*p < 0xC2 || (p[1] & 0xC0) != 0x80)
00230 return *p;
00231 (*pp)++;
00232 return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
00233 }
00234 if (*p < 0xF0) {
00235 if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80)
00236 return *p;
00237 (*pp) += 2;
00238 return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
00239 }
00240 if (*p < 0xF8) {
00241 if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80)
00242 return *p;
00243 (*pp) += 3;
00244 return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
00245 }
00246 if (*p < 0xFC) {
00247 if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00248 || (p[4] & 0xC0) != 0x80)
00249 return *p;
00250 (*pp) += 4;
00251 return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
00252 }
00253 if (*p < 0xFE) {
00254 if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
00255 || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80)
00256 return *p;
00257 (*pp) += 5;
00258 return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) + (p[5] & 0x3F);
00259 }
00260 return *p;
00261 }
00262
00263
00264
00265
00266
00267 static int packsms7 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00268 {
00269 unsigned char p = 0, b = 0, n = 0;
00270
00271 if (udhl) {
00272 if (o)
00273 o[p++] = udhl;
00274 b = 1;
00275 n = 1;
00276 while (udhl--) {
00277 if (o)
00278 o[p++] = *udh++;
00279 b += 8;
00280 while (b >= 7) {
00281 b -= 7;
00282 n++;
00283 }
00284 if (n >= SMSLEN)
00285 return n;
00286 }
00287 if (b) {
00288 b = 7 - b;
00289 if (++n >= SMSLEN)
00290 return n;
00291 };
00292 }
00293 if (o)
00294 o[p] = 0;
00295
00296 while (udl--) {
00297 long u;
00298 unsigned char v;
00299 u = *ud++;
00300 for (v = 0; v < 128 && defaultalphabet[v] != u; v++);
00301 if (v == 128 && u && n + 1 < SMSLEN) {
00302 for (v = 0; v < 128 && escapes[v] != u; v++);
00303 if (v < 128) {
00304 if (o)
00305 o[p] |= (27 << b);
00306 b += 7;
00307 if (b >= 8) {
00308 b -= 8;
00309 p++;
00310 if (o)
00311 o[p] = (27 >> (7 - b));
00312 }
00313 n++;
00314 }
00315 }
00316 if (v == 128)
00317 return -1;
00318 if (o)
00319 o[p] |= (v << b);
00320 b += 7;
00321 if (b >= 8) {
00322 b -= 8;
00323 p++;
00324 if (o)
00325 o[p] = (v >> (7 - b));
00326 }
00327 if (++n >= SMSLEN)
00328 return n;
00329 }
00330 return n;
00331 }
00332
00333
00334
00335
00336
00337 static int packsms8 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00338 {
00339 unsigned char p = 0;
00340
00341
00342 if (udhl) {
00343 if (o)
00344 o[p++] = udhl;
00345 while (udhl--) {
00346 if (o)
00347 o[p++] = *udh++;
00348 if (p >= 140)
00349 return p;
00350 }
00351 }
00352 while (udl--) {
00353 long u;
00354 u = *ud++;
00355 if (u < 0 || u > 0xFF)
00356 return -1;
00357 if (o)
00358 o[p++] = u;
00359 if (p >= 140)
00360 return p;
00361 }
00362 return p;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 static int packsms16 (unsigned char *o, int udhl, unsigned char *udh, int udl, unsigned short *ud)
00374 {
00375 unsigned char p = 0;
00376
00377 if (udhl) {
00378 if (o)
00379 o[p++] = udhl;
00380 while (udhl--) {
00381 if (o)
00382 o[p++] = *udh++;
00383 if (p >= 140)
00384 return p;
00385 }
00386 }
00387 while (udl--) {
00388 long u;
00389 u = *ud++;
00390 if (o)
00391 o[p++] = (u >> 8);
00392 if (p >= 140)
00393 return p - 1;
00394 if (o)
00395 o[p++] = u;
00396 if (p >= 140)
00397 return p;
00398 }
00399 return p;
00400 }
00401
00402
00403
00404 static int packsms (unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud)
00405 {
00406 unsigned char *p = base;
00407 if (udl) {
00408 int l = 0;
00409 if (is7bit (dcs)) {
00410 l = packsms7 (p + 1, udhl, udh, udl, ud);
00411 if (l < 0)
00412 l = 0;
00413 *p++ = l;
00414 p += (l * 7 + 7) / 8;
00415 } else if (is8bit (dcs)) {
00416 l = packsms8 (p + 1, udhl, udh, udl, ud);
00417 if (l < 0)
00418 l = 0;
00419 *p++ = l;
00420 p += l;
00421 } else {
00422 l = packsms16 (p + 1, udhl, udh, udl, ud);
00423 if (l < 0)
00424 l = 0;
00425 *p++ = l;
00426 p += l;
00427 }
00428 } else
00429 *p++ = 0;
00430 return p - base;
00431 }
00432
00433
00434
00435 static void packdate (unsigned char *o, time_t w)
00436 {
00437 struct tm *t = localtime (&w);
00438 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
00439 int z = -t->tm_gmtoff / 60 / 15;
00440 #else
00441 int z = timezone / 60 / 15;
00442 #endif
00443 *o++ = ((t->tm_year % 10) << 4) + (t->tm_year % 100) / 10;
00444 *o++ = (((t->tm_mon + 1) % 10) << 4) + (t->tm_mon + 1) / 10;
00445 *o++ = ((t->tm_mday % 10) << 4) + t->tm_mday / 10;
00446 *o++ = ((t->tm_hour % 10) << 4) + t->tm_hour / 10;
00447 *o++ = ((t->tm_min % 10) << 4) + t->tm_min / 10;
00448 *o++ = ((t->tm_sec % 10) << 4) + t->tm_sec / 10;
00449 if (z < 0)
00450 *o++ = (((-z) % 10) << 4) + (-z) / 10 + 0x08;
00451 else
00452 *o++ = ((z % 10) << 4) + z / 10;
00453 }
00454
00455
00456 static time_t unpackdate (unsigned char *i)
00457 {
00458 struct tm t;
00459 t.tm_year = 100 + (i[0] & 0xF) * 10 + (i[0] >> 4);
00460 t.tm_mon = (i[1] & 0xF) * 10 + (i[1] >> 4) - 1;
00461 t.tm_mday = (i[2] & 0xF) * 10 + (i[2] >> 4);
00462 t.tm_hour = (i[3] & 0xF) * 10 + (i[3] >> 4);
00463 t.tm_min = (i[4] & 0xF) * 10 + (i[4] >> 4);
00464 t.tm_sec = (i[5] & 0xF) * 10 + (i[5] >> 4);
00465 t.tm_isdst = 0;
00466 if (i[6] & 0x08)
00467 t.tm_min += 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00468 else
00469 t.tm_min -= 15 * ((i[6] & 0x7) * 10 + (i[6] >> 4));
00470 return ast_mktime(&t, NULL);
00471 }
00472
00473
00474
00475
00476 static void unpacksms7 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00477 {
00478 unsigned char b = 0, p = 0;
00479 unsigned short *o = ud;
00480 *udhl = 0;
00481 if (udhi && l) {
00482 int h = i[p];
00483 *udhl = h;
00484 if (h) {
00485 b = 1;
00486 p++;
00487 l--;
00488 while (h-- && l) {
00489 *udh++ = i[p++];
00490 b += 8;
00491 while (b >= 7) {
00492 b -= 7;
00493 l--;
00494 if (!l)
00495 break;
00496 }
00497 }
00498
00499 if (b) {
00500 b = 7 - b;
00501 l--;
00502 }
00503 }
00504 }
00505 while (l--) {
00506 unsigned char v;
00507 if (b < 2)
00508 v = ((i[p] >> b) & 0x7F);
00509 else
00510 v = ((((i[p] >> b) + (i[p + 1] << (8 - b)))) & 0x7F);
00511 b += 7;
00512 if (b >= 8) {
00513 b -= 8;
00514 p++;
00515 }
00516 if (o > ud && o[-1] == 0x00A0 && escapes[v])
00517 o[-1] = escapes[v];
00518 else
00519 *o++ = defaultalphabet[v];
00520 }
00521 *udl = (o - ud);
00522 }
00523
00524
00525
00526
00527 static void unpacksms8 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00528 {
00529 unsigned short *o = ud;
00530 *udhl = 0;
00531 if (udhi) {
00532 int n = *i;
00533 *udhl = n;
00534 if (n) {
00535 i++;
00536 l--;
00537 while (l && n) {
00538 l--;
00539 n--;
00540 *udh++ = *i++;
00541 }
00542 }
00543 }
00544 while (l--)
00545 *o++ = *i++;
00546 *udl = (o - ud);
00547 }
00548
00549
00550
00551
00552 static void unpacksms16 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00553 {
00554 unsigned short *o = ud;
00555 *udhl = 0;
00556 if (udhi) {
00557 int n = *i;
00558 *udhl = n;
00559 if (n) {
00560 i++;
00561 l--;
00562 while (l && n) {
00563 l--;
00564 n--;
00565 *udh++ = *i++;
00566 }
00567 }
00568 }
00569 while (l--) {
00570 int v = *i++;
00571 if (l--)
00572 v = (v << 8) + *i++;
00573 *o++ = v;
00574 }
00575 *udl = (o - ud);
00576 }
00577
00578
00579 static int unpacksms (unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
00580 {
00581 int l = *i++;
00582 if (is7bit (dcs)) {
00583 unpacksms7 (i, l, udh, udhl, ud, udl, udhi);
00584 l = (l * 7 + 7) / 8;
00585 } else if (is8bit (dcs))
00586 unpacksms8 (i, l, udh, udhl, ud, udl, udhi);
00587 else
00588 unpacksms16 (i, l, udh, udhl, ud, udl, udhi);
00589 return l + 1;
00590 }
00591
00592
00593 static unsigned char unpackaddress (char *o, unsigned char *i)
00594 {
00595 unsigned char l = i[0],
00596 p;
00597 if (i[1] == 0x91)
00598 *o++ = '+';
00599 for (p = 0; p < l; p++) {
00600 if (p & 1)
00601 *o++ = (i[2 + p / 2] >> 4) + '0';
00602 else
00603 *o++ = (i[2 + p / 2] & 0xF) + '0';
00604 }
00605 *o = 0;
00606 return (l + 5) / 2;
00607 }
00608
00609
00610 static unsigned char packaddress (unsigned char *o, char *i)
00611 {
00612 unsigned char p = 2;
00613 o[0] = 0;
00614 if (*i == '+') {
00615 i++;
00616 o[1] = 0x91;
00617 } else
00618 o[1] = 0x81;
00619 while (*i)
00620 if (isdigit (*i)) {
00621 if (o[0] & 1)
00622 o[p++] |= ((*i & 0xF) << 4);
00623 else
00624 o[p] = (*i & 0xF);
00625 o[0]++;
00626 i++;
00627 } else
00628 i++;
00629 if (o[0] & 1)
00630 o[p++] |= 0xF0;
00631 return p;
00632 }
00633
00634
00635 static void sms_log (sms_t * h, char status)
00636 {
00637 if (*h->oa || *h->da) {
00638 int o = open (log_file, O_CREAT | O_APPEND | O_WRONLY, 0666);
00639 if (o >= 0) {
00640 char line[1000], mrs[3] = "", *p;
00641 unsigned char n;
00642
00643 if (h->mr >= 0)
00644 snprintf (mrs, sizeof (mrs), "%02X", h->mr);
00645 snprintf (line, sizeof (line), "%s %c%c%c%s %s %s %s ",
00646 isodate (time (0)), status, h->rx ? 'I' : 'O', h->smsc ? 'S' : 'M', mrs, h->queue, *h->oa ? h->oa : "-",
00647 *h->da ? h->da : "-");
00648 p = line + strlen (line);
00649 for (n = 0; n < h->udl; n++)
00650 if (h->ud[n] == '\\') {
00651 *p++ = '\\';
00652 *p++ = '\\';
00653 } else if (h->ud[n] == '\n') {
00654 *p++ = '\\';
00655 *p++ = 'n';
00656 } else if (h->ud[n] == '\r') {
00657 *p++ = '\\';
00658 *p++ = 'r';
00659 } else if (h->ud[n] < 32 || h->ud[n] == 127)
00660 *p++ = 191;
00661 else
00662 *p++ = h->ud[n];
00663 *p++ = '\n';
00664 *p = 0;
00665 write (o, line, strlen (line));
00666 close (o);
00667 }
00668 *h->oa = *h->da = h->udl = 0;
00669 }
00670 }
00671
00672
00673 static void sms_readfile (sms_t * h, char *fn)
00674 {
00675 char line[1000];
00676 FILE *s;
00677 char dcsset = 0;
00678 ast_log (LOG_EVENT, "Sending %s\n", fn);
00679 h->rx = h->udl = *h->oa = *h->da = h->pid = h->srr = h->udhi = h->rp = h->vp = h->udhl = 0;
00680 h->mr = -1;
00681 h->dcs = 0xF1;
00682 h->scts = time (0);
00683 s = fopen (fn, "r");
00684 if (s)
00685 {
00686 if (unlink (fn))
00687 {
00688 fclose (s);
00689 return;
00690 }
00691 while (fgets (line, sizeof (line), s))
00692 {
00693 char *p;
00694 void *pp = &p;
00695 for (p = line; *p && *p != '\n' && *p != '\r'; p++);
00696 *p = 0;
00697 p = line;
00698 if (!*p || *p == ';')
00699 continue;
00700 while (isalnum (*p))
00701 {
00702 *p = tolower (*p);
00703 p++;
00704 }
00705 while (isspace (*p))
00706 *p++ = 0;
00707 if (*p == '=')
00708 {
00709 *p++ = 0;
00710 if (!strcmp (line, "ud"))
00711 {
00712 unsigned char o = 0;
00713 while (*p && o < SMSLEN)
00714 h->ud[o++] = utf8decode(pp);
00715 h->udl = o;
00716 if (*p)
00717 ast_log (LOG_WARNING, "UD too long in %s\n", fn);
00718 } else
00719 {
00720 while (isspace (*p))
00721 p++;
00722 if (!strcmp (line, "oa") && strlen (p) < sizeof (h->oa))
00723 numcpy (h->oa, p);
00724 else if (!strcmp (line, "da") && strlen (p) < sizeof (h->oa))
00725 numcpy (h->da, p);
00726 else if (!strcmp (line, "pid"))
00727 h->pid = atoi (p);
00728 else if (!strcmp (line, "dcs"))
00729 {
00730 h->dcs = atoi (p);
00731 dcsset = 1;
00732 } else if (!strcmp (line, "mr"))
00733 h->mr = atoi (p);
00734 else if (!strcmp (line, "srr"))
00735 h->srr = (atoi (p) ? 1 : 0);
00736 else if (!strcmp (line, "vp"))
00737 h->vp = atoi (p);
00738 else if (!strcmp (line, "rp"))
00739 h->rp = (atoi (p) ? 1 : 0);
00740 else if (!strcmp (line, "scts"))
00741 {
00742 int Y,
00743 m,
00744 d,
00745 H,
00746 M,
00747 S;
00748 if (sscanf (p, "%d-%d-%dT%d:%d:%d", &Y, &m, &d, &H, &M, &S) == 6)
00749 {
00750 struct tm t;
00751 t.tm_year = Y - 1900;
00752 t.tm_mon = m - 1;
00753 t.tm_mday = d;
00754 t.tm_hour = H;
00755 t.tm_min = M;
00756 t.tm_sec = S;
00757 t.tm_isdst = -1;
00758 h->scts = ast_mktime(&t, NULL);
00759 if (h->scts == (time_t) - 1)
00760 ast_log (LOG_WARNING, "Bad date/timein %s: %s", fn, p);
00761 }
00762 } else
00763 ast_log (LOG_WARNING, "Cannot parse in %s: %s=%si\n", fn, line, p);
00764 }
00765 } else if (*p == '#')
00766 {
00767 *p++ = 0;
00768 if (*p == '#')
00769 {
00770 p++;
00771 if (!strcmp (line, "ud"))
00772 {
00773 int o = 0;
00774 while (*p && o < SMSLEN)
00775 {
00776 if (isxdigit (*p) && isxdigit (p[1]) && isxdigit (p[2]) && isxdigit (p[3]))
00777 {
00778 h->ud[o++] =
00779 (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 12) +
00780 (((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
00781 (((isalpha (p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha (p[3]) ? 9 : 0) + (p[3] & 0xF));
00782 p += 4;
00783 } else
00784 break;
00785 }
00786 h->udl = o;
00787 if (*p)
00788 ast_log (LOG_WARNING, "UD too long / invalid UCS-2 hex in %s\n", fn);
00789 } else
00790 ast_log (LOG_WARNING, "Only ud can use ## format, %s\n", fn);
00791 } else if (!strcmp (line, "ud"))
00792 {
00793 int o = 0;
00794 while (*p && o < SMSLEN)
00795 {
00796 if (isxdigit (*p) && isxdigit (p[1]))
00797 {
00798 h->ud[o++] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
00799 p += 2;
00800 } else
00801 break;
00802 }
00803 h->udl = o;
00804 if (*p)
00805 ast_log (LOG_WARNING, "UD too long / invalid UCS-1 hex in %s\n", fn);
00806 } else if (!strcmp (line, "udh"))
00807 {
00808 unsigned char o = 0;
00809 h->udhi = 1;
00810 while (*p && o < SMSLEN)
00811 {
00812 if (isxdigit (*p) && isxdigit (p[1]))
00813 {
00814 h->udh[o] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
00815 o++;
00816 p += 2;
00817 } else
00818 break;
00819 }
00820 h->udhl = o;
00821 if (*p)
00822 ast_log (LOG_WARNING, "UDH too long / invalid hex in %s\n", fn);
00823 } else
00824 ast_log (LOG_WARNING, "Only ud and udh can use # format, %s\n", fn);
00825 } else
00826 ast_log (LOG_WARNING, "Cannot parse in %s: %s\n", fn, line);
00827 }
00828 fclose (s);
00829 if (!dcsset && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00830 {
00831 if (packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00832 {
00833 if (packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00834 ast_log (LOG_WARNING, "Invalid UTF-8 message even for UCS-2 (%s)\n", fn);
00835 else
00836 {
00837 h->dcs = 0x08;
00838 ast_log (LOG_WARNING, "Sending in 16 bit format (%s)\n", fn);
00839 }
00840 } else
00841 {
00842 h->dcs = 0xF5;
00843 ast_log (LOG_WARNING, "Sending in 8 bit format (%s)\n", fn);
00844 }
00845 }
00846 if (is7bit (h->dcs) && packsms7 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00847 ast_log (LOG_WARNING, "Invalid 7 bit GSM data %s\n", fn);
00848 if (is8bit (h->dcs) && packsms8 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00849 ast_log (LOG_WARNING, "Invalid 8 bit data %s\n", fn);
00850 if (is16bit (h->dcs) && packsms16 (0, h->udhl, h->udh, h->udl, h->ud) < 0)
00851 ast_log (LOG_WARNING, "Invalid 16 bit data %s\n", fn);
00852 }
00853 }
00854
00855
00856 static void sms_writefile (sms_t * h)
00857 {
00858 char fn[200] = "", fn2[200] = "";
00859 FILE *o;
00860 ast_copy_string (fn, spool_dir, sizeof (fn));
00861 mkdir (fn, 0777);
00862 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx");
00863 mkdir (fn, 0777);
00864 ast_copy_string (fn2, fn, sizeof (fn2));
00865 snprintf (fn2 + strlen (fn2), sizeof (fn2) - strlen (fn2), "/%s.%s-%d", h->queue, isodate (h->scts), seq++);
00866 snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/.%s", fn2 + strlen (fn) + 1);
00867 o = fopen (fn, "w");
00868 if (o) {
00869 if (*h->oa)
00870 fprintf (o, "oa=%s\n", h->oa);
00871 if (*h->da)
00872 fprintf (o, "da=%s\n", h->da);
00873 if (h->udhi) {
00874 unsigned int p;
00875 fprintf (o, "udh#");
00876 for (p = 0; p < h->udhl; p++)
00877 fprintf (o, "%02X", h->udh[p]);
00878 fprintf (o, "\n");
00879 }
00880 if (h->udl) {
00881 unsigned int p;
00882 for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
00883 if (p < h->udl)
00884 fputc (';', o);
00885 fprintf (o, "ud=");
00886 for (p = 0; p < h->udl; p++) {
00887 unsigned short v = h->ud[p];
00888 if (v < 32)
00889 fputc (191, o);
00890 else if (v < 0x80)
00891 fputc (v, o);
00892 else if (v < 0x800)
00893 {
00894 fputc (0xC0 + (v >> 6), o);
00895 fputc (0x80 + (v & 0x3F), o);
00896 } else
00897 {
00898 fputc (0xE0 + (v >> 12), o);
00899 fputc (0x80 + ((v >> 6) & 0x3F), o);
00900 fputc (0x80 + (v & 0x3F), o);
00901 }
00902 }
00903 fprintf (o, "\n");
00904 for (p = 0; p < h->udl && h->ud[p] >= ' '; p++);
00905 if (p < h->udl) {
00906 for (p = 0; p < h->udl && h->ud[p] < 0x100; p++);
00907 if (p == h->udl) {
00908 fprintf (o, "ud#");
00909 for (p = 0; p < h->udl; p++)
00910 fprintf (o, "%02X", h->ud[p]);
00911 fprintf (o, "\n");
00912 } else {
00913 fprintf (o, "ud##");
00914 for (p = 0; p < h->udl; p++)
00915 fprintf (o, "%04X", h->ud[p]);
00916 fprintf (o, "\n");
00917 }
00918 }
00919 }
00920 if (h->scts)
00921 fprintf (o, "scts=%s\n", isodate (h->scts));
00922 if (h->pid)
00923 fprintf (o, "pid=%d\n", h->pid);
00924 if (h->dcs != 0xF1)
00925 fprintf (o, "dcs=%d\n", h->dcs);
00926 if (h->vp)
00927 fprintf (o, "vp=%d\n", h->vp);
00928 if (h->srr)
00929 fprintf (o, "srr=1\n");
00930 if (h->mr >= 0)
00931 fprintf (o, "mr=%d\n", h->mr);
00932 if (h->rp)
00933 fprintf (o, "rp=1\n");
00934 fclose (o);
00935 if (rename (fn, fn2))
00936 unlink (fn);
00937 else
00938 ast_log (LOG_EVENT, "Received to %s\n", fn2);
00939 }
00940 }
00941
00942
00943 static struct dirent *readdirqueue (DIR * d, char *queue)
00944 {
00945 struct dirent *f;
00946 do {
00947 f = readdir (d);
00948 } while (f && (*f->d_name == '.' || strncmp (f->d_name, queue, strlen (queue)) || f->d_name[strlen (queue)] != '.'));
00949 return f;
00950 }
00951
00952
00953 static unsigned char sms_handleincoming (sms_t * h)
00954 {
00955 unsigned char p = 3;
00956 if (h->smsc) {
00957 if ((h->imsg[2] & 3) == 1) {
00958 h->udhl = h->udl = 0;
00959 h->vp = 0;
00960 h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);
00961 h->udhi = ((h->imsg[2] & 0x40) ? 1 : 0);
00962 h->rp = ((h->imsg[2] & 0x80) ? 1 : 0);
00963 ast_copy_string (h->oa, h->cli, sizeof (h->oa));
00964 h->scts = time (0);
00965 h->mr = h->imsg[p++];
00966 p += unpackaddress (h->da, h->imsg + p);
00967 h->pid = h->imsg[p++];
00968 h->dcs = h->imsg[p++];
00969 if ((h->imsg[2] & 0x18) == 0x10) {
00970 if (h->imsg[p] < 144)
00971 h->vp = (h->imsg[p] + 1) * 5;
00972 else if (h->imsg[p] < 168)
00973 h->vp = 720 + (h->imsg[p] - 143) * 30;
00974 else if (h->imsg[p] < 197)
00975 h->vp = (h->imsg[p] - 166) * 1440;
00976 else
00977 h->vp = (h->imsg[p] - 192) * 10080;
00978 p++;
00979 } else if (h->imsg[2] & 0x18)
00980 p += 7;
00981 p += unpacksms (h->dcs, h->imsg + p, h->udh, &h->udhl, h->ud, &h->udl, h->udhi);
00982 h->rx = 1;
00983 sms_writefile (h);
00984 if (p != h->imsg[1] + 2) {
00985 ast_log (LOG_WARNING, "Mismatch receive unpacking %d/%d\n", p, h->imsg[1] + 2);
00986 return 0xFF;
00987 }
00988 } else {
00989 ast_log (LOG_WARNING, "Unknown message type %02X\n", h->imsg[2]);
00990 return 0xFF;
00991 }
00992 } else {
00993 if (!(h->imsg[2] & 3)) {
00994 *h->da = h->srr = h->rp = h->vp = h->udhi = h->udhl = h->udl = 0;
00995 h->srr = ((h->imsg[2] & 0x20) ? 1 : 0);