mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-07-15 08:07:43 +02:00
* Fixed a bug in the 'rivwebcapi' validate_tm() function that caused dates containing '29 February' to always fail regardless of leap-year validity.
351 lines
9.3 KiB
C
351 lines
9.3 KiB
C
/* rd_common.c
|
|
*
|
|
* Common Utility Functions for the Rivendell Access Library
|
|
*
|
|
* (C) Copyright 2015-2019 Fred Gleason <fredg@paravelsystems.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* 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 "rd_common.h"
|
|
|
|
unsigned RD_ReadBool(const char *val)
|
|
{
|
|
if((strcasecmp(val,"true")==0)||(strcasecmp(val,"yes")==0)||
|
|
(strcasecmp(val,"on")==0)) {
|
|
return 1;
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
* RD_Cnv_DTString_to_tm
|
|
* Take a DateTime String and converts to a tm struct.
|
|
* Assumes a Z means Zulu (GMT) Always returns localtime
|
|
* in tm struct pointer. Returns null tm on invalid date length
|
|
*******************************************************************/
|
|
struct tm RD_Cnv_DTString_to_tm( const char *datein)
|
|
{
|
|
struct tm datetimetm = {0};
|
|
struct tm *tmptr;
|
|
time_t rawtime;
|
|
time_t newrawtime;
|
|
char theyear[5];
|
|
char themonth[3];
|
|
char theday[3];
|
|
char thehr[3];
|
|
char themin[3];
|
|
char thesec[3];
|
|
char plusminusz[2];
|
|
char offsethr[3];
|
|
char offsetmin[3];
|
|
double offsetfromutc = 0;
|
|
int offhr = 0;
|
|
int offmin = 0;
|
|
int val;
|
|
|
|
tmptr = &datetimetm;
|
|
|
|
if ((strlen(datein) < 19) || // INVALID DATE
|
|
(strlen(datein) > 26) )
|
|
return datetimetm;
|
|
|
|
strlcpy(theyear,datein,4);
|
|
strlcpy(themonth,datein+5,2);
|
|
strlcpy(theday,datein+8,2);
|
|
strlcpy(thehr,datein+11,2);
|
|
strlcpy(themin,datein+14,2);
|
|
strlcpy(thesec,datein+17,2);
|
|
if (strlen(datein) > 19)
|
|
{
|
|
strlcpy(plusminusz,datein+19,1);
|
|
if ( (( strcmp(plusminusz,"+"))==0) ||
|
|
(( strcmp(plusminusz,"-"))==0) )
|
|
{
|
|
strlcpy(offsethr,datein+20,2);
|
|
strlcpy(offsetmin,datein+23,2);
|
|
}
|
|
}
|
|
val = atoi(theyear) - 1900;
|
|
tmptr->tm_year = val;
|
|
val = atoi(themonth) - 1;
|
|
tmptr->tm_mon = val;
|
|
tmptr->tm_mday = atoi(theday);
|
|
tmptr->tm_hour = atoi(thehr);
|
|
tmptr->tm_min = atoi(themin);
|
|
tmptr->tm_sec = atoi(thesec);
|
|
/* This is to fix if Windows Assumes apply DST */
|
|
#ifdef _WIN32
|
|
tmptr->tm_isdst = -1;
|
|
#endif
|
|
rawtime = mktime (tmptr);
|
|
newrawtime = rawtime;
|
|
if ((strcmp(plusminusz,"Z")) != 0)
|
|
{
|
|
if (strlen(datein)==25)
|
|
{
|
|
offhr = atoi(offsethr);
|
|
offmin = atoi(offsetmin);
|
|
}
|
|
if ((strcmp(plusminusz,"-"))== 0)
|
|
{
|
|
newrawtime = rawtime + ((offhr * 3600) +
|
|
(offmin * 60));
|
|
}
|
|
else
|
|
{
|
|
newrawtime = rawtime - ((offhr * 3600) -
|
|
(offmin * 60));
|
|
}
|
|
}
|
|
// Get the local offset from UTC
|
|
offsetfromutc = get_local_offset();
|
|
newrawtime += offsetfromutc;
|
|
#ifdef _WIN32
|
|
tmptr = localtime(&newrawtime);
|
|
#else
|
|
localtime_r(&newrawtime,tmptr);
|
|
#endif
|
|
return datetimetm;
|
|
}
|
|
|
|
/****************************************************************
|
|
* strlcpy
|
|
* Copies a strng buffer into a string buffer with size bufsiz
|
|
* Returns size_t length copied. Null Terminates Automatically
|
|
*****************************************************************/
|
|
size_t strlcpy(char * dest, const char* src, size_t bufsize)
|
|
{
|
|
size_t srclen = strlen(src);
|
|
size_t len;
|
|
if (bufsize == 0)
|
|
return bufsize;
|
|
len = (bufsize < srclen) ? bufsize : srclen;
|
|
memcpy(dest,src,len);
|
|
dest[len]='\0';
|
|
return len;
|
|
}
|
|
|
|
/****************************************************************
|
|
* RD_Cnv_tm_to_DTString
|
|
* Copies tm struct values into a date string. Returns
|
|
* size_t length copied. Returns 0 if invalid tm struct.
|
|
*****************************************************************/
|
|
size_t RD_Cnv_tm_to_DTString(struct tm *tmptr,char * dest)
|
|
{
|
|
char theyear[5];
|
|
char themonth[3];
|
|
char theday[3];
|
|
char thehr[3];
|
|
char themin[3];
|
|
char thesec[3];
|
|
char plusminus[3];
|
|
char minus[2] = "-";
|
|
char colon_sep[4] = ":";
|
|
char T_sep[2] = "T";
|
|
char offsethr[3];
|
|
char offsetmin[3];
|
|
double offsetfromutc;
|
|
int offhr = 0;
|
|
int offmin = 0;
|
|
int val;
|
|
int leap = 0;
|
|
|
|
if (!validate_tm(tmptr))
|
|
{
|
|
dest[0]=0;
|
|
return 0;
|
|
}
|
|
offsetfromutc = get_local_offset();
|
|
if (offsetfromutc > 0)
|
|
strlcpy(plusminus,"%2b",3);
|
|
else
|
|
strlcpy(plusminus,"-",1);
|
|
offhr = (int) (offsetfromutc / 3600);
|
|
double hold_min;
|
|
double divby = 3600;
|
|
hold_min = fmod(offsetfromutc,divby);
|
|
offmin = (int) (hold_min / 60);
|
|
sprintf(offsethr,"%02d",abs(offhr));
|
|
sprintf(offsetmin,"%02d",abs(offmin));
|
|
val = tmptr->tm_year + 1900;
|
|
sprintf(theyear,"%d",val);
|
|
val = tmptr->tm_mon + 1;
|
|
sprintf(themonth,"%02d",val);
|
|
sprintf(theday,"%02d",tmptr->tm_mday);
|
|
sprintf(thehr,"%02d",tmptr->tm_hour);
|
|
sprintf(themin,"%02d",tmptr->tm_min);
|
|
sprintf(thesec,"%02d",tmptr->tm_sec);
|
|
strlcpy(dest,theyear,4);
|
|
strcat(dest, minus);
|
|
strcat(dest,themonth);
|
|
strcat(dest, minus);
|
|
strcat(dest,theday);
|
|
strcat(dest,T_sep);
|
|
strcat(dest,thehr);
|
|
strcat(dest,colon_sep);
|
|
strcat(dest,themin);
|
|
strcat(dest,colon_sep);
|
|
strcat(dest,thesec);
|
|
strcat(dest,plusminus);
|
|
strcat(dest,offsethr);
|
|
strcat(dest,colon_sep);
|
|
strcat(dest,offsetmin);
|
|
return strlen(dest);
|
|
}
|
|
|
|
/****************************************************************
|
|
* validate tm
|
|
* Validates a tm struct YYYY-MM-DD hh:mm:ss
|
|
* Returns 1 if successful 0 if error
|
|
****************************************************************/
|
|
int validate_tm (struct tm *tmptr)
|
|
{
|
|
int monthdays[12]={31,28,31,30,31,30,31,31,30,31,30,31};
|
|
int val;
|
|
int leap = 0;
|
|
|
|
val = tmptr->tm_year + 1900;
|
|
if ((val < 1900) || (val > 9999) )
|
|
return 0;
|
|
if ( (tmptr->tm_mon < 0) ||
|
|
(tmptr->tm_mon > 11))
|
|
return 0;
|
|
if ((tmptr->tm_mday == 29 ) && (tmptr->tm_mon == 1))
|
|
{
|
|
if ( (val % 400) == 0 )
|
|
leap = 1;
|
|
else if ((val %100) == 0)
|
|
leap = 0;
|
|
else if ((val % 4) == 0)
|
|
leap = 1;
|
|
else
|
|
leap = 0;
|
|
if (leap)
|
|
monthdays[1]=29;
|
|
else
|
|
return 0;
|
|
}
|
|
if ( (tmptr->tm_mday > monthdays[tmptr->tm_mon]) ||
|
|
(tmptr->tm_mday <=0) )
|
|
return 0;
|
|
if ( (tmptr->tm_sec > 61) ||
|
|
(tmptr->tm_sec < 0))
|
|
return 0;
|
|
if ( (tmptr->tm_min > 59) ||
|
|
(tmptr->tm_min < 0))
|
|
return 0;
|
|
if ( (tmptr->tm_hour > 23) ||
|
|
(tmptr->tm_hour < 0))
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/****************************************************************
|
|
* get_local_offset
|
|
* returns local UTC Offset
|
|
* Returns 1 if successful 0 if error
|
|
****************************************************************/
|
|
double get_local_offset()
|
|
{
|
|
time_t currtime;
|
|
struct tm * timeinfo;
|
|
time( &currtime );
|
|
timeinfo = gmtime (&currtime);
|
|
time_t utc = mktime (timeinfo);
|
|
timeinfo = localtime(&currtime);
|
|
time_t local = mktime(timeinfo);
|
|
double offsetfromutc = difftime(local,utc);
|
|
#ifdef _WIN32
|
|
if (timeinfo->tm_isdst)
|
|
offsetfromutc += 3600;
|
|
#endif
|
|
return offsetfromutc;
|
|
}
|
|
|
|
|
|
/****************************************************************
|
|
* RD_Cnv_TString_to_msec
|
|
* Converts a relative-to-midnight start time string ("HH:MM:SS.ZZZ")
|
|
* and returns it as milliseconds after midnight, or -1 if
|
|
* the conversion fails.
|
|
*****************************************************************/
|
|
int RD_Cnv_TString_to_msec(const char *str)
|
|
{
|
|
int hour;
|
|
int minute;
|
|
int second;
|
|
int tenth;
|
|
|
|
if(strlen(str)<10) {
|
|
return -1;
|
|
}
|
|
if(sscanf(str,"%02d",&hour)!=1) {
|
|
return -1;
|
|
}
|
|
if((hour<0)||(hour>23)) {
|
|
return -1;
|
|
}
|
|
if(sscanf(str+3,"%02d",&minute)!=1) {
|
|
return -1;
|
|
}
|
|
if((minute<0)||(minute>59)) {
|
|
return -1;
|
|
}
|
|
if(sscanf(str+6,"%02d",&second)!=1) {
|
|
return -1;
|
|
}
|
|
if((second<0)||(second>59)) {
|
|
return -1;
|
|
}
|
|
if(sscanf(str+9,"%1d",&tenth)!=1) {
|
|
return -1;
|
|
}
|
|
if((tenth<0)||(tenth>9)) {
|
|
return -1;
|
|
}
|
|
|
|
return 3600000*hour+60000*minute+1000*second+100*tenth;
|
|
}
|
|
|
|
|
|
/****************************************************************
|
|
* RD_Cnv_msec_to_TString
|
|
* Converts a milliseconds after midnight integer to
|
|
* time string ("HH:MM:SS.ZZZ"), returning the length
|
|
* of the string.
|
|
*****************************************************************/
|
|
size_t RD_Cnv_msec_to_TString(char *str, size_t len,int msec)
|
|
{
|
|
int hour;
|
|
int minute;
|
|
int second;
|
|
int tenth;
|
|
|
|
if(msec<0) {
|
|
str[len]=0;
|
|
return 0;
|
|
}
|
|
hour=msec/3600000;
|
|
minute=(msec-3600000*hour)/60000;
|
|
second=(msec-3600000*hour-60000*minute)/1000;
|
|
tenth=(msec-3600000*hour-60000*minute-1000*second)/100;
|
|
|
|
snprintf(str,len,"%02d:%02d:%02d.%1d",hour,minute,second,tenth);
|
|
|
|
return strlen(str);
|
|
}
|