/************************************************************************** * * TRENDS.C - NetSaint State Trends CGI * * Copyright (c) 1999-2001 Ethan Galstad (netsaint@netsaint.org) * Last Modified: 10-30-2001 * * License: * * 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 of the License, 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 "../common/config.h" #include "../common/locations.h" #include "../common/common.h" #include "../common/objects.h" #include "../common/comments.h" #include "../common/statusdata.h" #include "cgiutils.h" #include "getcgi.h" #include "auth.h" #include "edata.h" #include /* Boutell's GD library function */ #include /* GD library small font definition */ /*#define DEBUG 1*/ /* archived state types */ #define AS_NO_DATA 0 #define AS_PROGRAM_END 1 #define AS_PROGRAM_START 2 #define AS_HOST_UP 3 #define AS_HOST_DOWN 4 #define AS_HOST_UNREACHABLE 5 #define AS_SVC_OK 6 #define AS_SVC_UNKNOWN 7 #define AS_SVC_WARNING 8 #define AS_SVC_CRITICAL 9 /* display types */ #define DISPLAY_HOST_TRENDS 0 #define DISPLAY_SERVICE_TRENDS 1 #define DISPLAY_NO_TRENDS 2 /* input types */ #define GET_INPUT_NONE 0 #define GET_INPUT_TARGET_TYPE 1 #define GET_INPUT_HOST_TARGET 2 #define GET_INPUT_SERVICE_TARGET 3 #define GET_INPUT_OPTIONS 4 /* modes */ #define CREATE_HTML 0 #define CREATE_IMAGE 1 /* standard report times */ #define TIMEPERIOD_CUSTOM 0 #define TIMEPERIOD_TODAY 1 #define TIMEPERIOD_YESTERDAY 2 #define TIMEPERIOD_THISWEEK 3 #define TIMEPERIOD_LASTWEEK 4 #define TIMEPERIOD_THISMONTH 5 #define TIMEPERIOD_LASTMONTH 6 #define TIMEPERIOD_THISQUARTER 7 #define TIMEPERIOD_LASTQUARTER 8 #define TIMEPERIOD_THISYEAR 9 #define TIMEPERIOD_LASTYEAR 10 #define TIMEPERIOD_LAST24HOURS 11 #define TIMEPERIOD_LAST7DAYS 12 #define MIN_TIMESTAMP_SPACING 10 #define MAX_ARCHIVE_SPREAD 65 #define MAX_ARCHIVE 65 #define MAX_ARCHIVE_BACKTRACKS 60 authdata current_authdata; typedef struct archived_state_struct{ time_t time_stamp; int entry_type; char *state_info; struct archived_state_struct *next; }archived_state; archived_state *as_list=NULL; time_t t1; time_t t2; int display_type=DISPLAY_NO_TRENDS; int mode=CREATE_HTML; int timeperiod_type=TIMEPERIOD_LAST24HOURS; int display_popups=TRUE; int use_map=TRUE; int assume_initial_states=TRUE; int assume_state_retention=TRUE; int assume_initial_state_ok=TRUE; char *host_name=""; char *svc_description=""; void graph_all_trend_data(void); void graph_trend_data(int,int,time_t,time_t,time_t,char *); void draw_timestamps(void); void draw_timestamp(int,time_t); void draw_time_breakdowns(void); void draw_horizontal_grid_lines(void); void draw_dashed_line(int,int,int,int,int); int convert_host_state_to_archived_state(int); int convert_service_state_to_archived_state(int); void add_archived_state(int,time_t,char *); void free_archived_state_list(void); void read_archived_state_data(void); void scan_log_file_for_archived_state_data(char *); void convert_timeperiod_to_times(int); void get_time_breakdown_string(unsigned long,unsigned long,char *,char *buffer,int); void document_header(int); void document_footer(void); int process_cgivars(void); void write_popup_code(void); extern char main_config_file[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; extern char physical_images_path[MAX_FILENAME_LENGTH]; extern host *host_list; extern service *service_list; extern int log_rotation_method; extern time_t last_scheduled_log_rotation; gdImagePtr trends_image=0; int color_white=0; int color_black=0; int color_red=0; int color_darkred=0; int color_green=0; int color_yellow=0; int color_orange=0; FILE *image_file=NULL; int image_width=600; int image_height=300; #define HOST_DRAWING_WIDTH 498 #define HOST_DRAWING_HEIGHT 70 #define HOST_DRAWING_X_OFFSET 116 #define HOST_DRAWING_Y_OFFSET 55 #define SVC_DRAWING_WIDTH 498 #define SVC_DRAWING_HEIGHT 90 #define SVC_DRAWING_X_OFFSET 116 #define SVC_DRAWING_Y_OFFSET 55 int drawing_width=0; int drawing_height=0; int drawing_x_offset=0; int drawing_y_offset=0; int last_known_state=AS_NO_DATA; int zoom_factor=4; int backtrack_archives=2; int earliest_archive=0; time_t earliest_time; time_t latest_time; int earliest_state=AS_NO_DATA; int latest_state=AS_NO_DATA; unsigned long time_up=0L; unsigned long time_down=0L; unsigned long time_unreachable=0L; unsigned long time_ok=0L; unsigned long time_warning=0L; unsigned long time_unknown=0L; unsigned long time_critical=0L; int embedded=FALSE; int display_header=TRUE; int input_type=GET_INPUT_NONE; int main(int argc, char **argv){ int result=OK; char temp_buffer[MAX_INPUT_BUFFER]; char image_template[MAX_INPUT_BUFFER]; char start_time[MAX_INPUT_BUFFER]; char end_time[MAX_INPUT_BUFFER]; int string_width; int string_height; char start_timestring[MAX_INPUT_BUFFER]; char end_timestring[MAX_INPUT_BUFFER]; host *temp_host; service *temp_service; int is_authorized=TRUE; int found=FALSE; int days,hours,minutes,seconds; char *first_service=NULL; /* initialize time period to last 24 hours */ time(&t2); t1=(time_t)(t2-(60*60*24)); /* get the arguments passed in the URL */ process_cgivars(); /* reset internal CGI variables */ reset_cgi_vars(); /* read the CGI configuration file */ result=read_cgi_config_file(DEFAULT_CGI_CONFIG_FILE); if(result==ERROR){ if(mode==CREATE_HTML){ document_header(FALSE); printf("

Error: Could not open CGI configuration file '%s' for reading!

\n",DEFAULT_CGI_CONFIG_FILE); document_footer(); } return ERROR; } document_header(TRUE); /* read the main configuration file */ result=read_main_config_file(main_config_file); if(result==ERROR){ if(mode==CREATE_HTML){ printf("

