msfuncs.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2001-2003 FhG Fokus
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * Kamailio is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #include "msfuncs.h"
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <sys/types.h>
  26. #include <unistd.h>
  27. #include <time.h>
  28. #include "../../dprint.h"
  29. #include "../../config.h"
  30. #include "../../ut.h"
  31. #include "../../forward.h"
  32. #include "../../resolve.h"
  33. #include "../../globals.h"
  34. #include "../../udp_server.h"
  35. #include "../../pt.h"
  36. #define CONTACT_PREFIX "Contact: <"
  37. #define CONTACT_SUFFIX ">;msilo=yes"CRLF
  38. #define CONTACT_PREFIX_LEN (sizeof(CONTACT_PREFIX)-1)
  39. #define CONTACT_SUFFIX_LEN (sizeof(CONTACT_SUFFIX)-1)
  40. extern int ms_add_date;
  41. extern int ms_add_contact;
  42. /**
  43. * apostrophes escaping
  44. * - src: source buffer
  45. * - slen: length of source buffer
  46. * - dst: destination buffer
  47. * - dlen: max length of destination buffer
  48. * return: destination length => OK; -1 => error
  49. */
  50. int m_apo_escape(char* src, int slen, char* dst, int dlen)
  51. {
  52. int i, j;
  53. if(!src || !dst || dlen <= 0)
  54. return -1;
  55. if(slen == -1)
  56. slen = strlen(src);
  57. for(i=j=0; i<slen; i++)
  58. {
  59. switch(src[i])
  60. {
  61. case '\'':
  62. if(j+2>=dlen)
  63. return -2;
  64. memcpy(&dst[j], "\\'", 2);
  65. j += 2;
  66. break;
  67. default:
  68. if(j+1>=dlen)
  69. return -2;
  70. dst[j] = src[i];
  71. j++;
  72. }
  73. }
  74. dst[j] = '\0';
  75. return j;
  76. }
  77. /**
  78. * Build a RFC 3261 compliant Date string from a time_t value
  79. * - date: input of time_t to build the string from
  80. * - buf: pointer to string for output
  81. * - bufLen: length of buf param
  82. *
  83. * return: >0 length of data copied to buf ; <0 error occured
  84. */
  85. int timetToSipDateStr(time_t date, char* buf, int bufLen)
  86. {
  87. struct tm *gmt;
  88. char* dayArray[7] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
  89. char* monthArray[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
  90. int len = 0;
  91. gmt = gmtime(&date);
  92. /* In RFC 3261 the format is always GMT and in the string form like
  93. * "Wkday, Day Month Year HOUR:MIN:SEC GMT"
  94. * "Mon, 19 Feb 2007 18:42:27 GMT"
  95. */
  96. len = snprintf(buf,bufLen,"Date: %s, %02d %s %d %02d:%02d:%02d GMT\r\n",
  97. dayArray[gmt->tm_wday],
  98. gmt->tm_mday,
  99. monthArray[gmt->tm_mon],
  100. 1900 + gmt->tm_year,
  101. gmt->tm_hour,
  102. gmt->tm_min,
  103. gmt->tm_sec
  104. );
  105. /* snprintf returns number of chars it should have printed, so you
  106. * need to bounds check against input*/
  107. return (len > bufLen) ? bufLen : len;
  108. }
  109. /**
  110. * extract the value of Content-Type header
  111. * - src: pointer to C-T content
  112. * - len: length of src
  113. * - ctype: parsed C-T
  114. * - flag: what to parse - bit mask of CT_TYPE, CT_CHARSET, CT_MSGR
  115. *
  116. * return: 0 OK ; -1 error
  117. */
  118. int m_extract_content_type(char* src, int len, content_type_t* ctype, int flag)
  119. {
  120. char *p, *end;
  121. int f = 0;
  122. if( !src || len <=0 )
  123. goto error;
  124. p = src;
  125. end = p + len;
  126. while((p < end) && (f != flag))
  127. {
  128. while((p < end) && (*p==' ' || *p=='\t'))
  129. p++;
  130. if(p >= end)
  131. goto done;
  132. if((flag & CT_TYPE) && !(f & CT_TYPE))
  133. {
  134. ctype->type.s = p;
  135. while(p < end && *p!=' ' && *p!='\t' && *p!='\0'
  136. && *p!=';' && *p!='\r' && *p!='\n')
  137. p++;
  138. LM_DBG("content-type found\n");
  139. f |= CT_TYPE;
  140. ctype->type.len = p - ctype->type.s;
  141. if(f == flag) {
  142. return 0;
  143. } else {
  144. p++;
  145. continue;
  146. }
  147. } else {
  148. if((flag & CT_CHARSET) && !(f & CT_CHARSET))
  149. {
  150. return -1;
  151. } else {
  152. if((flag & CT_MSGR) && !(f & CT_MSGR))
  153. {
  154. return -1;
  155. } else {
  156. return 0;
  157. }
  158. }
  159. }
  160. }
  161. done:
  162. if(f==flag)
  163. return 0;
  164. else
  165. return -1;
  166. error:
  167. LM_DBG("error\n");
  168. return -1;
  169. }
  170. /** build MESSAGE headers
  171. *
  172. * Add Content-Type, Contact, Date, and extra headers if they exist
  173. * expects - max buf len of the resulted body in body->len
  174. * - body->s MUST be allocated
  175. * return: 0 OK ; -1 error
  176. * */
  177. int m_build_headers(str *buf, str ctype, str contact, time_t date, str extra)
  178. {
  179. char *p;
  180. char strDate[48];
  181. int lenDate = 0;
  182. int newLen = 0;
  183. if(!buf || !buf->s || buf->len <= 0 || ctype.len < 0)
  184. goto error;
  185. newLen = 14 + ctype.len + CRLF_LEN + extra.len;
  186. if(contact.len > 0 && ms_add_contact)
  187. newLen += CONTACT_PREFIX_LEN + contact.len + CONTACT_SUFFIX_LEN;
  188. if(buf->len <= newLen)
  189. goto error;
  190. p = buf->s;
  191. if(date > 0)
  192. {
  193. lenDate = timetToSipDateStr(date,strDate,48);
  194. strncpy(p, strDate, lenDate);
  195. p += lenDate;
  196. }
  197. if(ctype.len > 0)
  198. {
  199. strncpy(p, "Content-Type: ", 14);
  200. p += 14;
  201. strncpy(p, ctype.s, ctype.len);
  202. p += ctype.len;
  203. strncpy(p, CRLF, CRLF_LEN);
  204. p += CRLF_LEN;
  205. }
  206. if(contact.len > 0 && ms_add_contact)
  207. {
  208. strncpy(p, CONTACT_PREFIX, CONTACT_PREFIX_LEN);
  209. p += CONTACT_PREFIX_LEN;
  210. strncpy(p, contact.s, contact.len);
  211. p += contact.len;
  212. strncpy(p, CONTACT_SUFFIX, CONTACT_SUFFIX_LEN);
  213. p += CONTACT_SUFFIX_LEN;
  214. }
  215. if (extra.len > 0) {
  216. strncpy(p, extra.s, extra.len);
  217. p += extra.len;
  218. }
  219. buf->len = p - buf->s;
  220. return 0;
  221. error:
  222. return -1;
  223. }
  224. /** build MESSAGE body --- add incoming time and 'from'
  225. *
  226. * expects - max buf len of the resulted body in body->len
  227. * - body->s MUST be allocated
  228. * return: 0 OK ; -1 error
  229. * */
  230. int m_build_body(str *body, time_t date, str msg, time_t sdate)
  231. {
  232. char *p;
  233. if(!body || !(body->s) || body->len <= 0 || msg.len <= 0
  234. || date < 0 || msg.len < 0 || (46+msg.len > body->len) )
  235. goto error;
  236. p = body->s;
  237. if(ms_add_date!=0)
  238. {
  239. if(sdate!=0)
  240. {
  241. strncpy(p, "[Reminder message - ", 20);
  242. p += 20;
  243. strncpy(p, ctime(&sdate), 24);
  244. p += 24;
  245. *p++ = ']';
  246. } else {
  247. strncpy(p, "[Offline message - ", 19);
  248. p += 19;
  249. strncpy(p, ctime(&date), 24);
  250. p += 24;
  251. *p++ = ']';
  252. }
  253. *p++ = ' ';
  254. }
  255. memcpy(p, msg.s, msg.len);
  256. p += msg.len;
  257. body->len = p - body->s;
  258. return 0;
  259. error:
  260. return -1;
  261. }
  262. /* return time stamp of YYYYMMDDHHMMSS */
  263. int ms_extract_time(str *time_str, int *time_val)
  264. {
  265. struct tm stm;
  266. int i;
  267. if(time_str==NULL || time_str->s==NULL
  268. || time_str->len<=0 || time_val==NULL)
  269. {
  270. LM_ERR("bad parameters\n");
  271. return -1;
  272. }
  273. memset(&stm, 0, sizeof(struct tm));
  274. for(i=0; i<time_str->len; i++)
  275. {
  276. if(time_str->s[i]<'0' || time_str->s[i]>'9')
  277. {
  278. LM_ERR("bad time [%.*s]\n", time_str->len, time_str->s);
  279. return -1;
  280. }
  281. switch(i)
  282. {
  283. case 0:
  284. if(time_str->s[i]<'2')
  285. {
  286. LM_ERR("bad year in time [%.*s]\n",
  287. time_str->len, time_str->s);
  288. return -1;
  289. }
  290. stm.tm_year += 1000*(time_str->s[i]-'0') - 1900;
  291. break;
  292. case 1:
  293. stm.tm_year += 100*(time_str->s[i]-'0');
  294. break;
  295. case 2:
  296. stm.tm_year += 10*(time_str->s[i]-'0');
  297. break;
  298. case 3:
  299. stm.tm_year += (time_str->s[i]-'0');
  300. break;
  301. case 4:
  302. if(time_str->s[i]>'1')
  303. {
  304. LM_ERR("bad month in time[%.*s]\n",
  305. time_str->len, time_str->s);
  306. return -1;
  307. }
  308. stm.tm_mon += 10*(time_str->s[i]-'0') - 1;
  309. break;
  310. case 5:
  311. if((time_str->s[i-1]=='0' && time_str->s[i]=='0')
  312. || (time_str->s[i-1]=='1' && time_str->s[i]>'2'))
  313. {
  314. LM_ERR("bad month in time[%.*s]\n",
  315. time_str->len, time_str->s);
  316. return -1;
  317. }
  318. stm.tm_mon += (time_str->s[i]-'0');
  319. break;
  320. case 6:
  321. if(time_str->s[i]>'3')
  322. {
  323. LM_ERR("bad day in time [%.*s]\n",
  324. time_str->len, time_str->s);
  325. return -1;
  326. }
  327. stm.tm_mday += 10*(time_str->s[i]-'0');
  328. break;
  329. case 7:
  330. if((time_str->s[i-1]=='0' && time_str->s[i]=='0')
  331. || (time_str->s[i-1]=='3' && time_str->s[i]>'1'))
  332. {
  333. LM_ERR("bad day in time [%.*s]\n",
  334. time_str->len, time_str->s);
  335. return -1;
  336. }
  337. stm.tm_mday += (time_str->s[i]-'0');
  338. break;
  339. case 8:
  340. if(time_str->s[i]>'2')
  341. {
  342. LM_ERR("bad hour in time [%.*s]\n",
  343. time_str->len, time_str->s);
  344. return -1;
  345. }
  346. stm.tm_hour += 10*(time_str->s[i]-'0');
  347. break;
  348. case 9:
  349. if(time_str->s[i-1]=='2' && time_str->s[i]>'3')
  350. {
  351. LM_ERR("bad hour in time [%.*s]\n",
  352. time_str->len, time_str->s);
  353. return -1;
  354. }
  355. stm.tm_hour += (time_str->s[i]-'0');
  356. break;
  357. case 10:
  358. if(time_str->s[i]>'5')
  359. {
  360. LM_ERR("bad min in time [%.*s]\n",
  361. time_str->len, time_str->s);
  362. return -1;
  363. }
  364. stm.tm_min += 10*(time_str->s[i]-'0');
  365. break;
  366. case 11:
  367. stm.tm_min += (time_str->s[i]-'0');
  368. break;
  369. case 12:
  370. if(time_str->s[i]>'5')
  371. {
  372. LM_ERR("bad sec in time [%.*s]\n",
  373. time_str->len, time_str->s);
  374. return -1;
  375. }
  376. stm.tm_sec += 10*(time_str->s[i]-'0');
  377. break;
  378. case 13:
  379. stm.tm_sec += (time_str->s[i]-'0');
  380. break;
  381. default:
  382. LM_ERR("time spec too long [%.*s]\n",
  383. time_str->len, time_str->s);
  384. return -1;
  385. }
  386. }
  387. *time_val = (int)mktime(&stm);
  388. return 0;
  389. }