/*
Functions related to time:
1) rfc (string) time to unix-time
2) unix-time to rfc (string) time
3) current time to rfc (string) time for the "Date:" header
*/
/****************************************************************
* This program 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, or (at your option)
* any later version.
*
* This program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
****************************************************************/
#include <linux/time.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include "times.h"
#include "prototypes.h"
static char *dayName[7] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static char *monthName[12] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
char CurrentTime[64];
int CurrentTime_i;
static char itoa_h[60]={'0','0','0','0','0','0','0','0','0','0',
'1','1','1','1','1','1','1','1','1','1',
'2','2','2','2','2','2','2','2','2','2',
'3','3','3','3','3','3','3','3','3','3',
'4','4','4','4','4','4','4','4','4','4',
'5','5','5','5','5','5','5','5','5','5'};
static char itoa_l[60]={'0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9',
'0','1','2','3','4','5','6','7','8','9'};
void time_Unix2RFC(const time_t Zulu,char *Buffer)
{
int Y=0,M=0,D=0;
int H=0,Min=0,S=0,WD=0;
int I,I2;
time_t rest;
I=0;
while (I<KHTTPD_NUMYEARS)
{
if (TimeDays[I][0]>Zulu)
break;
I++;
}
Y=--I;
if (I<0)
{
Y=0;
goto BuildYear;
}
I2=0;
while (I2<=12)
{
if (TimeDays[I][I2]>Zulu)
break;
I2++;
}
M=I2-1;
rest=Zulu - TimeDays[Y][M];
WD=WeekDays[Y][M];
D=rest/86400;
rest=rest%86400;
WD+=D;
WD=WD%7;
H=rest/3600;
rest=rest%3600;
Min=rest/60;
rest=rest%60;
S=rest;
BuildYear:
Y+=KHTTPD_YEAROFFSET;
/* Format: Day, 01 Mon 1999 01:01:01 GMT */
/*
We want to do
sprintf( Buffer, "%s, %02i %s %04i %02i:%02i:%02i GMT",
dayName[ WD ], D+1, monthName[ M ], Y,
H, Min, S
);
but this is very expensive. Since the string is fixed length,
it is filled manually.
*/
Buffer[0]=dayName[WD][0];
Buffer[1]=dayName[WD][1];
Buffer[2]=dayName[WD][2];
Buffer[3]=',';
Buffer[4]=' ';
Buffer[5]=itoa_h[D+1];
Buffer[6]=itoa_l[D+1];
Buffer[7]=' ';
Buffer[8]=monthName[M][0];
Buffer[9]=monthName[M][1];
Buffer[10]=monthName[M][2];
Buffer[11]=' ';
Buffer[12]=itoa_l[Y/1000];
Buffer[13]=itoa_l[(Y/100)%10];
Buffer[14]=itoa_l[(Y/10)%10];
Buffer[15]=itoa_l[Y%10];
Buffer[16]=' ';
Buffer[17]=itoa_h[H];
Buffer[18]=itoa_l[H];
Buffer[19]=':';
Buffer[20]=itoa_h[Min];
Buffer[21]=itoa_l[Min];
Buffer[22]=':';
Buffer[23]=itoa_h[S];
Buffer[24]=itoa_l[S];
Buffer[25]=' ';
Buffer[26]='G';
Buffer[27]='M';
Buffer[28]='T';
Buffer[29]=0;
}
void UpdateCurrentDate(void)
{
struct timeval tv;
do_gettimeofday(&tv);
if (CurrentTime_i!=tv.tv_sec)
time_Unix2RFC(tv.tv_sec,CurrentTime);
CurrentTime_i = tv.tv_sec;
}
static int MonthHash[32] = {0,0,7,0,0,0,0,0,0,0,0,3,0,0,0,2,6,0,5,0,9,8,4,0,0,11,1,10,0,0,0,0};
#define is_digit(c) ((c) >= '0' && (c) <= '9')
__inline static int skip_atoi(char **s)
{
int i=0;
while (is_digit(**s))
i = i*10 + *((*s)++) - '0';
return i;
}
time_t mimeTime_to_UnixTime(char *Q)
{
int Y,M,D,H,Min,S;
unsigned int Hash;
time_t Temp;
char *s,**s2;
s=Q;
s2=&s;
if (strlen(s)<30) return 0;
if (s[3]!=',') return 0;
if (s[19]!=':') return 0;
s+=5; /* Skip day of week */
D = skip_atoi(s2); /* Day of month */
s++;
Hash = (unsigned char)s[0]+(unsigned char)s[2];
Hash = (Hash<<1) + (unsigned char)s[1];
Hash = (Hash&63)>>1;
M = MonthHash[Hash];
s+=4;
Y = skip_atoi(s2); /* Year */
s++;
H = skip_atoi(s2); /* Hour */
s++;
Min = skip_atoi(s2); /* Minutes */
s++;
S = skip_atoi(s2); /* Seconds */
s++;
if ((s[0]!='G')||(s[1]!='M')||(s[2]!='T'))
{
return 0; /* No GMT */
}
if (Y<KHTTPD_YEAROFFSET) Y = KHTTPD_YEAROFFSET;
if (Y>KHTTPD_YEAROFFSET+9) Y = KHTTPD_YEAROFFSET+9;
Temp = TimeDays[Y-KHTTPD_YEAROFFSET][M];
Temp += D*86400+H*3600+Min*60+S;
return Temp;
}