Error: Could not open main configuration file '%s' for reading!

\n",main_config_file); document_footer(); } return ERROR; } /* read all object configuration data */ result=read_all_object_configuration_data(main_config_file,READ_HOSTGROUPS|READ_CONTACTGROUPS|READ_CONTACTS|READ_HOSTS|READ_SERVICES); if(result==ERROR){ if(mode==CREATE_HTML){ printf("

Error: Could not read some or all object configuration data!

\n"); document_footer(); } return ERROR; } /* read all status data */ result=read_all_status_data(DEFAULT_CGI_CONFIG_FILE,READ_PROGRAM_STATUS|READ_HOST_STATUS|READ_SERVICE_STATUS); if(result==ERROR){ if(mode==CREATE_HTML){ printf("

Error: Could not read host and service status information!

\n"); document_footer(); } return ERROR; } /* get authentication information */ get_authentication_information(¤t_authdata); if(mode==CREATE_HTML && display_header==TRUE){ /* begin top table */ printf("\n"); printf("\n"); /* left column of the first row */ printf("\n"); /* center column of top row */ printf("\n"); /* right hand column of top row */ printf("\n"); /* end of top table */ printf("\n"); printf("
\n"); if(display_type==DISPLAY_HOST_TRENDS) snprintf(temp_buffer,sizeof(temp_buffer)-1,"Host State Trends"); else if(display_type==DISPLAY_SERVICE_TRENDS) snprintf(temp_buffer,sizeof(temp_buffer)-1,"Service State Trends"); else snprintf(temp_buffer,sizeof(temp_buffer)-1,"Host and Service State Trends"); temp_buffer[sizeof(temp_buffer)-1]='\x0'; display_info_table(temp_buffer,FALSE,¤t_authdata); if(display_type!=DISPLAY_NO_TRENDS && input_type==GET_INPUT_NONE){ printf("\n"); printf("\n"); printf("\n"); } printf("\n"); if(display_type!=DISPLAY_NO_TRENDS && input_type==GET_INPUT_NONE){ printf("
\n"); if(display_type==DISPLAY_HOST_TRENDS) printf("Host '%s'",host_name); else if(display_type==DISPLAY_SERVICE_TRENDS) printf("Service '%s' On Host '%s'",svc_description,host_name); printf("
\n"); printf("
\n"); printf("%s State Trends\n",url_images_path,TRENDS_ICON,(display_type==DISPLAY_HOST_TRENDS)?"Host":"Service"); printf("
\n"); get_time_string(&t1,start_timestring,sizeof(start_timestring)-1,SHORT_DATE_TIME); get_time_string(&t2,end_timestring,sizeof(end_timestring)-1,SHORT_DATE_TIME); printf("
%s to %s
\n",start_timestring,end_timestring); get_time_breakdown((time_t)(t2-t1),&days,&hours,&minutes,&seconds); printf("
Duration: %dd %dh %dm %ds
\n",days,hours,minutes,seconds); } printf("
\n"); if(display_type!=DISPLAY_NO_TRENDS && input_type==GET_INPUT_NONE){ printf("\n"); printf("\n",TRENDS_CGI); if(display_popups==FALSE) printf("\n"); if(use_map==FALSE) printf("\n"); printf("\n",(unsigned long)t1); printf("\n",(unsigned long)t2); printf("\n",host_name); if(display_type==DISPLAY_SERVICE_TRENDS) printf("\n",svc_description); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("
Assume initial states:Assume state retention:
\n"); printf("\n"); printf("\n"); printf("\n"); printf("
Assume initial state ok:Backtracked archives:
"); printf("\n"); printf("\n"); printf("\n",backtrack_archives); printf("
Report period:Zoom factor:
\n"); printf("\n"); printf("\n"); printf("\n"); printf("
\n"); printf("\n"); printf("\n"); printf("
\n"); } printf("
\n"); } #ifndef DEBUG /* check authorization... */ if(display_type==DISPLAY_HOST_TRENDS){ temp_host=find_host(host_name,NULL); if(temp_host==NULL || is_authorized_for_host(temp_host,¤t_authdata)==FALSE) is_authorized=FALSE; } else if(display_type==DISPLAY_SERVICE_TRENDS){ temp_service=find_service(host_name,svc_description,NULL); if(temp_service==NULL || is_authorized_for_service(temp_service,¤t_authdata)==FALSE) is_authorized=FALSE; } if(is_authorized==FALSE){ if(mode==CREATE_HTML) printf("

It appears as though you are not authorized to view information for the specified %s...

