#include #include #include #include #include #include /* #include "gaa.h" #include "gaa_simple.h" #include "gaa_util.h" #include "gaa_private.h" */ #include "cond_eval.h" //#include "time_parser.h" struct t_time_hrmin { int from_hr, to_hr; int from_min, to_min; struct t_time_hrmin *next; }; typedef struct t_time_hrmin time_hrmin; struct t_time_day { int from_day, to_day; struct t_time_day *next; }; typedef struct t_time_day time_day; struct t_time_date { int from_yr, to_yr; int from_mon, to_mon; int from_date, to_date; struct t_time_date *next; }; typedef struct t_time_date time_date; struct t_time_span { time_date *date; time_day *day; time_hrmin *hrmin; struct t_time_span *next; }; typedef struct t_time_span time_span; typedef enum { TA_ERROR=0, TA_ALLOW=1, TA_DENY=2 } time_answer; typedef enum { TT_DATE, TT_DAY, TT_HRMIN } time_type; #define MAX_ERROR_LENGTH 100 typedef struct { char *malloc_content; char *error; } time_parser; void time_initparser(time_parser *p, char* str) { p->malloc_content=(char *)malloc(strlen(str)*sizeof(char)+1); p->error=(char *)malloc(MAX_ERROR_LENGTH*sizeof(char)); strcpy(p->malloc_content,str); sprintf(p->error,"No Error"); } void time_freeparser(time_parser *p) { free(p->malloc_content); free(p->error); } void time_parsererror(time_parser *p, const char *fmt, /*args*/ ...) { va_list ap; va_start(ap, fmt); /* measure the required size */ vsprintf(p->error, fmt, ap); va_end(ap); } char *time_nexttoken(time_parser *p, char **str, char delim) { char *temp; while (**str==' ') { *str=*str+1; } temp=*str; while (**str!=delim && **str!='\0') { *str=*str+1; } if (**str==delim) { **str='\0'; *str=*str+1; } return temp; } time_answer time_answer_and(time_answer a, time_answer b) { if (a==TA_ERROR || b==TA_ERROR) { return TA_ERROR; } else return (a==TA_ALLOW && b==TA_ALLOW) ? TA_ALLOW : TA_DENY; } time_answer time_answer_or(time_answer a, time_answer b) { if (a==TA_ERROR || b==TA_ERROR) { return TA_ERROR; } else return (a==TA_ALLOW || b==TA_ALLOW) ? TA_ALLOW : TA_DENY; } static char weekday[7][4]={"SUN","MON","TUE","WED","THU","FRI","SAT"}; time_answer time_parse_hrmin(time_parser *p, char *str, int *hr, int *min) { char *curtoken; int len=strlen(str); int am_pm=0; if (*str=='\0') { *hr=-1; *min=0; return TA_ALLOW; } if (len>2) //may have am/pm { if ((str[len-1]=='m' || str[len-1]=='M')) { if (str[len-2]=='a' || str[len-2]=='A') { am_pm=1; } else if (str[len-2]=='p' || str[len-2]=='P') { am_pm=2; } else { time_parsererror(p,"Wrong hour-min expression"); return TA_ERROR; } str[len-2]='\0'; //remove am/pm } } curtoken=time_nexttoken(p,&str,':'); if (*curtoken=='\0' || strlen(curtoken)>2) { time_parsererror(p,"Wrong hour-min expression"); return TA_ERROR; } if (strcmp(curtoken,"0")==0 || strcmp(curtoken,"00")==0) { *hr=0; } else { *hr=atoi(curtoken); if (*hr==0) { time_parsererror(p,"Wrong hour-min expression"); return TA_ERROR; } } curtoken=time_nexttoken(p,&str,':'); if (*curtoken=='\0') { *min=0; } else { if (strlen(curtoken)!=2) { time_parsererror(p,"Wrong hour-min expression"); return TA_ERROR; } if (strcmp(curtoken,"00")==0) { *min=0; } else { *min=atoi(curtoken); if (*min==0) { time_parsererror(p,"Wrong hour-min expression"); return TA_ERROR; } } } if ((am_pm==1 || am_pm==2) && *hr==12) //adjust 12 to 0 is am-pm showed { *hr=0; } *hr = (am_pm==2) ? *hr+12 : *hr ; //adjust pm if ((*hr<0 || *hr>23) && !(*hr==24 && *min==0)) //24:00 is allowed as exception { time_parsererror(p,"Wrong hour-min expression, hour must be 0-23 or 24:00"); return TA_ERROR; } if (*min<0 || *min>59) { time_parsererror(p,"Wrong hour-min expression, minute must be 0-59"); return TA_ERROR; } return TA_ALLOW; } time_answer time_parse_hrminpair(time_parser *p, struct tm *t, char *str) { int hr1,hr2; int min1,min2; if (time_parse_hrmin(p, time_nexttoken(p,&str,'-'), &hr1, &min1)==TA_ERROR) { return TA_ERROR; } if (time_parse_hrmin(p, time_nexttoken(p,&str,'\0'), &hr2, &min2)==TA_ERROR) { return TA_ERROR; } if (hr1==-1 && hr2==-1) { time_parsererror(p,"Wrong hour-min expression"); return TA_ERROR; } else if (hr1==-1) { return (t->tm_hour*60+t->tm_min<=hr2*60+min2) ? TA_ALLOW : TA_DENY ; } else if (hr2==-1) { return (hr1*60+min1<=t->tm_hour*60+t->tm_min) ? TA_ALLOW : TA_DENY ; } else //hr1!=-1 hr2!=-1 { int temp=t->tm_hour*60+t->tm_min; return (hr1*60+min1<=temp && temp<=hr2*60+min2) ? TA_ALLOW : TA_DENY ; } } time_answer time_parse_day(time_parser *p, char *str, int *day, int flag) { int i; if (*str=='\0') { *day=-1; return TA_ALLOW; } for (i=0;i<7;i++) { if (strcasecmp(str,weekday[i])==0) { if (i==0 && flag==1) { i=7; } *day=i; return TA_ALLOW; } } time_parsererror(p,"Wrong weekday expression, must be one of SUN,MON,TUE,WED,THU,FRI,SAT"); return TA_ERROR; } time_answer time_parse_daypair(time_parser *p, struct tm *t, char *str) { int day1,day2; int has_slash=(strchr(str,'-')!=NULL)?1:0; //1:have slash 0:don't have slash if (time_parse_day(p, time_nexttoken(p,&str,'-'), &day1, 0)==TA_ERROR) { return TA_ERROR; } if (time_parse_day(p, time_nexttoken(p,&str,'\0'), &day2, 1)==TA_ERROR) { return TA_ERROR; } if (day1==-1) //-WWW { return (t->tm_wday<=day2) ? TA_ALLOW : TA_DENY ; } else if (day2==-1 && has_slash==1) //WWW- { return (day1<=t->tm_wday) ? TA_ALLOW : TA_DENY ; } else if (day2==-1 && has_slash==0) //WWW { return (day1==t->tm_wday) ? TA_ALLOW : TA_DENY ; } else //WWW-WWW { if (day2==0) { day2=7; } return (day1<=t->tm_wday && t->tm_wday<=day2) ? TA_ALLOW : TA_DENY ; } } time_answer time_parse_date(time_parser *p, char *str, int *year, int *month, int *date) { char *curtoken; if (*str=='\0') { *year=*month=*date=0; return TA_ALLOW; } curtoken=time_nexttoken(p,&str,'/'); if (strlen(curtoken)>2) { time_parsererror(p,"Wrong date expression"); return TA_ERROR; } if (strcmp(curtoken,"0")==0 || strcmp(curtoken,"00")==0) { *month=0; } else { *month=atoi(curtoken); if (*month<1 || *month>12) { time_parsererror(p,"Wrong date expression, month must be 0-12 (0 means any)"); return TA_ERROR; } } curtoken=time_nexttoken(p,&str,'/'); if (strlen(curtoken)>2) { time_parsererror(p,"Wrong date expression"); return TA_ERROR; } *date=atoi(curtoken); if (*date<1 || *date>31) { time_parsererror(p,"Wrong date expression, monthday must be 1-31"); return TA_ERROR; } curtoken=time_nexttoken(p,&str,'\0'); if (*curtoken=='\0') { *year=0; } else { if (strlen(curtoken)==2) { *year=atoi(curtoken); if (*year>=70) { *year+=1900; } else if (*year<=30) { *year+=2000; } else { time_parsererror(p,"Wrong date expression, year must be 1970-2030 or 70-99 or 0-30"); return TA_ERROR; } } else if (strlen(curtoken)==4) { *year=atoi(curtoken); if (*year<1970 || 2030<*year) { time_parsererror(p,"Wrong date expression, year must be 1970-2030 or 70-99 or 0-30"); return TA_ERROR; } } else { time_parsererror(p,"Wrong date expression"); return TA_ERROR; } } return TA_ALLOW; } time_answer time_parse_datepair(time_parser *p, struct tm *t, char *str) { int month1, date1, year1; int month2, date2, year2; int has_slash=(strchr(str,'-')!=NULL)?1:0; //1:have slash 0:don't have slash if (time_parse_date(p, time_nexttoken(p,&str,'-'), &year1, &month1, &date1)==TA_ERROR) { return TA_ERROR; } if (time_parse_date(p, time_nexttoken(p,&str,'\0'), &year2, &month2, &date2)==TA_ERROR) { return TA_ERROR; } if (year1!=0 && year2!=0 && month1!=0 && month2!=0 && date1!=0 && date2!=0) // MM/DD/YY-MM/DD/YY { int temp=t->tm_year*12*31+t->tm_mon*31+t->tm_mday; return ( year1*12*31+month1*31+date1 <= temp && temp <= year2*12*31+month2*31+date2 ) ? TA_ALLOW : TA_DENY ; } else if (year1==0 && year2==0 && month1!=0 && month2!=0 && date1!=0 && date2!=0) // MM/DD-MM/DD { int temp=t->tm_mon*31+t->tm_mday; return ( month1*31+date1 <= temp && temp <= month2*31+date2 ) ? TA_ALLOW : TA_DENY ; } else if (year1==0 && year2==0 && month1==0 && month2==0 && date1!=0 && date2!=0) // 0/DD-0/DD { return ( date1 <= t->tm_mday && t->tm_mday <= date2 ) ? TA_ALLOW : TA_DENY ; } else if (year1==0 && month1==0 && date1==0) // -MM/DD/YY { return ((year2==0) ? ((month2==0) ? ((t->tm_mday<=date2) ? TA_ALLOW : TA_DENY) // -0/DD :((t->tm_mon*31+t->tm_mday <= month2*32+date2) ? TA_ALLOW : TA_DENY)) // -MM/DD :((t->tm_year*12*31+t->tm_mon*31+t->tm_mday <= year2*12*32+month2*32+date2) ? TA_ALLOW : TA_DENY)); // -YY/MM/DD } else if (year2==0 && month2==0 && date2==0 && has_slash==1) // MM/DD/YY- { return ((year1==0) ? ((month1==0) ? ((date1<=t->tm_mday) ? TA_ALLOW : TA_DENY) // 0/DD- :((month1*31+date1 <= t->tm_mon*31+t->tm_mday) ? TA_ALLOW : TA_DENY)) // MM/DD- :((year1*12*31+month1*31+date1 <= t->tm_year*12*31+t->tm_mon*31+t->tm_mday) ? TA_ALLOW : TA_DENY)); // MM/DD/YY- } else if (year2==0 && year2==0 && year2==0 && has_slash==0) // MM/DD/YY { return ((year1==0) ? ((month1==0) ? ((date1==t->tm_mday) ? TA_ALLOW : TA_DENY) // 0/DD :((month1==t->tm_mon && date1==t->tm_mday) ? TA_ALLOW : TA_DENY)) // MM/DD :((year1==t->tm_year && month1==t->tm_mon && date1==t->tm_mday) ? TA_ALLOW : TA_DENY)); // MM/DD/YY } else { time_parsererror(p,"Not a valid pair of date"); return TA_ERROR; } } time_answer time_parse_list(time_parser *p, struct tm *t, char *str, time_type tt) { time_answer answer=TA_DENY; char *curtoken; curtoken=time_nexttoken(p,&str,','); while (*curtoken!='\0') { if (tt==TT_DATE) { answer=time_answer_or(answer, time_parse_datepair(p,t,curtoken)); } else if (tt==TT_DAY) { answer=time_answer_or(answer, time_parse_daypair(p,t,curtoken)); } else //TT_HRMIN { answer=time_answer_or(answer, time_parse_hrminpair(p,t,curtoken)); } curtoken=time_nexttoken(p,&str,','); } return answer; } int isdate(char *str) { return (strchr(str,'/')!=NULL); } int isweekday(char *str) { if (*str=='-') { return !isdigit(*(str+1)); } else { return !isdigit(*str); } } time_answer time_parse_block(time_parser *p, struct tm *t, char *str) { time_answer answer=TA_ALLOW; char *curtoken; curtoken=time_nexttoken(p,&str,' '); if (isdate(curtoken)) //date ? ? { answer=time_parse_list(p,t,curtoken,TT_DATE); if (answer==TA_ERROR) { return TA_ERROR; } curtoken=time_nexttoken(p,&str,' '); if (*curtoken!='\0') { if (isweekday(curtoken)) //date day ? { answer=time_answer_and(answer,time_parse_list(p,t,curtoken,TT_DAY)); if (answer==TA_ERROR) { return TA_ERROR; } curtoken=time_nexttoken(p,&str,' '); if (*curtoken!='\0') //date day hrmin { answer=time_answer_and(answer,time_parse_list(p,t,curtoken,TT_HRMIN)); if (answer==TA_ERROR) { return TA_ERROR; } } } else //date hrmin { answer=time_answer_and(answer,time_parse_list(p,t,curtoken,TT_HRMIN)); if (answer==TA_ERROR) { return TA_ERROR; } } } } else if (isweekday(curtoken)) //day ? { answer=time_parse_list(p,t,curtoken,TT_DAY); if (answer==TA_ERROR) { return TA_ERROR; } curtoken=time_nexttoken(p,&str,' '); if (*curtoken!='\0') //day hrmin { answer=time_answer_and(answer,time_parse_list(p,t,curtoken,TT_HRMIN)); if (answer==TA_ERROR) { return TA_ERROR; } } } else //hrmin { answer=time_parse_list(p,t,curtoken,TT_HRMIN); if (answer==TA_ERROR) { return TA_ERROR; } } curtoken=time_nexttoken(p,&str,' '); if (*curtoken!='\0') { time_parsererror(p,"Too much tokens, must be in form [date] [weekday] [time]"); return TA_ERROR; } return answer; } time_answer time_do_parse(time_parser *p, struct tm *t) { time_answer answer=TA_DENY; char *curtoken; char *str=p->malloc_content; t->tm_mon++; t->tm_year+=1900; curtoken=time_nexttoken(p,&str,';'); while (*curtoken!='\0') { answer=time_answer_or(answer,time_parse_block(p,t,curtoken)); if (answer==TA_ERROR) { return TA_ERROR; } curtoken=time_nexttoken(p,&str,';'); } t->tm_mon--; t->tm_year-=1900; return answer; } gaa_status cb_check_cond_access_time (gaa_ptr gaa, gaa_sc_ptr sc, gaa_condition *cond, gaa_time_period *valid_time, gaa_request_right_ptr right, gaa_status rstatus, gaa_string_data estatus, gaa_status *output_flags, void *params) { time_parser p; time_answer answer; time_t timet; struct tm *timem; gaa_status ret=GAA_S_SUCCESS; if (strcmp(cond->authority,"gmt")==0) { time(&timet); timem=gmtime(&timet); } else if (strcmp(cond->authority,"local")==0) { time(&timet); timem=gmtime(&timet); } else { timem=(struct tm *)get_request_option(right,"time",cond->authority); if (timem==0) { return GAA_S_INVALID_ARG; } } *output_flags |= GAA_COND_FLG_EVALUATED; time_initparser(&p, cond->value); answer=time_do_parse(&p, timem); if (answer==TA_ERROR) { //LOG2("Time Parser Report Error: %s",p.error); ret=GAA_S_POLICY_PARSING_FAILURE; } else if (answer==TA_ALLOW) { *output_flags |= GAA_COND_FLG_MET; } else //TA_DENY { //none } time_freeparser(&p); return ret; }