parse_date.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Copyright (c) 2007 iptelorg GmbH
00005  *
00006  * This file is part of ser, a free SIP server.
00007  *
00008  * ser 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  * ser 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 
00031 #include <string.h>
00032 #include "parse_date.h"
00033 #include "parse_def.h"
00034 #include "parser_f.h"  /* eat_space_end and so on */
00035 #include "../mem/mem.h"
00036 
00037 /*
00038  * Parse Date header field
00039  */
00040 
00041 #define READ(val) \
00042 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
00043 
00044 inline static int char2int (char *p, int *t)
00045 {
00046         if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9')
00047                 return -1;
00048         *t = (*p - '0')*10 + *(p + 1) - '0';
00049 
00050         return 0;
00051 }
00052 
00056 static int rfc1123totm (char *stime, struct tm *ttm ) {
00057         char *ptime = stime;
00058         unsigned int uval;
00059         int ires;
00060 
00061         uval = READ(ptime);
00062         ptime+=4;
00063         switch (uval) {
00064                 /* Sun, */
00065                 case 0x2c6e7553: ttm->tm_wday = 0; break;
00066                 /* Mon, */
00067                 case 0x2c6e6f4d: ttm->tm_wday = 1; break;
00068                 /* Tue, */
00069                 case 0x2c657554: ttm->tm_wday = 2; break;
00070                 /* Wed, */
00071                 case 0x2c646557: ttm->tm_wday = 3; break;
00072                 /* Thu, */
00073                 case 0x2c756854: ttm->tm_wday = 4; break;
00074                 /* Fri, */
00075                 case 0x2c697246: ttm->tm_wday = 5; break;
00076                 /* Sat, */
00077                 case 0x2c746153: ttm->tm_wday = 6; break;
00078                 default: return -2;
00079         }
00080 
00081         if (*(ptime++)!=' ') return -3;
00082 
00083 
00084         if (char2int(ptime,&ttm->tm_mday) || ttm->tm_mday > 31) return -4;
00085         ptime+=2;
00086 
00087         if (*(ptime++) != ' ') return -5;
00088 
00089         uval = READ(ptime);
00090         ptime+=4;
00091         switch (uval) {
00092                 /* Jan, */
00093                 case 0x206e614a: ttm->tm_mon = 0; break;
00094                 /* Feb, */
00095                 case 0x20626546: ttm->tm_mon = 1; break;
00096                 /* Mar, */
00097                 case 0x2072614d: ttm->tm_mon = 2; break;
00098                 /* Apr, */
00099                 case 0x20727041: ttm->tm_mon = 3; break;
00100                 /* May, */
00101                 case 0x2079614d: ttm->tm_mon = 4; break;
00102                 /* Jun, */
00103                 case 0x206e754a: ttm->tm_mon = 5; break;
00104                 /* Jul, */
00105                 case 0x206c754a: ttm->tm_mon = 6; break;
00106                 /* Aug, */
00107                 case 0x20677541: ttm->tm_mon = 7; break;
00108                 /* Sep, */
00109                 case 0x20706553: ttm->tm_mon = 8; break;
00110                 /* Oct, */
00111                 case 0x2074634f: ttm->tm_mon = 9; break;
00112                 /* Nov, */
00113                 case 0x20766f4e: ttm->tm_mon = 10; break;
00114                 /* Dec, */
00115                 case 0x20636544: ttm->tm_mon = 11; break;
00116                 default: return -6;
00117         }
00118 
00119         if (char2int(ptime,&ires)) return -7;
00120         ptime+=2;
00121         if (char2int(ptime,&ttm->tm_year)) return -8;
00122         ptime+=2;
00123         ttm->tm_year+=(ires-19)*100;
00124 
00125         if (*(ptime++) != ' ') return -9;
00126 
00127         if (char2int(ptime,&ttm->tm_hour) || ttm->tm_hour > 23) return -10;
00128         ptime+=2;
00129         if (*(ptime++) != ':') return -11;
00130 
00131         if (char2int(ptime,&ttm->tm_min) || ttm->tm_min > 59) return -12;
00132         ptime+=2;
00133         if (*(ptime++) != ':') return -13;
00134 
00135         if (char2int(ptime,&ttm->tm_sec) || ttm->tm_sec > 59) return -14;
00136         ptime+=2;
00137 
00138         /* " GMT" */
00139         uval = READ(ptime);
00140         if ((uval | 0x20202020) != 0x746d6720) return -15;
00141 
00142         return 0;
00143 }
00144 
00145 void parse_date(char *buffer, char *end, struct date_body *db)
00146 {
00147         db->error=PARSE_ERROR;
00148 
00149         /* check whether enough characters are available */
00150         if (end - buffer < RFC1123DATELENGTH)
00151                 goto error;
00152 
00153         if (rfc1123totm(buffer,&db->date))
00154                 goto error;
00155 
00156         db->error=PARSE_OK;
00157         return ;
00158 error:
00159         LOG(L_ERR,"ERROR: parse_date: parse error\n");
00160         return ;
00161 }
00162 
00163 int parse_date_header(struct sip_msg *msg)
00164 {
00165         struct date_body* date_b;
00166 
00167 
00168         if ( !msg->date && (parse_headers(msg,HDR_DATE_F,0)==-1 || !msg->date) ) {
00169                 LOG(L_ERR,"ERROR:parse_date_header: bad msg or missing DATE header\n");
00170                 goto error;
00171         }
00172 
00173         /* maybe the header is already parsed! */
00174         if (msg->date->parsed)
00175                 return 0;
00176 
00177         date_b=pkg_malloc(sizeof(*date_b));
00178         if (date_b==0){
00179                 LOG(L_ERR, "ERROR:parse_date_header: out of memory\n");
00180                 goto error;
00181         }
00182         memset(date_b, 0, sizeof(*date_b));
00183 
00184         parse_date(msg->date->body.s,
00185                            msg->date->body.s + msg->date->body.len+1,
00186                            date_b);
00187         if (date_b->error==PARSE_ERROR){
00188                 free_date(date_b);
00189                 goto error;
00190         }
00191         msg->date->parsed=(void*)date_b;
00192 
00193         return 0;
00194 error:
00195         return -1;
00196 }
00197 
00198 void free_date(struct date_body *db)
00199 {
00200         pkg_free(db);
00201 }