You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/parser/parse_date.c

200 lines
4.5 KiB

/*
* Copyright (c) 2007 iptelorg GmbH
*
* This file is part of Kamailio, a free SIP server.
*
* Kamailio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* Kamailio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*! \file
* \brief Parser :: Date header
*
* \ingroup parser
*/
#include <string.h>
#include "parse_date.h"
#include "parse_def.h"
#include "parser_f.h" /* eat_space_end and so on */
#include "../mem/mem.h"
/*
* Parse Date header field
*/
#define READ(val) \
(*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
inline static int char2int (char *p, int *t)
{
if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9')
return -1;
*t = (*p - '0')*10 + *(p + 1) - '0';
return 0;
}
/*! \brief
* Converts a RFC 1123 formatted date string to stuct tm
*/
static int rfc1123totm (char *stime, struct tm *ttm ) {
char *ptime = stime;
unsigned int uval;
int ires;
uval = READ(ptime);
ptime+=4;
switch (uval) {
/* Sun, */
case 0x2c6e7553: ttm->tm_wday = 0; break;
/* Mon, */
case 0x2c6e6f4d: ttm->tm_wday = 1; break;
/* Tue, */
case 0x2c657554: ttm->tm_wday = 2; break;
/* Wed, */
case 0x2c646557: ttm->tm_wday = 3; break;
/* Thu, */
case 0x2c756854: ttm->tm_wday = 4; break;
/* Fri, */
case 0x2c697246: ttm->tm_wday = 5; break;
/* Sat, */
case 0x2c746153: ttm->tm_wday = 6; break;
default: return -2;
}
if (*(ptime++)!=' ') return -3;
if (char2int(ptime,&ttm->tm_mday) || ttm->tm_mday > 31) return -4;
ptime+=2;
if (*(ptime++) != ' ') return -5;
uval = READ(ptime);
ptime+=4;
switch (uval) {
/* Jan, */
case 0x206e614a: ttm->tm_mon = 0; break;
/* Feb, */
case 0x20626546: ttm->tm_mon = 1; break;
/* Mar, */
case 0x2072614d: ttm->tm_mon = 2; break;
/* Apr, */
case 0x20727041: ttm->tm_mon = 3; break;
/* May, */
case 0x2079614d: ttm->tm_mon = 4; break;
/* Jun, */
case 0x206e754a: ttm->tm_mon = 5; break;
/* Jul, */
case 0x206c754a: ttm->tm_mon = 6; break;
/* Aug, */
case 0x20677541: ttm->tm_mon = 7; break;
/* Sep, */
case 0x20706553: ttm->tm_mon = 8; break;
/* Oct, */
case 0x2074634f: ttm->tm_mon = 9; break;
/* Nov, */
case 0x20766f4e: ttm->tm_mon = 10; break;
/* Dec, */
case 0x20636544: ttm->tm_mon = 11; break;
default: return -6;
}
if (char2int(ptime,&ires)) return -7;
ptime+=2;
if (char2int(ptime,&ttm->tm_year)) return -8;
ptime+=2;
ttm->tm_year+=(ires-19)*100;
if (*(ptime++) != ' ') return -9;
if (char2int(ptime,&ttm->tm_hour) || ttm->tm_hour > 23) return -10;
ptime+=2;
if (*(ptime++) != ':') return -11;
if (char2int(ptime,&ttm->tm_min) || ttm->tm_min > 59) return -12;
ptime+=2;
if (*(ptime++) != ':') return -13;
if (char2int(ptime,&ttm->tm_sec) || ttm->tm_sec > 59) return -14;
ptime+=2;
/* " GMT" */
uval = READ(ptime);
if ((uval | 0x20202020) != 0x746d6720) return -15;
return 0;
}
void parse_date(char *buffer, char *end, struct date_body *db)
{
db->error=PARSE_ERROR;
/* check whether enough characters are available */
if (end - buffer < RFC1123DATELENGTH)
goto error;
if (rfc1123totm(buffer,&db->date))
goto error;
db->error=PARSE_OK;
return ;
error:
LOG(L_ERR,"ERROR: parse_date: parse error\n");
return ;
}
int parse_date_header(struct sip_msg *msg)
{
struct date_body* date_b;
if ( !msg->date && (parse_headers(msg,HDR_DATE_F,0)==-1 || !msg->date) ) {
LOG(L_ERR,"ERROR:parse_date_header: bad msg or missing DATE header\n");
goto error;
}
/* maybe the header is already parsed! */
if (msg->date->parsed)
return 0;
date_b=pkg_malloc(sizeof(*date_b));
if (date_b==0){
LOG(L_ERR, "ERROR:parse_date_header: out of memory\n");
goto error;
}
memset(date_b, 0, sizeof(*date_b));
parse_date(msg->date->body.s,
msg->date->body.s + msg->date->body.len+1,
date_b);
if (date_b->error==PARSE_ERROR){
free_date(date_b);
goto error;
}
msg->date->parsed=(void*)date_b;
return 0;
error:
return -1;
}
void free_date(struct date_body *db)
{
pkg_free(db);
}