\n",(display_type==DISPLAY_HOST_TRENDS)?"host":"service"); document_footer(); free_memory(); return ERROR; } #endif /* set drawing parameters, etc */ if(display_type==DISPLAY_HOST_TRENDS){ drawing_width=HOST_DRAWING_WIDTH; drawing_height=HOST_DRAWING_HEIGHT; drawing_x_offset=HOST_DRAWING_X_OFFSET; drawing_y_offset=HOST_DRAWING_Y_OFFSET; last_known_state=AS_HOST_UP; } else if(display_type==DISPLAY_SERVICE_TRENDS){ drawing_width=SVC_DRAWING_WIDTH; drawing_height=SVC_DRAWING_HEIGHT; drawing_x_offset=SVC_DRAWING_X_OFFSET; drawing_y_offset=SVC_DRAWING_Y_OFFSET; last_known_state=AS_SVC_OK; } /* initialize PNG image */ if(display_type!=DISPLAY_NO_TRENDS && mode==CREATE_IMAGE){ if(display_type==DISPLAY_HOST_TRENDS) snprintf(image_template,sizeof(image_template)-1,"%s/trendshost.png",physical_images_path); else snprintf(image_template,sizeof(image_template)-1,"%s/trendssvc.png",physical_images_path); image_template[sizeof(image_template)-1]='\x0'; /* allocate buffer for storing image */ /*trends_image=gdImageCreate(image_width,image_height);*/ image_file=fopen(image_template,"r"); if(image_file==NULL) return ERROR; trends_image=gdImageCreateFromPng(image_file); if(trends_image==NULL){ #ifdef DEBUG printf("Error: Could not allocate memory for image\n"); #endif return ERROR; } fclose(image_file); /* allocate colors used for drawing */ color_white=gdImageColorAllocate(trends_image,255,255,255); color_black=gdImageColorAllocate(trends_image,0,0,0); color_red=gdImageColorAllocate(trends_image,255,0,0); color_darkred=gdImageColorAllocate(trends_image,128,0,0); color_green=gdImageColorAllocate(trends_image,0,210,0); color_yellow=gdImageColorAllocate(trends_image,220,220,0); color_orange=gdImageColorAllocate(trends_image,255,100,25); /* set transparency index */ gdImageColorTransparent(trends_image,color_white); /* make sure the graphic is interlaced */ gdImageInterlace(trends_image,1); /* title */ snprintf(start_time,sizeof(start_time)-1,"%s",ctime(&t1)); start_time[sizeof(start_time)-1]='\x0'; start_time[strlen(start_time)-1]='\x0'; snprintf(end_time,sizeof(end_time)-1,"%s",ctime(&t2)); end_time[sizeof(end_time)-1]='\x0'; end_time[strlen(end_time)-1]='\x0'; string_height=gdFontSmall->h; if(display_type==DISPLAY_HOST_TRENDS) snprintf(temp_buffer,sizeof(temp_buffer)-1,"State History For Host '%s'",host_name); else snprintf(temp_buffer,sizeof(temp_buffer)-1,"State History For Service '%s' On Host '%s'",svc_description,host_name); temp_buffer[sizeof(temp_buffer)-1]='\x0'; string_width=gdFontSmall->w*strlen(temp_buffer); gdImageString(trends_image,gdFontSmall,(drawing_width/2)-(string_width/2)+drawing_x_offset,string_height,(unsigned char *)temp_buffer,color_black); snprintf(temp_buffer,sizeof(temp_buffer)-1,"%s to %s",start_time,end_time); temp_buffer[sizeof(temp_buffer)-1]='\x0'; string_width=gdFontSmall->w*strlen(temp_buffer); gdImageString(trends_image,gdFontSmall,(drawing_width/2)-(string_width/2)+drawing_x_offset,(string_height*2)+5,(unsigned char *)temp_buffer,color_black); /* first time stamp */ snprintf(temp_buffer,sizeof(temp_buffer)-1,"%s",start_time); temp_buffer[sizeof(temp_buffer)-1]='\x0'; string_width=gdFontSmall->w*strlen(temp_buffer); gdImageStringUp(trends_image,gdFontSmall,drawing_x_offset-(string_height/2),drawing_y_offset+drawing_height+string_width+5,(unsigned char *)temp_buffer,color_black); } if(display_type!=DISPLAY_NO_TRENDS && input_type==GET_INPUT_NONE){ if(mode==CREATE_IMAGE || (mode==CREATE_HTML && use_map==TRUE)){ /* read in all necessary archived state data */ read_archived_state_data(); /* graph archived state trend data */ graph_all_trend_data(); } /* print URL to image */ if(mode==CREATE_HTML){ printf("

\n"); printf("
\n"); printf("\n"); printf("
\n"); } if(mode==CREATE_IMAGE || (mode==CREATE_HTML && use_map==TRUE)){ /* draw timestamps */ draw_timestamps(); /* draw horizontal lines */ draw_horizontal_grid_lines(); /* draw state time breakdowns */ draw_time_breakdowns(); } if(mode==CREATE_IMAGE){ /* use STDOUT for writing the image data... */ image_file=stdout; #ifndef DEBUG /* write the image to file */ gdImagePng(trends_image,image_file); #endif #ifdef DEBUG image_file=fopen("trends.png","w"); if(image_file==NULL) printf("Could not open trends.png for writing!\n"); else{ gdImagePng(trends_image,image_file); fclose(image_file); } #endif /* free memory allocated to image */ gdImageDestroy(trends_image); } else{ printf("

"); printf("Note: The host/service state breakdowns displayed above may not be 100%% accurate. "); printf("However, they reflect best estimates based upon the historical information that is stored in the log files. "); printf("This CGI assumes that historical data is stored in archived log files, as determined by the log_rotation_method and "); printf("log_archive_path variables in the main configuration file. "); printf("If the beginning portion (or all) of the graph is empty, try using the 'Backtracked archives' option to specify the number "); printf("of archived log files (occurring prior to the initial time displayed in the graph) that the CGI should scan for initial state information.\n"); printf("

\n"); } } /* show user a selection of hosts and services to choose from... */ if(display_type==DISPLAY_NO_TRENDS || input_type!=GET_INPUT_NONE){ /* ask the user for what host they want a report for */ if(input_type==GET_INPUT_HOST_TARGET){ printf("

\n"); printf("
Step 2: Select Host
\n"); printf("

\n"); printf("

\n"); printf("\n"); printf("\n",TRENDS_CGI); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("
Host\n"); printf("\n"); printf("
\n"); printf("\n"); printf("
\n"); printf("

\n"); } /* ask the user for what service they want a report for */ else if(input_type==GET_INPUT_SERVICE_TARGET){ printf("\n"); printf("

\n"); printf("
Step 2: Select Service
\n"); printf("

\n"); printf("

\n"); printf("\n"); printf("\n",TRENDS_CGI); printf("\n"); printf("\n",(first_service==NULL)?"unknown":first_service); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("
Service:\n"); printf("\n"); printf("
\n"); printf("\n"); printf("
\n"); printf("

\n"); } /* ask the user for report range and options */ else if(input_type==GET_INPUT_OPTIONS){ printf("

\n"); printf("
Step 3: Select Report Range and Options
\n"); printf("

\n"); printf("

\n"); printf("\n"); printf("\n",TRENDS_CGI); printf("\n",host_name); if(display_type==DISPLAY_SERVICE_TRENDS) printf("\n",svc_description); printf("\n"); printf("\n"); printf(""); printf("\n"); printf("\n"); printf("\n"); printf("
Report period:\n"); printf("\n"); printf("
Suppress image map:
Suppress popups:
\n"); printf("

\n"); printf("

\n"); printf("Note: Choosing the 'suppress image map' option will make the report run approximately twice as fast as it would otherwise, but it will prevent you from being able to zoom in on specific time periods.\n"); printf("

\n"); } /* as the user whether they want a graph for a host or service */ else{ printf("

\n"); printf("
Step 1: Select Report Type
\n"); printf("

\n"); printf("

\n"); printf("\n"); printf("\n",TRENDS_CGI); printf("\n"); printf("\n"); printf("\n"); printf("\n"); printf("
Host
Service
\n"); printf("\n"); printf("
\n"); printf("

