msfuncs.c

Go to the documentation of this file.
00001 /*
00002  * $Id: msfuncs.c 4518 2008-07-28 15:39:28Z henningw $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 
00023 #include "msfuncs.h"
00024 
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <sys/types.h>
00028 #include <unistd.h>
00029 #include <time.h>
00030 #include "../../dprint.h"
00031 #include "../../config.h"
00032 #include "../../ut.h"
00033 #include "../../forward.h"
00034 #include "../../resolve.h"
00035 #include "../../globals.h"
00036 #include "../../udp_server.h"
00037 #include "../../pt.h"
00038 
00039 #define CONTACT_PREFIX "Contact: <"
00040 #define CONTACT_SUFFIX  ">;msilo=yes"CRLF
00041 #define CONTACT_PREFIX_LEN (sizeof(CONTACT_PREFIX)-1)
00042 #define CONTACT_SUFFIX_LEN  (sizeof(CONTACT_SUFFIX)-1)
00043 
00044 extern int ms_add_date;
00045 
00046 /**
00047  * apostrophes escaping
00048  * - src: source buffer
00049  * - slen: length of source buffer
00050  * - dst: destination buffer
00051  * - dlen: max length of destination buffer
00052  * return: destination length => OK; -1 => error
00053  */
00054 
00055 int m_apo_escape(char* src, int slen, char* dst, int dlen)
00056 {
00057    int i, j;
00058 
00059    if(!src || !dst || dlen <= 0)
00060       return -1;
00061 
00062    if(slen == -1)
00063       slen = strlen(src);
00064 
00065    for(i=j=0; i<slen; i++)
00066    {
00067       switch(src[i])
00068       {
00069          case '\'':
00070                if(j+2>=dlen)
00071                   return -2;
00072                memcpy(&dst[j], "\\'", 2);
00073                j += 2;
00074             break;
00075          default:
00076             if(j+1>=dlen)
00077                   return -2;
00078             dst[j] = src[i];
00079             j++;
00080       }
00081    }
00082    dst[j] = '\0';
00083 
00084    return j;
00085 }
00086 
00087 /**
00088  * Build a RFC 3261 compliant Date string from a time_t value
00089  * - date: input of time_t to build the string from
00090  * - buf: pointer to string for output
00091  * - bufLen: length of buf param
00092  *
00093  * return: >0 length of data copied to buf ; <0 error occured
00094   */
00095 int timetToSipDateStr(time_t date, char* buf, int bufLen)
00096 {
00097    struct tm *gmt;
00098    char* dayArray[7] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
00099    char* monthArray[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
00100    int len = 0;
00101 
00102    gmt = gmtime(&date);
00103    /* In RFC 3261 the format is always GMT and in the string form like
00104     * "Wkday, Day Month Year HOUR:MIN:SEC GMT"
00105     * "Mon, 19 Feb 2007 18:42:27 GMT"
00106     */
00107    len = snprintf(buf,bufLen,"Date: %s, %02d %s %d %02d:%02d:%02d GMT\r\n",
00108       dayArray[gmt->tm_wday],
00109       gmt->tm_mday,
00110       monthArray[gmt->tm_mon],
00111       1900 + gmt->tm_year,
00112       gmt->tm_hour,
00113       gmt->tm_min,
00114       gmt->tm_sec
00115       );
00116 
00117    /* snprintf returns number of chars it should have printed, so you 
00118     * need to bounds check against input*/
00119    return (len > bufLen) ? bufLen : len;
00120 }
00121 
00122 /**
00123  * extract the value of Content-Type header
00124  * - src: pointer to C-T content
00125  * - len: length of src
00126  * - ctype: parsed C-T
00127  * - flag: what to parse - bit mask of CT_TYPE, CT_CHARSET, CT_MSGR
00128  *
00129  * return: 0 OK ; -1 error
00130   */
00131 int m_extract_content_type(char* src, int len, content_type_t* ctype, int flag)
00132 {
00133    char *p, *end;
00134    int f = 0;
00135 
00136    if( !src || len <=0 )
00137       goto error;
00138    p = src;
00139    end = p + len;
00140    while((p < end) && (f != flag))
00141    {
00142       while((p < end) && (*p==' ' || *p=='\t'))
00143          p++;
00144       if(p >= end)
00145          goto done;
00146       if((flag & CT_TYPE) && !(f & CT_TYPE))
00147       {
00148          ctype->type.s = p;
00149          while(p < end && *p!=' ' && *p!='\t' && *p!='\0'
00150                 && *p!=';' && *p!='\r' && *p!='\n')
00151             p++;
00152          
00153          LM_DBG("content-type found\n");
00154          f |= CT_TYPE;
00155          ctype->type.len = p - ctype->type.s;
00156          if(f == flag) {
00157             return 0;
00158          } else {
00159             p++;
00160             continue;
00161          }
00162       } else {
00163          if((flag & CT_CHARSET) && !(f & CT_CHARSET))
00164          {
00165             return -1;
00166          } else {
00167             if((flag & CT_MSGR) && !(f & CT_MSGR))
00168             {
00169                return -1;
00170             } else {
00171                return 0;
00172             }
00173          }
00174       }
00175    }
00176 
00177 done:
00178    if(f==flag)
00179       return 0;
00180    else
00181       return -1;
00182 error:
00183    LM_DBG("error\n");
00184    return -1;
00185 }
00186 
00187 /** build MESSAGE headers 
00188  *
00189  * Add Content-Type, Contact and Date headers if they exist
00190  * expects - max buf len of the resulted body in body->len
00191  *         - body->s MUST be allocated
00192  * return: 0 OK ; -1 error
00193  * */
00194 int m_build_headers(str *buf, str ctype, str contact, time_t date)
00195 {
00196    char *p;
00197    char strDate[48];
00198    int lenDate = 0;
00199 
00200    if(!buf || !buf->s || buf->len <= 0 || ctype.len < 0 || contact.len < 0
00201          || buf->len <= ctype.len+contact.len+14 /*Content-Type: */
00202             +CRLF_LEN+CONTACT_PREFIX_LEN+CONTACT_SUFFIX_LEN)
00203       goto error;
00204 
00205    p = buf->s;
00206    if(date > 0)
00207    {
00208       lenDate = timetToSipDateStr(date,strDate,48);
00209       strncpy(p, strDate, lenDate);
00210       p += lenDate;
00211    }
00212    if(ctype.len > 0)
00213    {
00214       strncpy(p, "Content-Type: ", 14);
00215       p += 14;
00216       strncpy(p, ctype.s, ctype.len);
00217       p += ctype.len;
00218       strncpy(p, CRLF, CRLF_LEN);
00219       p += CRLF_LEN;
00220    
00221    }
00222    if(contact.len > 0)
00223    {
00224       strncpy(p, CONTACT_PREFIX, CONTACT_PREFIX_LEN);
00225       p += CONTACT_PREFIX_LEN;
00226       strncpy(p, contact.s, contact.len);
00227       p += contact.len;
00228       strncpy(p, CONTACT_SUFFIX, CONTACT_SUFFIX_LEN);
00229       p += CONTACT_SUFFIX_LEN;
00230    }
00231    buf->len = p - buf->s;  
00232    return 0;
00233 error:
00234    return -1;
00235 }
00236 
00237 /** build MESSAGE body --- add incoming time and 'from' 
00238  *
00239  * expects - max buf len of the resulted body in body->len
00240  *         - body->s MUST be allocated
00241  * return: 0 OK ; -1 error
00242  * */
00243 int m_build_body(str *body, time_t date, str msg, time_t sdate)
00244 {
00245    char *p;
00246    
00247    if(!body || !(body->s) || body->len <= 0 || msg.len <= 0
00248          || date < 0 || msg.len < 0 || (46+msg.len > body->len) )
00249       goto error;
00250    
00251    p = body->s;
00252 
00253    if(ms_add_date!=0)
00254    {
00255       if(sdate!=0)
00256       {
00257          strncpy(p, "[Reminder message - ", 20);
00258          p += 20;
00259       
00260          strncpy(p, ctime(&sdate), 24);
00261          p += 24;
00262 
00263          *p++ = ']';
00264       } else {
00265          strncpy(p, "[Offline message - ", 19);
00266          p += 19;
00267    
00268          strncpy(p, ctime(&date), 24);
00269          p += 24;
00270 
00271          *p++ = ']';
00272       }
00273       *p++ = ' ';
00274    }
00275    
00276    memcpy(p, msg.s, msg.len);
00277    p += msg.len;
00278 
00279    body->len = p - body->s;
00280    
00281    return 0;
00282 error:
00283    return -1;
00284 }
00285 
00286 /* return time stamp of YYYYMMDDHHMMSS */
00287 int ms_extract_time(str *time_str, int *time_val)
00288 {
00289    struct tm stm;
00290    int i;
00291 
00292    if(time_str==NULL || time_str->s==NULL  
00293          || time_str->len<=0 || time_val==NULL)
00294    {
00295       LM_ERR("bad parameters\n");
00296       return -1;
00297    }
00298    
00299    memset(&stm, 0, sizeof(struct tm));
00300    for(i=0; i<time_str->len; i++)
00301    {
00302       if(time_str->s[i]<'0' || time_str->s[i]>'9')
00303       {
00304          LM_ERR("bad time [%.*s]\n", time_str->len, time_str->s);
00305          return -1;
00306       }
00307       switch(i)
00308       {
00309          case 0:
00310             if(time_str->s[i]<'2')
00311             {
00312                LM_ERR("bad year in time [%.*s]\n",
00313                      time_str->len, time_str->s);
00314                return -1;
00315             }
00316             stm.tm_year += 1000*(time_str->s[i]-'0') - 1900;
00317          break;
00318          case 1:
00319             stm.tm_year += 100*(time_str->s[i]-'0');
00320          break;
00321          case 2:
00322             stm.tm_year += 10*(time_str->s[i]-'0');
00323          break;
00324          case 3:
00325             stm.tm_year += (time_str->s[i]-'0');
00326          break;
00327          case 4:
00328             if(time_str->s[i]>'1')
00329             {
00330                LM_ERR("bad month in time[%.*s]\n",
00331                      time_str->len, time_str->s);
00332                return -1;
00333             }
00334             stm.tm_mon += 10*(time_str->s[i]-'0') - 1;
00335          break;
00336          case 5:
00337             if((time_str->s[i-1]=='0' && time_str->s[i]=='0')
00338                   || (time_str->s[i-1]=='1' && time_str->s[i]>'2'))
00339             {
00340                LM_ERR("bad month in time[%.*s]\n",
00341                      time_str->len, time_str->s);
00342                return -1;
00343             }
00344             stm.tm_mon += (time_str->s[i]-'0');
00345          break;
00346          case 6:
00347             if(time_str->s[i]>'3')
00348             {
00349                LM_ERR("bad day in time [%.*s]\n",
00350                      time_str->len, time_str->s);
00351                return -1;
00352             }
00353             stm.tm_mday += 10*(time_str->s[i]-'0');
00354          break;
00355          case 7:
00356             if((time_str->s[i-1]=='0' && time_str->s[i]=='0')
00357                   || (time_str->s[i-1]=='3' && time_str->s[i]>'1'))
00358             {
00359                LM_ERR("bad day in time [%.*s]\n",
00360                      time_str->len, time_str->s);
00361                return -1;
00362             }
00363             stm.tm_mday += (time_str->s[i]-'0');
00364          break;
00365          case 8:
00366             if(time_str->s[i]>'2')
00367             {
00368                LM_ERR("bad hour in time [%.*s]\n",
00369                      time_str->len, time_str->s);
00370                return -1;
00371             }
00372             stm.tm_hour += 10*(time_str->s[i]-'0');
00373          break;
00374          case 9:
00375             if(time_str->s[i-1]=='2' && time_str->s[i]>'3')
00376             {
00377                LM_ERR("bad hour in time [%.*s]\n",
00378                      time_str->len, time_str->s);
00379                return -1;
00380             }
00381             stm.tm_hour += (time_str->s[i]-'0');
00382          break;
00383          case 10:
00384             if(time_str->s[i]>'5')
00385             {
00386                LM_ERR("bad min in time [%.*s]\n",
00387                      time_str->len, time_str->s);
00388                return -1;
00389             }
00390             stm.tm_min += 10*(time_str->s[i]-'0');
00391          break;
00392          case 11:
00393             stm.tm_min += (time_str->s[i]-'0');
00394          break;
00395          case 12:
00396             if(time_str->s[i]>'5')
00397             {
00398                LM_ERR("bad sec in time [%.*s]\n",
00399                      time_str->len, time_str->s);
00400                return -1;
00401             }
00402             stm.tm_sec += 10*(time_str->s[i]-'0');
00403          break;
00404          case 13:
00405             stm.tm_sec += (time_str->s[i]-'0');
00406          break;
00407          default:
00408             LM_ERR("time spec too long [%.*s]\n",
00409                   time_str->len, time_str->s);
00410             return -1;
00411       }
00412    }
00413    *time_val = (int)mktime(&stm);
00414 
00415    return 0;
00416 }

Generated on Wed May 23 20:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6