\n"); } } document_footer(); /* free memory allocated to the archived state data list */ free_archived_state_list(); /* free all other allocated memory */ free_memory(); return OK; } void document_header(int use_stylesheet){ char date_time[MAX_DATETIME_LENGTH]; time_t current_time; time_t expire_time; if(mode==CREATE_HTML){ printf("Cache-Control: no-store\n"); printf("Pragma: no-cache\n"); time(¤t_time); get_time_string(¤t_time,date_time,sizeof(date_time),HTTP_DATE_TIME); printf("Last-Modified: %s\n",date_time); expire_time=(time_t)0; get_time_string(&expire_time,date_time,sizeof(date_time),HTTP_DATE_TIME); printf("Expires: %s\n",date_time); printf("Content-type: text/html\n\n"); if(embedded==TRUE) return; printf("\n"); printf("\n"); printf("\n"); printf("NetSaint Trends\n"); printf("\n"); if(use_stylesheet==TRUE) printf("\n",url_stylesheets_path,TRENDS_CSS); /* write JavaScript code for popup window */ if(display_type!=DISPLAY_NO_TRENDS) write_popup_code(); printf("\n"); printf("\n"); printf("
\n"); } else{ printf("Cache-Control: no-store\n"); printf("Pragma: no-cache\n"); time(¤t_time); get_time_string(¤t_time,date_time,sizeof(date_time),HTTP_DATE_TIME); printf("Last-Modified: %s\n",date_time); expire_time=(time_t)0L; get_time_string(&expire_time,date_time,sizeof(date_time),HTTP_DATE_TIME); printf("Expires: %s\n",date_time); printf("Content-Type: image/png\n\n"); } return; } void document_footer(void){ if(embedded==TRUE) return; if(mode==CREATE_HTML){ printf("\n"); printf("\n"); } return; } int process_cgivars(void){ char **variables; int error=FALSE; int x; variables=getcgivars(); for(x=0;variables[x]!=NULL;x++){ /* do some basic length checking on the variable identifier to prevent buffer overflows */ if(strlen(variables[x])>=MAX_INPUT_BUFFER-1){ x++; continue; } /* we found the host argument */ else if(!strcmp(variables[x],"host")){ x++; if(variables[x]==NULL){ error=TRUE; break; } host_name=(char *)malloc(strlen(variables[x])+1); if(host_name==NULL) host_name=""; else strcpy(host_name,variables[x]); display_type=DISPLAY_HOST_TRENDS; } /* we found the node width argument */ else if(!strcmp(variables[x],"service")){ x++; if(variables[x]==NULL){ error=TRUE; break; } svc_description=(char *)malloc(strlen(variables[x])+1); if(svc_description==NULL) svc_description=""; else strcpy(svc_description,variables[x]); display_type=DISPLAY_SERVICE_TRENDS; } /* we found first time argument */ else if(!strcmp(variables[x],"t1")){ x++; if(variables[x]==NULL){ error=TRUE; break; } t1=(time_t)strtoul(variables[x],NULL,10); timeperiod_type=TIMEPERIOD_CUSTOM; } /* we found first time argument */ else if(!strcmp(variables[x],"t2")){ x++; if(variables[x]==NULL){ error=TRUE; break; } t2=(time_t)strtoul(variables[x],NULL,10); timeperiod_type=TIMEPERIOD_CUSTOM; } /* we found the image creation option */ else if(!strcmp(variables[x],"createimage")){ mode=CREATE_IMAGE; } /* we found the assume initial states option */ else if(!strcmp(variables[x],"assumeinitialstates")){ x++; if(variables[x]==NULL){ error=TRUE; break; } if(!strcmp(variables[x],"on")) assume_initial_states=TRUE; else assume_initial_states=FALSE; } /* we found the assume initial state ok option */ else if(!strcmp(variables[x],"assumeinitialstateok")){ x++; if(variables[x]==NULL){ error=TRUE; break; } if(!strcmp(variables[x],"on")) assume_initial_state_ok=TRUE; else assume_initial_state_ok=FALSE; } /* we found the assume state retention option */ else if(!strcmp(variables[x],"assumestateretention")){ x++; if(variables[x]==NULL){ error=TRUE; break; } if(!strcmp(variables[x],"on")) assume_state_retention=TRUE; else assume_state_retention=FALSE; } /* we found the zoom factor argument */ else if(!strcmp(variables[x],"zoom")){ x++; if(variables[x]==NULL){ error=TRUE; break; } zoom_factor=atoi(variables[x]); if(zoom_factor==0) zoom_factor=1; } /* we found the backtrack archives argument */ else if(!strcmp(variables[x],"backtrack")){ x++; if(variables[x]==NULL){ error=TRUE; break; } backtrack_archives=atoi(variables[x]); if(backtrack_archives<0) backtrack_archives=0; if(backtrack_archives>MAX_ARCHIVE_BACKTRACKS) backtrack_archives=MAX_ARCHIVE_BACKTRACKS; } /* we found the standard timeperiod argument */ else if(!strcmp(variables[x],"timeperiod")){ x++; if(variables[x]==NULL){ error=TRUE; break; } if(!strcmp(variables[x],"today")) timeperiod_type=TIMEPERIOD_TODAY; else if(!strcmp(variables[x],"yesterday")) timeperiod_type=TIMEPERIOD_YESTERDAY; else if(!strcmp(variables[x],"thisweek")) timeperiod_type=TIMEPERIOD_THISWEEK; else if(!strcmp(variables[x],"lastweek")) timeperiod_type=TIMEPERIOD_LASTWEEK; else if(!strcmp(variables[x],"thismonth")) timeperiod_type=TIMEPERIOD_THISMONTH; else if(!strcmp(variables[x],"lastmonth")) timeperiod_type=TIMEPERIOD_LASTMONTH; else if(!strcmp(variables[x],"thisquarter")) timeperiod_type=TIMEPERIOD_THISQUARTER; else if(!strcmp(variables[x],"lastquarter")) timeperiod_type=TIMEPERIOD_LASTQUARTER; else if(!strcmp(variables[x],"thisyear")) timeperiod_type=TIMEPERIOD_THISYEAR; else if(!strcmp(variables[x],"lastyear")) timeperiod_type=TIMEPERIOD_LASTYEAR; else if(!strcmp(variables[x],"last24hours")) timeperiod_type=TIMEPERIOD_LAST24HOURS; else if(!strcmp(variables[x],"last7days")) timeperiod_type=TIMEPERIOD_LAST7DAYS; else if(!strcmp(variables[x],"custom")) timeperiod_type=TIMEPERIOD_CUSTOM; else return error; convert_timeperiod_to_times(timeperiod_type); } /* we found the embed option */ else if(!strcmp(variables[x],"embedded")) embedded=TRUE; /* we found the noheader option */ else if(!strcmp(variables[x],"noheader")) display_header=FALSE; /* we found the nopopups option */ else if(!strcmp(variables[x],"nopopups")) display_popups=FALSE; /* we found the nomap option */ else if(!strcmp(variables[x],"nomap")){ display_popups=FALSE; use_map=FALSE; } /* we found the input option */ else if(!strcmp(variables[x],"input")){ x++; if(variables[x]==NULL){ error=TRUE; break; } if(!strcmp(variables[x],"gethost")) input_type=GET_INPUT_HOST_TARGET; else if(!strcmp(variables[x],"getservice")) input_type=GET_INPUT_SERVICE_TARGET; else if(!strcmp(variables[x],"getoptions")) input_type=GET_INPUT_OPTIONS; else input_type=GET_INPUT_TARGET_TYPE; } } return error; } /* top level routine for graphic all trend data */ void graph_all_trend_data(void){ archived_state *temp_as; archived_state *last_as; time_t a; time_t b; time_t current_time; int current_state=AS_NO_DATA; int graph_end_data=TRUE; int have_some_real_data=FALSE; hoststatus *hststatus=NULL; servicestatus *svcstatus=NULL; unsigned long wobble=300; int first_real_state=AS_NO_DATA; int initial_assumed_state=AS_NO_DATA; time_t initial_assumed_time; time(¤t_time); /* if left hand of graph is after current time, we can't do anything at all.... */ if(t1>current_time) return; /* check to see if we have any real data whatsoever... */ for(temp_as=as_list;temp_as!=NULL;temp_as=temp_as->next){ if(temp_as->entry_type!=AS_NO_DATA && temp_as->entry_type!=AS_PROGRAM_START && temp_as->entry_type!=AS_PROGRAM_END){ have_some_real_data=TRUE; first_real_state=temp_as->entry_type; break; } } /* if we don't have any data, assume current state (if possible) */ if(have_some_real_data==FALSE){ /* current time DOES NOT fall within graph bounds, so we can't do anything */ /* the "wobble" value is necessary because when the CGI is called to do the PNG generation, t2 will actually be less that current_time by a bit */ if(current_time(t2+wobble)) return; if(display_type==DISPLAY_HOST_TRENDS) last_known_state=AS_HOST_UP; else last_known_state=AS_SVC_OK; /* we don't have any historical information, but the current time falls within the reporting period, so use */ /* the current status of the host/service as the starting data */ if(display_type==DISPLAY_HOST_TRENDS){ hststatus=find_hoststatus(host_name); if(hststatus!=NULL){ if(hststatus->status==HOST_DOWN) last_known_state=AS_HOST_DOWN; else if(hststatus->status==HOST_UNREACHABLE) last_known_state=AS_HOST_UNREACHABLE; else last_known_state=AS_HOST_UP; } /* add a dummy archived state item, so something can get graphed */ add_archived_state(last_known_state,t1,"Current Host State (Assumed)"); } else{ svcstatus=find_servicestatus(host_name,svc_description); if(svcstatus!=NULL){ if(svcstatus->status==SERVICE_OK || svcstatus->status==SERVICE_RECOVERY) last_known_state=AS_SVC_OK; else if(svcstatus->status==SERVICE_WARNING) last_known_state=AS_SVC_WARNING; else if(svcstatus->status==SERVICE_CRITICAL || svcstatus->status==SERVICE_HOST_DOWN || svcstatus->status==SERVICE_UNREACHABLE) last_known_state=AS_SVC_CRITICAL; else if(svcstatus->status==SERVICE_UNKNOWN) last_known_state=AS_SVC_UNKNOWN; } /* add a dummy archived state item, so something can get graphed */ add_archived_state(last_known_state,t1,"Current Service State (Assumed)"); } } /* we do have some real data, so insert initial (assumed) state if we can */ else if(assume_initial_states==TRUE){ /* we're assuming the initial state is either OK or UP (for services or hosts) */ if(assume_initial_state_ok==TRUE){ if(display_type==DISPLAY_HOST_TRENDS) initial_assumed_state=AS_HOST_UP; else initial_assumed_state=AS_SVC_OK; } /* else use the first 'real' state we encountered as the initial state to use */ else initial_assumed_state=first_real_state; /* add this assumed state entry before any entries in the list and <= t1 */ if(as_list->time_stamp>t1) initial_assumed_time=t1; else initial_assumed_time=as_list->time_stamp-1; if(display_type==DISPLAY_HOST_TRENDS) add_archived_state(initial_assumed_state,initial_assumed_time,"Assumed Initial Host State"); else add_archived_state(initial_assumed_state,initial_assumed_time,"Assumed Initial Service State"); } /* if we're creating the HTML, start map code... */ if(mode==CREATE_HTML) printf("\n"); last_as=NULL; earliest_time=t2; latest_time=t1; /**********************************/ /* BEGINNING/MIDDLE SECTION */ /**********************************/ for(temp_as=as_list;temp_as!=NULL;temp_as=temp_as->next){ if(last_as!=NULL){ a=last_as->time_stamp; b=temp_as->time_stamp; /* we've already passed the last time displayed in the graph */ if(a>t2) break; /* only graph this data if its on the graph */ if(b>t1){ /* clip last time if it exceeds graph limits */ if(b>t2) b=t2; /* clip first time if it preceeds graph limits */ if(aentry_type; } /* save this time if its the latest we've graphed */ if(b>latest_time){ latest_time=b; latest_state=last_as->entry_type; } /* graph the state */ graph_trend_data(last_as->entry_type,temp_as->entry_type,last_as->time_stamp,a,b,last_as->state_info); /* return if we've reached the end of the graph limits */ if(b>=t2) break; } /* else we're still before the first time on the graph, but keep this as the last know state (if possible) */ else if(b<=t1){ if(temp_as->entry_type!=AS_NO_DATA && temp_as->entry_type!=AS_PROGRAM_END && temp_as->entry_type!=AS_PROGRAM_START) last_known_state=temp_as->entry_type; } } last_as=temp_as; /* special case for first entry in list */ if(temp_as==as_list){ if(temp_as->entry_type!=AS_NO_DATA && temp_as->entry_type!=AS_PROGRAM_END && temp_as->entry_type!=AS_PROGRAM_START) last_known_state=temp_as->entry_type; } } #ifdef DEBUG printf("GRAPHING END!\n"); #endif /**********************************/ /* END SECTION */ /**********************************/ if(as_list!=NULL){ time(¤t_time); b=current_time; if(b>t2) b=t2; /* fake the current state (it doesn't really matter for graphing) */ if(display_type==DISPLAY_HOST_INFO) current_state=AS_HOST_UP; else current_state=AS_SVC_OK; /***** SPECIAL CASE - THERE WAS ONLY ONE ENTRY IN THE LIST *****/ if(latest_time<=t1){ graph_trend_data(as_list->entry_type,current_state,as_list->time_stamp,as_list->time_stamp,b,as_list->state_info); } /***** NORMAL CASE - THERE WERE TWO OR MORE ENTRIES IN THE LIST *****/ else{ /* the timestamp on the last data point has to be within the graph bounds */ if(latest_time < b){ graph_trend_data(last_as->entry_type,current_state,latest_time,latest_time,b,last_as->state_info); } } } /* if we're creating the HTML, close the map code */ if(mode==CREATE_HTML) printf("\n"); return; } /* graphs trend data */ void graph_trend_data(int first_state,int last_state,time_t real_start_time,time_t start_time,time_t end_time,char *state_info){ int start_state; int end_state; int start_pixel=0; int end_pixel=0; int color_to_use=0; int height=0; double start_pixel_ratio; double end_pixel_ratio; char temp_buffer[MAX_INPUT_BUFFER]; char state_string[MAX_INPUT_BUFFER]; char end_timestring[MAX_INPUT_BUFFER]; char start_timestring[MAX_INPUT_BUFFER]; time_t center_time; time_t next_start_time; time_t next_end_time; int days=0; int hours=0; int minutes=0; int seconds=0; /* can't graph if we don't have data... */ if(first_state==AS_NO_DATA || last_state==AS_NO_DATA) return; if(first_state==AS_PROGRAM_START && (last_state==AS_PROGRAM_END || last_state==AS_PROGRAM_START)){ if(assume_initial_states==FALSE) return; } if(first_state==AS_PROGRAM_END) return; /* special case if first entry was program start */ if(first_state==AS_PROGRAM_START){ #ifdef DEBUG printf("First state=program start!\n"); #endif if(assume_initial_states==TRUE){ #ifdef DEBUG printf("\tWe are assuming initial states...\n"); #endif if(assume_state_retention==TRUE){ start_state=last_known_state; #ifdef DEBUG printf("\tWe are assuming state retention (%d)...\n",start_state); #endif } else{ #ifdef DEBUG printf("\tWe are NOT assuming state retention...\n"); #endif if(display_type==DISPLAY_HOST_TRENDS) start_state=AS_HOST_UP; else start_state=AS_SVC_OK; } } else{ #ifdef DEBUG printf("We ARE NOT assuming initial states!\n"); #endif return; } } else{ start_state=first_state; last_known_state=first_state; } /* special case if last entry was program stop */ if(last_state==AS_PROGRAM_END) end_state=first_state; else end_state=last_state; #ifdef DEBUG printf("Graphing state %d\n",start_state); printf("\tfrom %s",ctime(&start_time)); printf("\tto %s",ctime(&end_time)); #endif if(start_timet2) end_time=t2; if(end_timet2) return; /* calculate the first and last pixels to use */ if(start_time==t1) start_pixel=0; else{ start_pixel_ratio=((double)(start_time-t1))/((double)(t2-t1)); start_pixel=(int)(start_pixel_ratio*(drawing_width-1)); } if(end_time==t1) end_pixel=0; else{ end_pixel_ratio=((double)(end_time-t1))/((double)(t2-t1)); end_pixel=(int)(end_pixel_ratio*(drawing_width-1)); } #ifdef DEBUG printf("\tPixel %d to %d\n\n",start_pixel,end_pixel); #endif /* we're creating the image, so draw... */ if(mode==CREATE_IMAGE){ /* figure out the color to use for drawing */ switch(start_state){ case AS_HOST_UP: color_to_use=color_green; height=60; break; case AS_HOST_DOWN: color_to_use=color_red; height=40; break; case AS_HOST_UNREACHABLE: color_to_use=color_darkred; height=20; break; case AS_SVC_OK: color_to_use=color_green; height=80; break; case AS_SVC_WARNING: color_to_use=color_yellow; height=60; break; case AS_SVC_UNKNOWN: color_to_use=color_orange; height=40; break; case AS_SVC_CRITICAL: color_to_use=color_red; height=20; break; default: color_to_use=color_black; height=5; break; } /* draw a rectangle */ gdImageFilledRectangle(trends_image,start_pixel+drawing_x_offset,drawing_height-height+drawing_y_offset,end_pixel+drawing_x_offset,drawing_height+drawing_y_offset,color_to_use); } /* else we're creating the HTML, so write map area code... */ else{ /* figure out the the state string to use */ switch(start_state){ case AS_HOST_UP: strcpy(state_string,"UP"); height=60; break; case AS_HOST_DOWN: strcpy(state_string,"DOWN"); height=40; break; case AS_HOST_UNREACHABLE: strcpy(state_string,"UNREACHABLE"); height=20; break; case AS_SVC_OK: strcpy(state_string,"OK"); height=80; break; case AS_SVC_WARNING: strcpy(state_string,"WARNING"); height=60; break; case AS_SVC_UNKNOWN: strcpy(state_string,"UNKNOWN"); height=40; break; case AS_SVC_CRITICAL: strcpy(state_string,"CRITICAL"); height=20; break; default: strcpy(state_string,"?"); height=5; break; } /* get the center of this time range */ center_time=start_time+((start_time-end_time)/2); /* determine next start and end time range with zoom factor */ if(zoom_factor>0){ next_start_time=center_time-(((t2-t1)/2)/zoom_factor); next_end_time=center_time+(((t2-t1)/2)/zoom_factor); } else{ next_start_time=center_time+(((t2-t1)/2)*zoom_factor); next_end_time=center_time-(((t2-t1)/2)*zoom_factor); } printf("\n"); } /* calculate time in this state */ switch(start_state){ case AS_HOST_UP: time_up+=(unsigned long)(end_time-start_time); break; case AS_HOST_DOWN: time_down+=(unsigned long)(end_time-start_time); break; case AS_HOST_UNREACHABLE: time_unreachable+=(unsigned long)(end_time-start_time); break; case AS_SVC_OK: time_ok+=(unsigned long)(end_time-start_time); break; case AS_SVC_WARNING: time_warning+=(unsigned long)(end_time-start_time); break; case AS_SVC_UNKNOWN: time_unknown+=(unsigned long)(end_time-start_time); break; case AS_SVC_CRITICAL: time_critical+=(unsigned long)(end_time-start_time); break; default: break; } return; } /* convert current host state to archived state value */ int convert_host_state_to_archived_state(int current_status){ if(current_status==HOST_UP) return AS_HOST_UP; if(current_status==HOST_DOWN) return AS_HOST_DOWN; if(current_status==HOST_UNREACHABLE) return AS_HOST_UNREACHABLE; return AS_NO_DATA; } /* convert current service state to archived state value */ int convert_service_state_to_archived_state(int current_status){ if(current_status==SERVICE_OK) return AS_SVC_OK; if(current_status==SERVICE_UNKNOWN) return AS_SVC_UNKNOWN; if(current_status==SERVICE_WARNING) return AS_SVC_WARNING; if(current_status==SERVICE_CRITICAL) return AS_SVC_CRITICAL; return AS_NO_DATA; } /* adds an archived state entry */ void add_archived_state(int state_type, time_t time_stamp, char *state_info){ archived_state *last_as=NULL; archived_state *temp_as=NULL; archived_state *new_as=NULL; #ifdef DEBUG printf("Added state %d @ %s",state_type,ctime(&time_stamp)); #endif /* allocate memory for the new entry */ new_as=(archived_state *)malloc(sizeof(archived_state)); if(new_as==NULL) return; /* allocate memory fo the state info */ if(state_info!=NULL){ new_as->state_info=(char *)malloc(strlen(state_info)+1); if(new_as->state_info!=NULL) strcpy(new_as->state_info,state_info); } else new_as->state_info=NULL; new_as->entry_type=state_type; new_as->time_stamp=time_stamp; /* add the new entry to the list in memory, sorted by time */ last_as=as_list; for(temp_as=as_list;temp_as!=NULL;temp_as=temp_as->next){ if(new_as->time_stamptime_stamp){ new_as->next=temp_as; if(temp_as==as_list) as_list=new_as; else last_as->next=new_as; break; } else last_as=temp_as; } if(as_list==NULL){ new_as->next=NULL; as_list=new_as; } else if(temp_as==NULL){ new_as->next=NULL; last_as->next=new_as; } return; } /* frees memory allocated to the archived state list */ void free_archived_state_list(void){ archived_state *this_as=NULL; archived_state *next_as=NULL; for(this_as=as_list;this_as!=NULL;){ next_as=this_as->next; if(this_as->state_info!=NULL) free(this_as->state_info); free(this_as); this_as=next_as; } as_list=NULL; return; } /* reads log files for archived state data */ void read_archived_state_data(void){ char filename[MAX_FILENAME_LENGTH]; int newest_archive=0; int oldest_archive=0; int current_archive; #ifdef DEBUG printf("Determining archives to use...\n"); #endif /* determine earliest archive to use */ oldest_archive=determine_archive_to_use_from_time(t1); if(log_rotation_method!=LOG_ROTATION_NONE) oldest_archive+=backtrack_archives; /* determine most recent archive to use */ newest_archive=determine_archive_to_use_from_time(t2); if(oldest_archive\n"); printf("\n"); printf("\n"); return; } /* write timestamps */ void draw_timestamps(void){ int last_timestamp=0; archived_state *temp_as; double start_pixel_ratio; int start_pixel; if(mode!=CREATE_IMAGE) return; /* draw first timestamp */ draw_timestamp(0,t1); last_timestamp=0; for(temp_as=as_list;temp_as!=NULL;temp_as=temp_as->next){ if(temp_as->time_stamptime_stamp>t2) continue; start_pixel_ratio=((double)(temp_as->time_stamp-t1))/((double)(t2-t1)); start_pixel=(int)(start_pixel_ratio*(drawing_width-1)); /* draw start timestamp if possible */ if((start_pixel > last_timestamp+MIN_TIMESTAMP_SPACING) && (start_pixel < drawing_width-1-MIN_TIMESTAMP_SPACING)){ draw_timestamp(start_pixel,temp_as->time_stamp); last_timestamp=start_pixel; } } /* draw last timestamp */ draw_timestamp(drawing_width-1,t2); return; } /* write timestamp below graph */ void draw_timestamp(int ts_pixel, time_t ts_time){ char temp_buffer[MAX_INPUT_BUFFER]; int string_height; int string_width; snprintf(temp_buffer,sizeof(temp_buffer)-1,"%s",ctime(&ts_time)); temp_buffer[sizeof(temp_buffer)-1]='\x0'; temp_buffer[strlen(temp_buffer)-1]='\x0'; string_height=gdFontSmall->h; string_width=gdFontSmall->w*strlen(temp_buffer); gdImageStringUp(trends_image,gdFontSmall,ts_pixel+drawing_x_offset-(string_height/2),drawing_y_offset+drawing_height+string_width+5,(unsigned char *)temp_buffer,color_black); /* draw a dashed vertical line at this point */ if(ts_pixel>0 && ts_pixel<(drawing_width-1)) draw_dashed_line(ts_pixel+drawing_x_offset,drawing_y_offset,ts_pixel+drawing_x_offset,drawing_y_offset+drawing_height,color_black); return; } /* draw total state times */ void draw_time_breakdowns(void){ char temp_buffer[MAX_INPUT_BUFFER]; unsigned long total_time=0L; unsigned long total_state_time; unsigned long time_indeterminate=0L; int string_height; if(mode==CREATE_HTML) return; total_time=(unsigned long)(t2-t1); if(display_type==DISPLAY_HOST_TRENDS) total_state_time=time_up+time_down+time_unreachable; else total_state_time=time_ok+time_warning+time_unknown+time_critical; if(total_state_time>=total_time) time_indeterminate=0L; else time_indeterminate=total_time-total_state_time; string_height=gdFontSmall->h; if(display_type==DISPLAY_HOST_TRENDS){ get_time_breakdown_string(total_time,time_up,"Up",&temp_buffer[0],sizeof(temp_buffer)); gdImageString(trends_image,gdFontSmall,drawing_x_offset+drawing_width+20,drawing_y_offset+5,(unsigned char *)temp_buffer,color_green); gdImageString(trends_image,gdFontSmall,drawing_x_offset-10-(gdFontSmall->w*2),drawing_y_offset+5,"Up",color_green); get_time_breakdown_string(total_time,time_down,"Down",&temp_buffer[0],sizeof(temp_buffer)); gdImageString(trends_image,gdFontSmall,drawing_x_offset+drawing_width+20,drawing_y_offset+25,(unsigned char *)temp_buffer,color_red); gdImageString(trends_image,gdFontSmall,drawing_x_offset-10-(gdFontSmall->w*4),drawing_y_offset+25,"Down",color_red); get_time_breakdown_string(total_time,time_unreachable,"Unreachable",&temp_buffer[0],sizeof(temp_buffer)); gdImageString(trends_image,gdFontSmall,drawing_x_offset+drawing_width+20,drawing_y_offset+45,(unsigned char *)temp_buffer,color_darkred); gdImageString(trends_image,gdFontSmall,drawing_x_offset-10-(gdFontSmall->w*11),drawing_y_offset+45,"Unreachable",color_darkred); get_time_breakdown_string(total_time,time_indeterminate,"Indeterminate",&temp_buffer[0],sizeof(temp_buffer)); gdImageString(trends_image,gdFontSmall,drawing_x_offset+drawing_width+20,drawing_y_offset+65,(unsigned char *)temp_buffer,color_black); gdImageString(trends_image,gdFontSmall,drawing_x_offset-10-(gdFontSmall->w*13),drawing_y_offset+65,"Indeterminate",color_black); } else{ get_time_breakdown_string(total_time,time_ok,"Ok",&temp_buffer[0],sizeof(temp_buffer)); gdImageString(trends_image,gdFontSmall,drawing_x_offset+drawing_width+20,drawing_y_offset+5,(unsigned char *)temp_buffer,color_green); gdImageString(trends_image,gdFontSmall,drawing_x_offset-10-(gdFontSmall->w*2),drawing_y_offset+5,"Ok",color_green); get_time_breakdown_string(total_time,time_warning,"Warning",&temp_buffer[0],sizeof(temp_buffer)); gdImageString(trends_image,gdFontSmall,drawing_x_offset+drawing_width+20,drawing_y_offset+25,(unsigned char *)temp_buffer,color_yellow); gdImageString(trends_image,gdFontSmall,drawing_x_offset-10-(gdFontSmall->w*7),drawing_y_offset+25,"Warning",color_yellow); get_time_breakdown_string(total_time,time_unknown,"Unknown",&temp_buffer[0],sizeof(temp_buffer)); gdImageString(trends_image,gdFontSmall,drawing_x_offset+drawing_width+20,drawing_y_offset+45,(unsigned char *)temp_buffer,color_orange); gdImageString(trends_image,gdFontSmall,drawing_x_offset-10-(gdFontSmall->w*7),drawing_y_offset+45,"Unknown",color_orange); get_time_breakdown_string(total_time,time_critical,"Critical",&temp_buffer[0],sizeof(temp_buffer)); gdImageString(trends_image,gdFontSmall,drawing_x_offset+drawing_width+20,drawing_y_offset+65,(unsigned char *)temp_buffer,color_red); gdImageString(trends_image,gdFontSmall,drawing_x_offset-10-(gdFontSmall->w*8),drawing_y_offset+65,"Critical",color_red); get_time_breakdown_string(total_time,time_indeterminate,"Indeterminate",&temp_buffer[0],sizeof(temp_buffer)); gdImageString(trends_image,gdFontSmall,drawing_x_offset+drawing_width+20,drawing_y_offset+85,(unsigned char *)temp_buffer,color_black); gdImageString(trends_image,gdFontSmall,drawing_x_offset-10-(gdFontSmall->w*13),drawing_y_offset+85,"Indeterminate",color_black); } return; } void get_time_breakdown_string(unsigned long total_time, unsigned long state_time, char *state_string, char *buffer, int buffer_length){ int days; int hours; int minutes; int seconds; double percent_time; get_time_breakdown(state_time,&days,&hours,&minutes,&seconds); if(total_time==0L) percent_time=0.0; else percent_time=((double)state_time/total_time)*100.0; snprintf(buffer,buffer_length-1,"%-13s: (%3.1f%%) %dd %dh %dm %ds",state_string,percent_time,days,hours,minutes,seconds); buffer[buffer_length-1]='\x0'; return; } void convert_timeperiod_to_times(int type){ time_t current_time; struct tm *t; /* get the current time */ time(¤t_time); t=localtime(¤t_time); t->tm_sec=0; t->tm_min=0; t->tm_hour=0; switch(type){ case TIMEPERIOD_LAST24HOURS: t1=current_time-(60*60*24); t2=current_time; break; case TIMEPERIOD_TODAY: t1=mktime(t); t2=current_time; break; case TIMEPERIOD_YESTERDAY: t1=(time_t)(mktime(t)-(60*60*24)); t2=(time_t)mktime(t); break; case TIMEPERIOD_THISWEEK: t1=(time_t)(mktime(t)-(60*60*24*t->tm_wday)); t2=current_time; break; case TIMEPERIOD_LASTWEEK: t1=(time_t)(mktime(t)-(60*60*24*t->tm_wday)-(60*60*24*7)); t2=(time_t)(mktime(t)-(60*60*24*t->tm_wday)); break; case TIMEPERIOD_THISMONTH: t->tm_mday=1; t1=mktime(t); t2=current_time; break; case TIMEPERIOD_LASTMONTH: t->tm_mday=1; t2=mktime(t); if(t->tm_mon==0){ t->tm_mon=11; t->tm_year--; } else t->tm_mon--; t1=mktime(t); break; case TIMEPERIOD_THISQUARTER: break; case TIMEPERIOD_LASTQUARTER: break; case TIMEPERIOD_THISYEAR: t->tm_mon=0; t->tm_mday=1; t1=mktime(t); t2=current_time; break; case TIMEPERIOD_LASTYEAR: t->tm_mon=0; t->tm_mday=1; t2=mktime(t); t->tm_year--; t1=mktime(t); break; case TIMEPERIOD_LAST7DAYS: t2=current_time; t1=current_time-(7*24*60*60); break; default: break; } return; } /* draws a dashed line */ void draw_dashed_line(int x1,int y1,int x2,int y2,int color){ int styleDashed[12]; styleDashed[0]=color; styleDashed[1]=color; styleDashed[2]=gdTransparent; styleDashed[3]=gdTransparent; styleDashed[4]=color; styleDashed[5]=color; styleDashed[6]=gdTransparent; styleDashed[7]=gdTransparent; styleDashed[8]=color; styleDashed[9]=color; styleDashed[10]=gdTransparent; styleDashed[11]=gdTransparent; /* sets current style to a dashed line */ gdImageSetStyle(trends_image,styleDashed,12); /* draws a line (dashed) */ gdImageLine(trends_image,x1,y1,x2,y2,gdStyled); return; } /* draws horizontal grid lines */ void draw_horizontal_grid_lines(void){ if(mode==CREATE_HTML) return; draw_dashed_line(drawing_x_offset,drawing_y_offset+10,drawing_x_offset+drawing_width,drawing_y_offset+10,color_black); draw_dashed_line(drawing_x_offset,drawing_y_offset+30,drawing_x_offset+drawing_width,drawing_y_offset+30,color_black); draw_dashed_line(drawing_x_offset,drawing_y_offset+50,drawing_x_offset+drawing_width,drawing_y_offset+50,color_black); if(display_type==DISPLAY_SERVICE_TRENDS) draw_dashed_line(drawing_x_offset,drawing_y_offset+70,drawing_x_offset+drawing_width,drawing_y_offset+70,color_black); return; }