/***************************************************************************** * * STATUSMAP.C - Nagios Network Status Map CGI * * Copyright (c) 1999-2004 Ethan Galstad (nagios@nagios.org) * Last Modified: 01-19-2004 * * Description: * * This CGI will create a map of all hosts that are being monitored on your * network. * * 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/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 */ extern int refresh_rate; /*#define DEBUG*/ #define UNKNOWN_GD2_ICON "unknown.gd2" #define UNKNOWN_ICON_IMAGE "unknown.gif" #define NAGIOS_GD2_ICON "nagios.gd2" extern char main_config_file[MAX_FILENAME_LENGTH]; extern char physical_images_path[MAX_FILENAME_LENGTH]; extern char url_images_path[MAX_FILENAME_LENGTH]; extern char url_logo_images_path[MAX_FILENAME_LENGTH]; extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; extern hostgroup *hostgroup_list; extern hoststatus *hoststatus_list; extern host *host_list; extern servicestatus *servicestatus_list; extern service *service_list; extern char *statusmap_background_image; extern int default_statusmap_layout_method; #define DEFAULT_NODE_WIDTH 40 #define DEFAULT_NODE_HEIGHT 65 #define DEFAULT_NODE_VSPACING 15 #define DEFAULT_NODE_HSPACING 45 #define DEFAULT_PROXIMITY_WIDTH 1000 #define DEFAULT_PROXIMITY_HEIGHT 800 #define MINIMUM_PROXIMITY_WIDTH 250 #define MINIMUM_PROXIMITY_HEIGHT 200 #define COORDS_WARNING_WIDTH 650 #define COORDS_WARNING_HEIGHT 60 #define CIRCULAR_DRAWING_RADIUS 100 #define CREATE_HTML 0 #define CREATE_IMAGE 1 #define LAYOUT_USER_SUPPLIED 0 #define LAYOUT_SUBLAYERS 1 #define LAYOUT_COLLAPSED_TREE 2 #define LAYOUT_BALANCED_TREE 3 #define LAYOUT_CIRCULAR 4 #define LAYOUT_CIRCULAR_MARKUP 5 #define LAYOUT_CIRCULAR_BALLOON 6 typedef struct layer_struct{ char *layer_name; struct layer_struct *next; }layer; void document_header(int); void document_footer(void); int process_cgivars(void); void display_page_header(void); void display_map(void); void calculate_host_coords(void); void calculate_total_image_bounds(void); void calculate_canvas_bounds(void); void calculate_canvas_bounds_from_host(char *); void calculate_scaling_factor(void); void find_eligible_hosts(void); void load_background_image(void); void draw_background_image(void); void draw_background_extras(void); void draw_host_links(void); void draw_hosts(void); void draw_host_text(char *,int,int); void draw_text(char *,int,int,int); void write_popup_code(void); void write_host_popup_text(host *); int initialize_graphics(void); gdImagePtr load_image_from_file(char *); void write_graphics(void); void cleanup_graphics(void); void draw_line_extended(int,int,int,int,int); void draw_line(int,int,int,int,int); void draw_dotted_line(int,int,int,int,int); void draw_dashed_line(int,int,int,int,int); int is_host_in_layer_list(host *); int add_layer(char *); void free_layer_list(void); void print_layer_url(int); int number_of_host_layer_members(host *,int); int max_child_host_layer_members(host *); int host_child_depth_separation(host *, host *); int max_child_host_drawing_width(host *); int number_of_host_services(host *); void calculate_balanced_tree_coords(host *,int,int); void calculate_circular_coords(void); void calculate_circular_layer_coords(host *,double,double,int,int); void draw_circular_markup(void); void draw_circular_layer_markup(host *,double,double,int,int); char physical_logo_images_path[MAX_FILENAME_LENGTH]; authdata current_authdata; int create_type=CREATE_HTML; gdImagePtr unknown_logo_image=NULL; gdImagePtr logo_image=NULL; gdImagePtr map_image=NULL; gdImagePtr background_image=NULL; int color_white=0; int color_black=0; int color_red=0; int color_lightred=0; int color_green=0; int color_lightgreen=0; int color_blue=0; int color_yellow=0; int color_orange=0; int color_grey=0; int color_lightgrey=0; int show_all_hosts=TRUE; char *host_name="all"; int embedded=FALSE; int display_header=TRUE; int display_popups=TRUE; int use_links=TRUE; int use_text=TRUE; int use_highlights=TRUE; int user_supplied_canvas=FALSE; int user_supplied_scaling=FALSE; int layout_method=LAYOUT_USER_SUPPLIED; int proximity_width=DEFAULT_PROXIMITY_WIDTH; int proximity_height=DEFAULT_PROXIMITY_HEIGHT; int coordinates_were_specified=FALSE; /* were any coordinates specified in extended host information entries? */ int scaled_image_width=0; /* size of the image actually displayed on the screen (after scaling) */ int scaled_image_height=0; int canvas_width=0; /* actual size of the image (or portion thereof) that we are drawing */ int canvas_height=0; int total_image_width=0; /* actual size of the image that would be created if we drew all hosts */ int total_image_height=0; int max_image_width=0; /* max image size the user wants (scaled) */ int max_image_height=0; double scaling_factor=1.0; /* scaling factor to use */ double user_scaling_factor=1.0; /* user-supplied scaling factor */ int background_image_width=0; int background_image_height=0; int canvas_x=0; /* upper left coords of drawing canvas */ int canvas_y=0; int bottom_margin=0; int draw_child_links=FALSE; int draw_parent_links=FALSE; int draw_nagios_icon=FALSE; /* should we drawn the Nagios process icon? */ int nagios_icon_x=0; /* coords of Nagios icon */ int nagios_icon_y=0; extern hostextinfo *hostextinfo_list; extern host *host_list; extern hoststatus *hoststatus_list; extern time_t program_start; layer *layer_list=NULL; int exclude_layers=TRUE; int all_layers=FALSE; int main(int argc, char **argv){ int result; /* reset internal variables */ reset_cgi_vars(); /* read the CGI configuration file */ result=read_cgi_config_file(DEFAULT_CGI_CONFIG_FILE); if(result==ERROR){ document_header(FALSE); if(create_type==CREATE_HTML) cgi_config_file_error(DEFAULT_CGI_CONFIG_FILE); document_footer(); return ERROR; } /* defaults from CGI config file */ layout_method=default_statusmap_layout_method; /* get the arguments passed in the URL */ process_cgivars(); /* read the main configuration file */ result=read_main_config_file(main_config_file); if(result==ERROR){ document_header(FALSE); if(create_type==CREATE_HTML) main_config_file_error(main_config_file); document_footer(); return ERROR; } /* read all object configuration data */ result=read_all_object_configuration_data(main_config_file,READ_ALL_OBJECT_DATA); if(result==ERROR){ document_header(FALSE); if(create_type==CREATE_HTML) object_data_error(); document_footer(); return ERROR; } /* read all status data */ result=read_all_status_data(DEFAULT_CGI_CONFIG_FILE,READ_ALL_STATUS_DATA); if(result==ERROR){ document_header(FALSE); if(create_type==CREATE_HTML) status_data_error(); document_footer(); free_memory(); return ERROR; } document_header(TRUE); /* get authentication information */ get_authentication_information(¤t_authdata); /* read in extended host information */ read_extended_object_config_data(DEFAULT_CGI_CONFIG_FILE,READ_EXTENDED_HOST_INFO); /* display the network map... */ display_map(); document_footer(); /* free all allocated memory */ free_memory(); free_extended_data(); free_layer_list(); return OK; } void document_header(int use_stylesheet){ char date_time[MAX_DATETIME_LENGTH]; time_t current_time; time_t expire_time; if(create_type==CREATE_HTML){ printf("Cache-Control: no-store\n"); printf("Pragma: no-cache\n"); printf("Refresh: %d\n",refresh_rate); 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=0L; 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("Network Map\n"); printf("\n"); if(use_stylesheet==TRUE) printf("\n",url_stylesheets_path,STATUSMAP_CSS); /* write JavaScript code for popup window */ write_popup_code(); printf("\n"); printf("\n"); /* include user SSI header */ include_ssi_files(STATUSMAP_CGI,SSI_HEADER); 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(create_type==CREATE_HTML){ /* include user SSI footer */ include_ssi_files(STATUSMAP_CGI,SSI_FOOTER); 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="all"; else strcpy(host_name,variables[x]); if(!strcmp(host_name,"all")) show_all_hosts=TRUE; else show_all_hosts=FALSE; } /* we found the image creation option */ else if(!strcmp(variables[x],"createimage")){ create_type=CREATE_IMAGE; } /* 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 canvas origin */ else if(!strcmp(variables[x],"canvas_x")){ x++; if(variables[x]==NULL){ error=TRUE; break; } canvas_x=atoi(variables[x]); user_supplied_canvas=TRUE; } else if(!strcmp(variables[x],"canvas_y")){ x++; if(variables[x]==NULL){ error=TRUE; break; } canvas_y=atoi(variables[x]); user_supplied_canvas=TRUE; } /* we found the canvas size */ else if(!strcmp(variables[x],"canvas_width")){ x++; if(variables[x]==NULL){ error=TRUE; break; } canvas_width=atoi(variables[x]); user_supplied_canvas=TRUE; } else if(!strcmp(variables[x],"canvas_height")){ x++; if(variables[x]==NULL){ error=TRUE; break; } canvas_height=atoi(variables[x]); user_supplied_canvas=TRUE; } else if(!strcmp(variables[x],"proximity_width")){ x++; if(variables[x]==NULL){ error=TRUE; break; } proximity_width=atoi(variables[x]); if(proximity_width<0) proximity_width=DEFAULT_PROXIMITY_WIDTH; } else if(!strcmp(variables[x],"proximity_height")){ x++; if(variables[x]==NULL){ error=TRUE; break; } proximity_height=atoi(variables[x]); if(proximity_height<0) proximity_height=DEFAULT_PROXIMITY_HEIGHT; } /* we found the scaling factor */ else if(!strcmp(variables[x],"scaling_factor")){ x++; if(variables[x]==NULL){ error=TRUE; break; } user_scaling_factor=strtod(variables[x],NULL); if(user_scaling_factor>0.0) user_supplied_scaling=TRUE; } /* we found the max image size */ else if(!strcmp(variables[x],"max_width")){ x++; if(variables[x]==NULL){ error=TRUE; break; } max_image_width=atoi(variables[x]); } else if(!strcmp(variables[x],"max_height")){ x++; if(variables[x]==NULL){ error=TRUE; break; } max_image_height=atoi(variables[x]); } /* we found the layout method option */ else if(!strcmp(variables[x],"layout")){ x++; if(variables[x]==NULL){ error=TRUE; break; } layout_method=atoi(variables[x]); } /* we found the no links argument*/ else if(!strcmp(variables[x],"nolinks")) use_links=FALSE; /* we found the no text argument*/ else if(!strcmp(variables[x],"notext")) use_text=FALSE; /* we found the no highlights argument*/ else if(!strcmp(variables[x],"nohighlights")) use_highlights=FALSE; /* we found the no popups argument*/ else if(!strcmp(variables[x],"nopopups")) display_popups=FALSE; /* we found the layer inclusion/exclusion argument */ else if(!strcmp(variables[x],"layermode")){ x++; if(variables[x]==NULL){ error=TRUE; break; } if(!strcmp(variables[x],"include")) exclude_layers=FALSE; else exclude_layers=TRUE; } /* we found the layer argument */ else if(!strcmp(variables[x],"layer")){ x++; if(variables[x]==NULL){ error=TRUE; break; } add_layer(variables[x]); } } /* free memory allocated to the CGI variables */ free_cgivars(variables); return error; } /* top of page */ void display_page_header(void){ char temp_buffer[MAX_INPUT_BUFFER]; int zoom; int zoom_width, zoom_height; int zoom_width_granularity=0; int zoom_height_granularity=0; int current_zoom_granularity=0; hostgroup *temp_hostgroup; layer *temp_layer; int found=0; if(create_type!=CREATE_HTML) return; if(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(show_all_hosts==TRUE) snprintf(temp_buffer,sizeof(temp_buffer)-1,"Network Map For All Hosts"); else snprintf(temp_buffer,sizeof(temp_buffer)-1,"Network Map For Host %s",host_name); temp_buffer[sizeof(temp_buffer)-1]='\x0'; display_info_table(temp_buffer,TRUE,¤t_authdata); printf("\n"); printf("\n"); printf("\n"); printf("\n"); /* print image size and scaling info */ #ifdef DEBUG printf("

\n"); printf("[ Raw Image Size: %d x %d pixels | Scaling Factor: %1.2lf | Scaled Image Size: %d x %d pixels ]",canvas_width,canvas_height,scaling_factor,(int)(canvas_width*scaling_factor),(int)(canvas_height*scaling_factor)); printf("

\n"); printf("

\n"); printf("[ Canvas_x: %d | Canvas_y: %d | Canvas_width: %d | Canvas_height: %d ]",canvas_x,canvas_y,canvas_width,canvas_height); printf("

\n"); #endif /* zoom links */ if(user_supplied_canvas==FALSE && strcmp(host_name,"all") && display_header==TRUE){ printf("

\n"); zoom_width_granularity=((total_image_width-MINIMUM_PROXIMITY_WIDTH)/11); if(zoom_width_granularity==0) zoom_width_granularity=1; zoom_height_granularity=((total_image_height-MINIMUM_PROXIMITY_HEIGHT)/11); if(proximity_width<=0) current_zoom_granularity=0; else current_zoom_granularity=(total_image_width-proximity_width)/zoom_width_granularity; if(current_zoom_granularity>10) current_zoom_granularity=10; printf("\n"); printf("\n"); printf("\n"); for(zoom=0;zoom<=10;zoom++){ zoom_width=total_image_width-(zoom*zoom_width_granularity); zoom_height=total_image_height-(zoom*zoom_height_granularity); printf("\n",url_images_path,(current_zoom_granularity==zoom)?ZOOM2_ICON:ZOOM1_ICON,zoom); } printf("\n"); printf("\n"); printf("
Zoom Out  "); printf("%d  Zoom In
\n"); printf("

\n"); } printf("
\n"); printf("\n"); printf("\n"); printf("
\n"); printf("
\n",STATUSMAP_CGI); printf("\n",host_name); printf("\n",layout_method); printf("
\n"); printf("\n"); printf("\n"); printf("\n"); /* printf("\n"); printf("\n"); printf("\n"); printf("\n"); */ printf("\n",max_image_width); printf("\n",max_image_height); printf("\n",proximity_width); printf("\n",proximity_height); printf("\n"); printf("\n"); /* display context-sensitive help */ printf("\n"); printf("
\n"); printf("Layout Method:
\n"); printf("\n"); printf("
\n"); printf("Scaling factor:
\n"); printf("\n",(user_supplied_scaling==TRUE)?user_scaling_factor:0.0); printf("
\n"); printf("Max image width:
\n"); printf("\n",max_image_width); printf("
\n"); printf("Max image height:
\n"); printf("\n",max_image_height); printf("
\n"); printf("Proximity width:
\n"); printf("\n",proximity_width); printf("
\n"); printf("Proximity height:
\n"); printf("\n",proximity_height); printf("
Drawing Layers:
\n"); printf("\n"); printf("
Layer mode:
"); printf("Include
\n",(exclude_layers==FALSE)?"CHECKED":""); printf("Exclude\n",(exclude_layers==TRUE)?"CHECKED":""); printf("
\n"); printf("Supress popups:
\n"); printf("\n",(display_popups==FALSE)?"CHECKED":""); printf("
\n"); printf("\n"); printf("
\n"); display_context_help(CONTEXTHELP_MAP); printf("
\n"); printf("\n"); printf("
\n"); printf("
\n"); } return; } /* top-level map generation... */ void display_map(void){ load_background_image(); calculate_host_coords(); calculate_total_image_bounds(); calculate_canvas_bounds(); calculate_scaling_factor(); find_eligible_hosts(); /* display page header */ display_page_header(); initialize_graphics(); draw_background_image(); draw_background_extras(); draw_host_links(); if(create_type==CREATE_HTML) printf("\n"); draw_hosts(); if(create_type==CREATE_HTML) printf("\n"); write_graphics(); cleanup_graphics(); /* write the URL location for the image we just generated - the web browser will come and get it... */ if(create_type==CREATE_HTML){ printf("

\n"); printf("\n",(int)(canvas_width*scaling_factor),(int)(canvas_height*scaling_factor)); printf("

\n"); } return; } /******************************************************************/ /********************* CALCULATION FUNCTIONS **********************/ /******************************************************************/ /* calculates host drawing coordinates */ void calculate_host_coords(void){ hostextinfo *temp_hostextinfo; host *this_host; host *temp_host; int child_hosts=0; int parent_hosts=0; int max_layer_width=1; int current_child_host=0; int current_parent_host=0; int center_x=0; int offset_x=DEFAULT_NODE_WIDTH/2; int offset_y=DEFAULT_NODE_WIDTH/2; int current_layer=0; int layer_members=0; int current_layer_member=0; int max_drawing_width=0; int x=0; /******************************/ /***** MANUAL LAYOUT MODE *****/ /******************************/ /* user-supplied coords */ if(layout_method==LAYOUT_USER_SUPPLIED){ /* see which hosts we should draw and calculate drawing coords */ for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){ if(temp_hostextinfo->have_2d_coords==TRUE) temp_hostextinfo->should_be_drawn=TRUE; else temp_hostextinfo->should_be_drawn=FALSE; } return; } /*****************************/ /***** AUTO-LAYOUT MODES *****/ /*****************************/ /* add empty extended host info entries for all hosts that don't have any */ for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ /* find the corresponding hostextinfo definition */ temp_hostextinfo=find_hostextinfo(temp_host->name); /* none was found, so add a blank one */ if(temp_hostextinfo==NULL) add_extended_host_info(temp_host->name,NULL,NULL,NULL,NULL,NULL,0,0,0.0,0.0,0.0,0,0); } /***** DEPTH LAYER MODE *****/ if(layout_method==LAYOUT_SUBLAYERS){ /* find the "main" host we're displaying */ if(show_all_hosts==TRUE) this_host=NULL; else this_host=find_host(host_name,NULL); /* find total number of immediate parents/children for this host */ child_hosts=number_of_immediate_child_hosts(this_host); parent_hosts=number_of_immediate_parent_hosts(this_host); if(child_hosts==0 && parent_hosts==0) max_layer_width=1; else max_layer_width=(child_hosts>parent_hosts)?child_hosts:parent_hosts; /* calculate center x coord */ center_x=(((DEFAULT_NODE_WIDTH*max_layer_width)+(DEFAULT_NODE_HSPACING*(max_layer_width-1)))/2)+offset_x; /* coords for Nagios icon if necessary */ if(this_host==NULL || this_host->parent_hosts==NULL){ nagios_icon_x=center_x; nagios_icon_y=offset_y; draw_nagios_icon=TRUE; } /* do we need to draw a link to parent(s)? */ if(this_host!=NULL && is_host_immediate_child_of_host(NULL,this_host)==FALSE){ draw_parent_links=TRUE; offset_y+=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING; } /* see which hosts we should draw and calculate drawing coords */ for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){ /* find the host that matches this entry */ temp_host=find_host(temp_hostextinfo->host_name,NULL); if(temp_host==NULL) continue; /* this is an immediate parent of the "main" host we're drawing */ else if(is_host_immediate_parent_of_host(this_host,temp_host)==TRUE){ temp_hostextinfo->should_be_drawn=TRUE; temp_hostextinfo->have_2d_coords=TRUE; temp_hostextinfo->x_2d=center_x-(((parent_hosts*DEFAULT_NODE_WIDTH)+((parent_hosts-1)*DEFAULT_NODE_HSPACING))/2)+(current_parent_host*(DEFAULT_NODE_WIDTH+DEFAULT_NODE_HSPACING))+(DEFAULT_NODE_WIDTH/2); temp_hostextinfo->y_2d=offset_y; current_parent_host++; } /* this is the "main" host we're drawing */ else if(this_host==temp_host){ temp_hostextinfo->should_be_drawn=TRUE; temp_hostextinfo->have_2d_coords=TRUE; temp_hostextinfo->x_2d=center_x; temp_hostextinfo->y_2d=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y; } /* this is an immediate child of the "main" host we're drawing */ else if(is_host_immediate_child_of_host(this_host,temp_host)==TRUE){ temp_hostextinfo->should_be_drawn=TRUE; temp_hostextinfo->have_2d_coords=TRUE; temp_hostextinfo->x_2d=center_x-(((child_hosts*DEFAULT_NODE_WIDTH)+((child_hosts-1)*DEFAULT_NODE_HSPACING))/2)+(current_child_host*(DEFAULT_NODE_WIDTH+DEFAULT_NODE_HSPACING))+(DEFAULT_NODE_WIDTH/2); if(this_host==NULL) temp_hostextinfo->y_2d=(DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)+offset_y; else temp_hostextinfo->y_2d=((DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)*2)+offset_y; current_child_host++; if(number_of_immediate_child_hosts(temp_host)>0){ bottom_margin=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING; draw_child_links=TRUE; } } /* else do not draw this host */ else{ temp_hostextinfo->should_be_drawn=FALSE; temp_hostextinfo->have_2d_coords=FALSE; } } } /***** COLLAPSED TREE MODE *****/ else if(layout_method==LAYOUT_COLLAPSED_TREE){ /* find the "main" host we're displaying - DO NOT USE THIS (THIS IS THE OLD METHOD) */ /* if(show_all_hosts==TRUE) this_host=NULL; else this_host=find_host(host_name,NULL); */ /* always use NULL as the "main" host, screen coords/dimensions are adjusted automatically */ this_host=NULL; /* find total number of immediate parents for this host */ parent_hosts=number_of_immediate_parent_hosts(this_host); /* find the max layer width we have... */ max_layer_width=max_child_host_layer_members(this_host); if(parent_hosts>max_layer_width) max_layer_width=parent_hosts; /* calculate center x coord */ center_x=(((DEFAULT_NODE_WIDTH*max_layer_width)+(DEFAULT_NODE_HSPACING*(max_layer_width-1)))/2)+offset_x; /* coords for Nagios icon if necessary */ if(this_host==NULL || this_host->parent_hosts==NULL){ nagios_icon_x=center_x; nagios_icon_y=offset_y; draw_nagios_icon=TRUE; } /* do we need to draw a link to parent(s)? */ if(this_host!=NULL && is_host_immediate_child_of_host(NULL,this_host)==FALSE){ draw_parent_links=TRUE; offset_y+=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING; } /* see which hosts we should draw and calculate drawing coords */ for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){ /* find the host that matches this entry */ temp_host=find_host(temp_hostextinfo->host_name,NULL); if(temp_host==NULL) continue; /* this is an immediate parent of the "main" host we're drawing */ else if(is_host_immediate_parent_of_host(this_host,temp_host)==TRUE){ temp_hostextinfo->should_be_drawn=TRUE; temp_hostextinfo->have_2d_coords=TRUE; temp_hostextinfo->x_2d=center_x-(((parent_hosts*DEFAULT_NODE_WIDTH)+((parent_hosts-1)*DEFAULT_NODE_HSPACING))/2)+(current_parent_host*(DEFAULT_NODE_WIDTH+DEFAULT_NODE_HSPACING))+(DEFAULT_NODE_WIDTH/2); temp_hostextinfo->y_2d=offset_y; current_parent_host++; } /* this is the "main" host we're drawing */ else if(this_host==temp_host){ temp_hostextinfo->should_be_drawn=TRUE; temp_hostextinfo->have_2d_coords=TRUE; temp_hostextinfo->x_2d=center_x; temp_hostextinfo->y_2d=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y; } /* else do not draw this host (we might if its a child - see below, but assume no for now) */ else{ temp_hostextinfo->should_be_drawn=FALSE; temp_hostextinfo->have_2d_coords=FALSE; } } /* TODO: REORDER CHILD LAYER MEMBERS SO THAT WE MINIMIZE LINK CROSSOVERS FROM PARENT HOSTS */ /* draw hosts in child "layers" */ for(current_layer=1;;current_layer++){ /* how many members in this layer? */ layer_members=number_of_host_layer_members(this_host,current_layer); if(layer_members==0) break; current_layer_member=0; /* see which hosts are members of this layer and calculate drawing coords */ for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){ /* find the host that matches this entry */ temp_host=find_host(temp_hostextinfo->host_name,NULL); if(temp_host==NULL) continue; /* is this host a member of the current child layer? */ if(host_child_depth_separation(this_host,temp_host)==current_layer){ temp_hostextinfo->should_be_drawn=TRUE; temp_hostextinfo->have_2d_coords=TRUE; temp_hostextinfo->x_2d=center_x-(((layer_members*DEFAULT_NODE_WIDTH)+((layer_members-1)*DEFAULT_NODE_HSPACING))/2)+(current_layer_member*(DEFAULT_NODE_WIDTH+DEFAULT_NODE_HSPACING))+(DEFAULT_NODE_WIDTH/2); if(this_host==NULL) temp_hostextinfo->y_2d=((DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)*current_layer)+offset_y; else temp_hostextinfo->y_2d=((DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)*(current_layer+1))+offset_y; current_layer_member++; } } } } /***** "BALANCED" TREE MODE *****/ else if(layout_method==LAYOUT_BALANCED_TREE){ /* find the "main" host we're displaying - DO NOT USE THIS (THIS IS THE OLD METHOD) */ /* if(show_all_hosts==TRUE) this_host=NULL; else this_host=find_host(host_name,NULL); */ /* always use NULL as the "main" host, screen coords/dimensions are adjusted automatically */ this_host=NULL; /* find total number of immediate parents for this host */ parent_hosts=number_of_immediate_parent_hosts(this_host); /* find the max drawing width we have... */ max_drawing_width=max_child_host_drawing_width(this_host); if(parent_hosts>max_drawing_width) max_drawing_width=parent_hosts; /* calculate center x coord */ center_x=(((DEFAULT_NODE_WIDTH*max_drawing_width)+(DEFAULT_NODE_HSPACING*(max_drawing_width-1)))/2)+offset_x; /* coords for Nagios icon if necessary */ if(this_host==NULL || this_host->parent_hosts==NULL){ nagios_icon_x=center_x; nagios_icon_y=offset_y; draw_nagios_icon=TRUE; } /* do we need to draw a link to parent(s)? */ if(this_host!=NULL && is_host_immediate_child_of_host(NULL,this_host)==FALSE){ draw_parent_links=TRUE; offset_y+=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING; } /* see which hosts we should draw and calculate drawing coords */ for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){ /* find the host that matches this entry */ temp_host=find_host(temp_hostextinfo->host_name,NULL); if(temp_host==NULL) continue; /* this is an immediate parent of the "main" host we're drawing */ else if(is_host_immediate_parent_of_host(this_host,temp_host)==TRUE){ temp_hostextinfo->should_be_drawn=TRUE; temp_hostextinfo->have_2d_coords=TRUE; temp_hostextinfo->x_2d=center_x-(((parent_hosts*DEFAULT_NODE_WIDTH)+((parent_hosts-1)*DEFAULT_NODE_HSPACING))/2)+(current_parent_host*(DEFAULT_NODE_WIDTH+DEFAULT_NODE_HSPACING))+(DEFAULT_NODE_WIDTH/2); temp_hostextinfo->y_2d=offset_y; current_parent_host++; } /* this is the "main" host we're drawing */ else if(this_host==temp_host){ temp_hostextinfo->should_be_drawn=TRUE; temp_hostextinfo->have_2d_coords=TRUE; temp_hostextinfo->x_2d=center_x; temp_hostextinfo->y_2d=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y; } /* else do not draw this host (we might if its a child - see below, but assume no for now) */ else{ temp_hostextinfo->should_be_drawn=FALSE; temp_hostextinfo->have_2d_coords=FALSE; } } /* draw all children hosts */ calculate_balanced_tree_coords(this_host,center_x,DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y); } /***** CIRCULAR LAYOUT MODE *****/ else if(layout_method==LAYOUT_CIRCULAR || layout_method==LAYOUT_CIRCULAR_MARKUP || layout_method==LAYOUT_CIRCULAR_BALLOON){ /* draw process icon */ nagios_icon_x=0; nagios_icon_y=0; draw_nagios_icon=TRUE; /* calculate coordinates for all hosts */ calculate_circular_coords(); } return; } /* calculates max possible image dimensions */ void calculate_total_image_bounds(void){ hostextinfo *temp_hostextinfo; total_image_width=0; total_image_height=0; /* check all extended host information entries... */ for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){ /* only check entries that have 2-D coords specified */ if(temp_hostextinfo->have_2d_coords==FALSE) continue; /* skip hosts we shouldn't be drawing */ if(temp_hostextinfo->should_be_drawn==FALSE) continue; if(temp_hostextinfo->x_2d>total_image_width) total_image_width=temp_hostextinfo->x_2d; if(temp_hostextinfo->y_2d>total_image_height) total_image_height=temp_hostextinfo->y_2d; coordinates_were_specified=TRUE; } /* add some space for icon size and overlapping text... */ if(coordinates_were_specified==TRUE){ total_image_width+=(DEFAULT_NODE_WIDTH*2); total_image_height+=DEFAULT_NODE_HEIGHT; /* add space for bottom margin if necessary */ total_image_height+=bottom_margin; } /* image size should be at least as large as dimensions of background image */ if(total_image_widthtotal_image_width) canvas_x=0; if(canvas_y<=0 || canvas_height>total_image_height) canvas_y=0; /* calculate canvas dimensions */ if(canvas_height<=0) canvas_height=(total_image_height-canvas_y); if(canvas_width<=0) canvas_width=(total_image_width-canvas_x); if(canvas_x+canvas_width>total_image_width) canvas_width=total_image_width-canvas_x; if(canvas_y+canvas_height>total_image_height) canvas_height=total_image_height-canvas_y; return; } /* calculates canvas coordinates/dimensions around a particular host */ void calculate_canvas_bounds_from_host(char *host_name){ hostextinfo *temp_hostextinfo; int zoom_width; int zoom_height; /* find the extended host info */ temp_hostextinfo=find_hostextinfo(host_name); if(temp_hostextinfo==NULL) return; /* make sure we have 2-D coords */ if(temp_hostextinfo->have_2d_coords==FALSE) return; if(max_image_width>0 && proximity_width>max_image_width) zoom_width=max_image_width; else zoom_width=proximity_width; if(max_image_height>0 && proximity_height>max_image_height) zoom_height=max_image_height; else zoom_height=proximity_height; canvas_width=zoom_width; if(canvas_width>=total_image_width) canvas_x=0; else canvas_x=(temp_hostextinfo->x_2d-(zoom_width/2)); canvas_height=zoom_height; if(canvas_height>=total_image_height) canvas_y=0; else canvas_y=(temp_hostextinfo->y_2d-(zoom_height/2)); return; } /* calculates scaling factor used in image generation */ void calculate_scaling_factor(void){ double x_scaling=1.0; double y_scaling=1.0; /* calculate horizontal scaling factor */ if(max_image_width<=0 || canvas_width<=max_image_width) x_scaling=1.0; else x_scaling=(double)((double)max_image_width/(double)canvas_width); /* calculate vertical scaling factor */ if(max_image_height<=0 || canvas_height<=max_image_height) y_scaling=1.0; else y_scaling=(double)((double)max_image_height/(double)canvas_height); /* calculate general scaling factor to use */ if(x_scalingnext){ /* find the host */ temp_host=find_host(temp_hostextinfo->host_name,NULL); if(temp_host==NULL) temp_hostextinfo->should_be_drawn=FALSE; /* only include hosts that have 2-D coords supplied */ else if(temp_hostextinfo->have_2d_coords==FALSE) temp_hostextinfo->should_be_drawn=FALSE; /* make sure coords are all positive */ else if(temp_hostextinfo->x_2d<0 || temp_hostextinfo->y_2d<0) temp_hostextinfo->should_be_drawn=FALSE; /* make sure x coordinates fall within canvas bounds */ else if(temp_hostextinfo->x_2d<(canvas_x-DEFAULT_NODE_WIDTH) || temp_hostextinfo->x_2d>(canvas_x+canvas_width)) temp_hostextinfo->should_be_drawn=FALSE; /* make sure y coordinates fall within canvas bounds */ else if(temp_hostextinfo->y_2d<(canvas_y-DEFAULT_NODE_HEIGHT) || temp_hostextinfo->y_2d>(canvas_y+canvas_height)) temp_hostextinfo->should_be_drawn=FALSE; /* see if the user is authorized to view the host */ else if(is_authorized_for_host(temp_host,¤t_authdata)==FALSE) temp_hostextinfo->should_be_drawn=FALSE; /* all checks passed, so we can draw the host! */ else{ temp_hostextinfo->should_be_drawn=TRUE; total_eligible_hosts++; } } return; } /******************************************************************/ /*********************** DRAWING FUNCTIONS ************************/ /******************************************************************/ /* loads background image from file */ void load_background_image(void){ char temp_buffer[MAX_INPUT_BUFFER]; /* bail out if we shouldn't be drawing a background image */ if(layout_method!=LAYOUT_USER_SUPPLIED || statusmap_background_image==NULL) return; snprintf(temp_buffer,sizeof(temp_buffer)-1,"%s%s",physical_images_path,statusmap_background_image); temp_buffer[sizeof(temp_buffer)-1]='\x0'; /* read the background image into memory */ background_image=load_image_from_file(temp_buffer); /* grab background image dimensions for calculating total image width later */ if(background_image!=NULL){ background_image_width=background_image->sx; background_image_height=background_image->sy; } /* if we are just creating the html, we don't need the image anymore */ if(create_type==CREATE_HTML && background_image!=NULL) gdImageDestroy(background_image); return; } /* draws background image on drawing canvas */ void draw_background_image(void){ /* bail out if we shouldn't be drawing a background image */ if(create_type==CREATE_HTML || layout_method!=LAYOUT_USER_SUPPLIED || statusmap_background_image==NULL) return; /* bail out if we don't have an image */ if(background_image==NULL) return; /* copy the background image to the canvas */ gdImageCopy(map_image,background_image,0,0,canvas_x,canvas_y,canvas_width,canvas_height); /* free memory for background image, as we don't need it anymore */ gdImageDestroy(background_image); return; } /* draws background "extras" */ void draw_background_extras(void){ /* bail out if we shouldn't be here */ if(create_type==CREATE_HTML) return; /* circular layout stuff... */ if(layout_method==LAYOUT_CIRCULAR_MARKUP){ /* draw colored sections... */ draw_circular_markup(); } return; } /* draws host links */ void draw_host_links(void){ hostextinfo *temp_hostextinfo; hostextinfo *temp_parent_hostextinfo; host *this_host; host *main_host; host *parent_host; hostsmember *temp_hostsmember; int status_color=color_black; hoststatus *this_hoststatus; hoststatus *parent_hoststatus; int child_in_layer_list=FALSE; int parent_in_layer_list=FALSE; int dotted_line=FALSE; int x=0; int y=0; if(create_type==CREATE_HTML) return; if(use_links==FALSE) return; /* find the "main" host we're drawing */ main_host=find_host(host_name,NULL); if(show_all_hosts==TRUE) main_host=NULL; /* check all extended host information entries... */ for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){ /* find the config entry for this host */ this_host=find_host(temp_hostextinfo->host_name,NULL); if(this_host==NULL) continue; /* only draw link if user is authorized to view this host */ if(is_authorized_for_host(this_host,¤t_authdata)==FALSE) continue; /* this is a "root" host, so draw link to Nagios process icon if using auto-layout mode */ if(this_host->parent_hosts==NULL && layout_method!=LAYOUT_USER_SUPPLIED && draw_nagios_icon==TRUE){ x=temp_hostextinfo->x_2d+(DEFAULT_NODE_WIDTH/2)-canvas_x; y=temp_hostextinfo->y_2d+(DEFAULT_NODE_WIDTH/2)-canvas_y; draw_line(x,y,nagios_icon_x+(DEFAULT_NODE_WIDTH/2)-canvas_x,nagios_icon_y+(DEFAULT_NODE_WIDTH/2)-canvas_y,color_black); } /* this is a child of the main host we're drawing in auto-layout mode... */ if(layout_method!=LAYOUT_USER_SUPPLIED && draw_child_links==TRUE && number_of_immediate_child_hosts(this_host)>0 && is_host_immediate_child_of_host(main_host,this_host)==TRUE){ /* determine color to use when drawing links to children */ this_hoststatus=find_hoststatus(temp_hostextinfo->host_name); if(this_hoststatus!=NULL){ if(this_hoststatus->status==HOST_DOWN || this_hoststatus->status==HOST_UNREACHABLE) status_color=color_red; else status_color=color_black; } else status_color=color_black; x=temp_hostextinfo->x_2d+(DEFAULT_NODE_WIDTH/2)-canvas_x; y=(temp_hostextinfo->y_2d+(DEFAULT_NODE_WIDTH)/2)-canvas_y; draw_dashed_line(x,y,x,y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING,status_color); /* draw arrow tips */ draw_line(x,y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING,x-5,y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING-5,color_black); draw_line(x,y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING,x+5,y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING-5,color_black); } /* this is a parent of the main host we're drawing in auto-layout mode... */ if(layout_method!=LAYOUT_USER_SUPPLIED && draw_parent_links==TRUE && is_host_immediate_child_of_host(this_host,main_host)==TRUE){ x=temp_hostextinfo->x_2d+(DEFAULT_NODE_WIDTH/2)-canvas_x; y=temp_hostextinfo->y_2d+(DEFAULT_NODE_WIDTH/2)-canvas_y; draw_dashed_line(x,y,x,y-DEFAULT_NODE_HEIGHT-DEFAULT_NODE_VSPACING,color_black); /* draw arrow tips */ draw_line(x,y-DEFAULT_NODE_HEIGHT-DEFAULT_NODE_VSPACING,x-5,y-DEFAULT_NODE_HEIGHT-DEFAULT_NODE_VSPACING+5,color_black); draw_line(x,y-DEFAULT_NODE_HEIGHT-DEFAULT_NODE_VSPACING,x+5,y-DEFAULT_NODE_HEIGHT-DEFAULT_NODE_VSPACING+5,color_black); } /* draw links to all parent hosts */ for(temp_hostsmember=this_host->parent_hosts;temp_hostsmember!=NULL;temp_hostsmember=temp_hostsmember->next){ /* find extended info entry for this parent host */ temp_parent_hostextinfo=find_hostextinfo(temp_hostsmember->host_name); if(temp_parent_hostextinfo==NULL) continue; /* don't draw the link if we don't have the coords */ if(temp_parent_hostextinfo->have_2d_coords==FALSE || temp_hostextinfo->have_2d_coords==FALSE) continue; /* find the parent host config entry */ parent_host=find_host(temp_parent_hostextinfo->host_name,NULL); if(parent_host==NULL) continue; /* only draw link if user is authorized for this parent host */ if(is_authorized_for_host(parent_host,¤t_authdata)==FALSE) continue; /* are the hosts in the layer list? */ child_in_layer_list=is_host_in_layer_list(this_host); parent_in_layer_list=is_host_in_layer_list(parent_host); /* use dotted or solid line? */ /* either the child or parent should not be drawn, so use a dotted line */ if((child_in_layer_list==TRUE && parent_in_layer_list==FALSE) || (child_in_layer_list==FALSE && parent_in_layer_list==TRUE)) dotted_line=TRUE; /* both hosts should not be drawn, so use a dotted line */ else if((child_in_layer_list==FALSE && parent_in_layer_list==FALSE && exclude_layers==FALSE) || (child_in_layer_list==TRUE && parent_in_layer_list==TRUE && exclude_layers==TRUE)) dotted_line=TRUE; /* both hosts should be drawn, so use a solid line */ else dotted_line=FALSE; /* determine color to use when drawing links to parent host */ parent_hoststatus=find_hoststatus(temp_parent_hostextinfo->host_name); if(parent_hoststatus!=NULL){ if(parent_hoststatus->status==HOST_DOWN || parent_hoststatus->status==HOST_UNREACHABLE) status_color=color_red; else status_color=color_black; } else status_color=color_black; /* draw the link */ if(dotted_line==TRUE) draw_dotted_line((temp_hostextinfo->x_2d+(DEFAULT_NODE_WIDTH/2))-canvas_x,(temp_hostextinfo->y_2d+(DEFAULT_NODE_WIDTH)/2)-canvas_y,(temp_parent_hostextinfo->x_2d+(DEFAULT_NODE_WIDTH/2))-canvas_x,(temp_parent_hostextinfo->y_2d+(DEFAULT_NODE_WIDTH/2))-canvas_y,status_color); else draw_line_extended((temp_hostextinfo->x_2d+(DEFAULT_NODE_WIDTH/2))-canvas_x,(temp_hostextinfo->y_2d+(DEFAULT_NODE_WIDTH)/2)-canvas_y,(temp_parent_hostextinfo->x_2d+(DEFAULT_NODE_WIDTH/2))-canvas_x,(temp_parent_hostextinfo->y_2d+(DEFAULT_NODE_WIDTH/2))-canvas_y,status_color); } } return; } /* draws hosts */ void draw_hosts(void){ hostextinfo *temp_hostextinfo; host *temp_host; int x1, x2; int y1, y2; int has_image=FALSE; char image_input_file[MAX_INPUT_BUFFER]; int current_radius=0; int status_color=color_black; hoststatus *temp_hoststatus; int in_layer_list=FALSE; int average_host_services; int host_services; double host_services_ratio; int outer_radius; int inner_radius; int time_color=0; time_t current_time; int translated_x; int translated_y; /* user didn't supply any coordinates for hosts, so display a warning */ if(coordinates_were_specified==FALSE){ if(create_type==CREATE_IMAGE){ draw_text("You have not supplied any host drawing coordinates, so you cannot use this layout method.",(COORDS_WARNING_WIDTH/2),30,color_black); draw_text("Read the FAQs for more information on specifying drawing coordinates or select a different layout method.",(COORDS_WARNING_WIDTH/2),45,color_black); } return; } /* draw Nagios process icon if using auto-layout mode */ if(layout_method!=LAYOUT_USER_SUPPLIED && draw_nagios_icon==TRUE){ /* get coords of bounding box */ x1=nagios_icon_x-canvas_x; x2=x1+DEFAULT_NODE_WIDTH; y1=nagios_icon_y-canvas_y; y2=y1+DEFAULT_NODE_HEIGHT; /* get the name of the image file to open for the logo */ snprintf(image_input_file,sizeof(image_input_file)-1,"%s%s",physical_logo_images_path,NAGIOS_GD2_ICON); image_input_file[sizeof(image_input_file)-1]='\x0'; /* read in the image from file... */ logo_image=load_image_from_file(image_input_file); /* copy the logo image to the canvas image... */ if(logo_image!=NULL){ gdImageCopy(map_image,logo_image,x1,y1,0,0,logo_image->sx,logo_image->sy); gdImageDestroy(logo_image); } /* if we don't have an image, draw a bounding box */ else{ draw_line(x1,y1,x1,y1+DEFAULT_NODE_WIDTH,color_black); draw_line(x1,y1+DEFAULT_NODE_WIDTH,x2,y1+DEFAULT_NODE_WIDTH,color_black); draw_line(x2,y1+DEFAULT_NODE_WIDTH,x2,y1,color_black); draw_line(x2,y1,x1,y1,color_black); } if(create_type==CREATE_IMAGE) draw_text("Nagios Process",x1+(DEFAULT_NODE_WIDTH/2),y1+DEFAULT_NODE_HEIGHT,color_black); } /* calculate average services per host */ average_host_services=4; /* draw all hosts... */ for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){ /* skip hosts that should not be drawn */ if(temp_hostextinfo->should_be_drawn==FALSE) continue; /* find the host */ temp_host=find_host(temp_hostextinfo->host_name,NULL); /* is this host in the layer inclusion/exclusion list? */ in_layer_list=is_host_in_layer_list(temp_host); if((in_layer_list==TRUE && exclude_layers==TRUE) || (in_layer_list==FALSE && exclude_layers==FALSE)) continue; /* get coords of host bounding box */ x1=temp_hostextinfo->x_2d-canvas_x; x2=x1+DEFAULT_NODE_WIDTH; y1=temp_hostextinfo->y_2d-canvas_y; y2=y1+DEFAULT_NODE_HEIGHT; if(create_type==CREATE_IMAGE){ temp_hoststatus=find_hoststatus(temp_hostextinfo->host_name); if(temp_hoststatus!=NULL){ if(temp_hoststatus->status==HOST_DOWN) status_color=color_red; else if(temp_hoststatus->status==HOST_UNREACHABLE) status_color=color_red; else if(temp_hoststatus->status==HOST_UP) status_color=color_green; else if(temp_hoststatus->status==HOST_PENDING) status_color=color_grey; } else status_color=color_black; /* use balloons instead of icons... */ if(layout_method==LAYOUT_CIRCULAR_BALLOON){ /* get the number of services associated with the host */ host_services=number_of_host_services(temp_host); if(average_host_services==0) host_services_ratio=0.0; else host_services_ratio=(double)((double)host_services/(double)average_host_services); /* calculate size of node */ if(host_services_ratio>=2.0) outer_radius=DEFAULT_NODE_WIDTH; else if(host_services_ratio>=1.5) outer_radius=DEFAULT_NODE_WIDTH*0.8; else if(host_services_ratio>=1.0) outer_radius=DEFAULT_NODE_WIDTH*0.6; else if(host_services_ratio>=0.5) outer_radius=DEFAULT_NODE_WIDTH*0.4; else outer_radius=DEFAULT_NODE_WIDTH*0.2; /* calculate width of border */ if(temp_hoststatus==NULL) inner_radius=outer_radius; else if((temp_hoststatus->status==HOST_DOWN || temp_hoststatus->status==HOST_UNREACHABLE) && temp_hoststatus->problem_has_been_acknowledged==FALSE) inner_radius=outer_radius-3; else inner_radius=outer_radius; /* fill node with color based on how long its been in this state... */ gdImageArc(map_image,x1+(DEFAULT_NODE_WIDTH/2),y1+(DEFAULT_NODE_WIDTH/2),outer_radius,outer_radius,0,360,color_blue); /* determine fill color */ time(¤t_time); if(temp_hoststatus==NULL) time_color=color_white; else if(current_time-temp_hoststatus->last_state_change<=900) time_color=color_orange; else if(current_time-temp_hoststatus->last_state_change<=3600) time_color=color_yellow; else time_color=color_white; /* fill node with appropriate time color */ /* the fill function only works with coordinates that are in bounds of the actual image */ translated_x=x1+(DEFAULT_NODE_WIDTH/2); translated_y=y1+(DEFAULT_NODE_WIDTH/2); if(translated_x>0 && translated_y>0 && translated_x=inner_radius;current_radius--) gdImageArc(map_image,x1+(DEFAULT_NODE_WIDTH/2),y1+(DEFAULT_NODE_WIDTH/2),current_radius,current_radius,0,360,status_color); /* draw circles around the selected host (if there is one) */ if(!strcmp(host_name,temp_hostextinfo->host_name) && use_highlights==TRUE){ for(current_radius=DEFAULT_NODE_WIDTH*2;current_radius>0;current_radius-=10) gdImageArc(map_image,x1+(DEFAULT_NODE_WIDTH/2),y1+(DEFAULT_NODE_WIDTH/2),current_radius,current_radius,0,360,status_color); } } /* normal method is to use icons for hosts... */ else{ /* draw a target around root hosts (hosts with no parents) */ if(temp_host!=NULL && use_highlights==TRUE){ if(temp_host->parent_hosts==NULL){ gdImageArc(map_image,x1+(DEFAULT_NODE_WIDTH/2),y1+(DEFAULT_NODE_WIDTH/2),(DEFAULT_NODE_WIDTH*2),(DEFAULT_NODE_WIDTH*2),0,360,status_color); draw_line(x1-(DEFAULT_NODE_WIDTH/2),y1+(DEFAULT_NODE_WIDTH/2),x1+(DEFAULT_NODE_WIDTH*3/2),y1+(DEFAULT_NODE_WIDTH/2),status_color); draw_line(x1+(DEFAULT_NODE_WIDTH/2),y1-(DEFAULT_NODE_WIDTH/2),x1+(DEFAULT_NODE_WIDTH/2),y1+(DEFAULT_NODE_WIDTH*3/2),status_color); } } /* draw circles around the selected host (if there is one) */ if(!strcmp(host_name,temp_hostextinfo->host_name) && use_highlights==TRUE){ for(current_radius=DEFAULT_NODE_WIDTH*2;current_radius>0;current_radius-=10) gdImageArc(map_image,x1+(DEFAULT_NODE_WIDTH/2),y1+(DEFAULT_NODE_WIDTH/2),current_radius,current_radius,0,360,status_color); } if(temp_hostextinfo->gd2_icon_image!=NULL) has_image=TRUE; else has_image=FALSE; /* load the logo associated with this host */ if(has_image==TRUE){ /* get the name of the image file to open for the logo */ snprintf(image_input_file,sizeof(image_input_file)-1,"%s%s",physical_logo_images_path,temp_hostextinfo->gd2_icon_image); image_input_file[sizeof(image_input_file)-1]='\x0'; /* read in the logo image from file... */ logo_image=load_image_from_file(image_input_file); /* copy the logo image to the canvas image... */ if(logo_image!=NULL){ gdImageCopy(map_image,logo_image,x1,y1,0,0,logo_image->sx,logo_image->sy); gdImageDestroy(logo_image); } else has_image=FALSE; } /* if the host doesn't have an image associated with it (or the user doesn't have rights to see this host), use the unknown image */ if(has_image==FALSE){ if(unknown_logo_image!=NULL) gdImageCopy(map_image,unknown_logo_image,x1,y1,0,0,unknown_logo_image->sx,unknown_logo_image->sy); else{ /* last ditch effort - draw a host bounding box */ draw_line(x1,y1,x1,y1+DEFAULT_NODE_WIDTH,color_black); draw_line(x1,y1+DEFAULT_NODE_WIDTH,x2,y1+DEFAULT_NODE_WIDTH,color_black); draw_line(x2,y1+DEFAULT_NODE_WIDTH,x2,y1,color_black); draw_line(x2,y1,x1,y1,color_black); } } } /* draw host name, status, etc. */ draw_host_text(temp_hostextinfo->host_name,x1+(DEFAULT_NODE_WIDTH/2),y1+DEFAULT_NODE_HEIGHT); } /* we're creating HTML image map... */ else{ printf("host_name)) printf("href='%s?host=%s' ",STATUS_CGI,url_encode(temp_hostextinfo->host_name)); else{ printf("href='%s?host=%s&layout=%d&max_width=%d&max_height=%d&proximity_width=%d&proximity_height=%d%s%s%s%s%s",STATUSMAP_CGI,url_encode(temp_hostextinfo->host_name),layout_method,max_image_width,max_image_height,proximity_width,proximity_height,(display_header==TRUE)?"":"&noheader",(use_links==FALSE)?"&nolinks":"",(use_text==FALSE)?"¬ext":"",(use_highlights==FALSE)?"&nohighlights":"",(display_popups==FALSE)?"&nopopups":""); if(user_supplied_scaling==TRUE) printf("&scaling_factor=%2.1f",user_scaling_factor); print_layer_url(TRUE); printf("' "); } /* popup text */ if(display_popups==TRUE){ printf("onMouseOver='showPopup(\""); write_host_popup_text(find_host(temp_hostextinfo->host_name,NULL)); printf("\",event)' onMouseOut='hidePopup()'"); } printf(">\n"); } } return; } /* draws text */ void draw_text(char *buffer,int x,int y,int text_color){ int string_width=0; int string_height=0; /* write the string to the generated image... */ string_height=gdFontSmall->h; string_width=gdFontSmall->w*strlen(buffer); if(layout_method!=LAYOUT_CIRCULAR_MARKUP) gdImageFilledRectangle(map_image,x-(string_width/2)-2,y-(2*string_height),x+(string_width/2)+2,y-string_height,color_white); gdImageString(map_image,gdFontSmall,x-(string_width/2),y-(2*string_height),(unsigned char *)buffer,text_color); return; } /* draws host text */ void draw_host_text(char *name,int x,int y){ hoststatus *temp_hoststatus; int status_color=color_black; char temp_buffer[MAX_INPUT_BUFFER]; int string_width=0; int string_height=0; if(use_text==FALSE) return; strncpy(temp_buffer,name,sizeof(temp_buffer)-1); temp_buffer[sizeof(temp_buffer)-1]='\x0'; /* write the host status string to the generated image... */ draw_text(temp_buffer,x,y,color_black); /* find the status entry for this host */ temp_hoststatus=find_hoststatus(name); /* get the status of the host (pending, up, down, or unreachable) */ if(temp_hoststatus!=NULL){ /* draw the status string */ if(temp_hoststatus->status==HOST_DOWN){ strncpy(temp_buffer,"Down",sizeof(temp_buffer)); status_color=color_red; } else if(temp_hoststatus->status==HOST_UNREACHABLE){ strncpy(temp_buffer,"Unreachable",sizeof(temp_buffer)); status_color=color_red; } else if(temp_hoststatus->status==HOST_UP){ strncpy(temp_buffer,"Up",sizeof(temp_buffer)); status_color=color_green; } else if(temp_hoststatus->status==HOST_PENDING){ strncpy(temp_buffer,"Pending",sizeof(temp_buffer)); status_color=color_grey; } else{ strncpy(temp_buffer,"Unknown",sizeof(temp_buffer)); status_color=color_orange; } temp_buffer[sizeof(temp_buffer)-1]='\x0'; /* write the host status string to the generated imate... */ draw_text(temp_buffer,x,y+gdFontSmall->h,status_color); } return; } /* writes popup text for a specific host */ void write_host_popup_text(host *hst){ hostextinfo *temp_hostextinfo; hoststatus *temp_status; hostsmember *temp_hostsmember; int service_totals; char date_time[48]; time_t current_time; time_t t; char state_duration[48]; int days; int hours; int minutes; int seconds; if(hst==NULL){ printf("Host data not found"); return; } /* find the status entry for this host */ temp_status=find_hoststatus(hst->name); if(temp_status==NULL){ printf("Host status information not found"); return; } /* strip nasty stuff from plugin output */ sanitize_plugin_output(temp_status->information); printf(""); temp_hostextinfo=find_hostextinfo(hst->name); if(temp_hostextinfo!=NULL){ printf("",url_logo_images_path,(temp_hostextinfo->icon_image==NULL)?UNKNOWN_ICON_IMAGE:temp_hostextinfo->icon_image); printf("",(temp_hostextinfo->icon_image_alt==NULL)?"":html_encode(temp_hostextinfo->icon_image_alt)); } printf("",html_encode(hst->name)); printf("",html_encode(hst->alias)); printf("",html_encode(hst->address)); printf(""); printf("",temp_status->information); current_time=time(NULL); if(temp_status->last_state_change==(time_t)0) t=current_time-program_start; else t=current_time-temp_status->last_state_change; get_time_breakdown((unsigned long)t,&days,&hours,&minutes,&seconds); snprintf(state_duration,sizeof(state_duration)-1,"%2dd %2dh %2dm %2ds%s",days,hours,minutes,seconds,(temp_status->last_state_change==(time_t)0)?"+":""); state_duration[sizeof(state_duration)-1]='\x0'; printf("",state_duration); get_time_string(&temp_status->last_check,date_time,(int)sizeof(date_time),SHORT_DATE_TIME); printf("",(temp_status->last_check==(time_t)0)?"N/A":date_time); get_time_string(&temp_status->last_state_change,date_time,(int)sizeof(date_time),SHORT_DATE_TIME); printf("",(temp_status->last_state_change==(time_t)0)?"N/A":date_time); printf(""); printf(""); printf("
%s
Name:%s
Alias:%s
Address:%s
State:"); /* get the status of the host (pending, up, down, or unreachable) */ if(temp_status->status==HOST_DOWN){ printf("Down"); if(temp_status->problem_has_been_acknowledged==TRUE) printf(" (Acknowledged)"); printf(""); } else if(temp_status->status==HOST_UNREACHABLE){ printf("Unreachable"); if(temp_status->problem_has_been_acknowledged==TRUE) printf(" (Acknowledged)"); printf(""); } else if(temp_status->status==HOST_UP) printf("Up"); else if(temp_status->status==HOST_PENDING) printf("Pending"); printf("
Status Information:%s
State Duration:%s
Last Status Check:%s
Last State Change:%s
Parent Host(s):"); if(hst->parent_hosts==NULL) printf("None (This is a root host)"); else{ for(temp_hostsmember=hst->parent_hosts;temp_hostsmember!=NULL;temp_hostsmember=temp_hostsmember->next) printf("%s%s",(temp_hostsmember==hst->parent_hosts)?"":", ",html_encode(temp_hostsmember->host_name)); } printf("
Immediate Child Hosts:"); printf("%d",number_of_immediate_child_hosts(hst)); printf("
"); printf("
Services:
"); service_totals=get_servicestatus_count(hst->name,SERVICE_OK)+get_servicestatus_count(hst->name,SERVICE_RECOVERY); if(service_totals>0) printf("- %d ok
",service_totals); service_totals=get_servicestatus_count(hst->name,SERVICE_CRITICAL)+get_servicestatus_count(hst->name,SERVICE_UNREACHABLE)+get_servicestatus_count(hst->name,SERVICE_HOST_DOWN); if(service_totals>0) printf("- %d critical
",service_totals); service_totals=get_servicestatus_count(hst->name,SERVICE_WARNING); if(service_totals>0) printf("- %d warning
",service_totals); service_totals=get_servicestatus_count(hst->name,SERVICE_UNKNOWN); if(service_totals>0) printf("- %d unknown
",service_totals); service_totals=get_servicestatus_count(hst->name,SERVICE_PENDING); if(service_totals>0) printf("- %d pending
",service_totals); return; } /* draws a solid line */ void draw_line_extended(int x1,int y1,int x2,int y2,int color){ if(create_type==CREATE_HTML) return; if( x1 == x2 ) { gdImageLine(map_image,x1,y1,x2,y2,color); gdImageLine(map_image,x1 + 1,y1,x2 + 1,y2,color); gdImageLine(map_image,x1 + 2,y1,x2 + 2,y2,color); } else { gdImageLine(map_image,x1,y1,x2,y2,color); gdImageLine(map_image,x1,y1 + 1,x2,y2 + 1,color); gdImageLine(map_image,x1,y1 + 2,x2,y2 + 2,color); } return; } void draw_line(int x1,int y1,int x2,int y2,int color){ if(create_type==CREATE_HTML) return; gdImageLine(map_image,x1,y1,x2,y2,color); return; } /* draws a dotted line */ void draw_dotted_line(int x1,int y1,int x2,int y2,int color){ int styleDotted[12]; styleDotted[0]=color; styleDotted[1]=gdTransparent; styleDotted[2]=gdTransparent; styleDotted[3]=gdTransparent; styleDotted[4]=gdTransparent; styleDotted[5]=gdTransparent; styleDotted[6]=color; styleDotted[7]=gdTransparent; styleDotted[8]=gdTransparent; styleDotted[9]=gdTransparent; styleDotted[10]=gdTransparent; styleDotted[11]=gdTransparent; /* sets current style to a dashed line */ gdImageSetStyle(map_image,styleDotted,12); /* draws a line (dotted) */ gdImageLine(map_image,x1,y1,x2,y2,gdStyled); 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]=color; styleDashed[3]=color; styleDashed[4]=gdTransparent; styleDashed[5]=gdTransparent; styleDashed[6]=color; styleDashed[7]=color; styleDashed[8]=color; styleDashed[9]=color; styleDashed[10]=gdTransparent; styleDashed[11]=gdTransparent; /* sets current style to a dashed line */ gdImageSetStyle(map_image,styleDashed,12); /* draws a line (dashed) */ gdImageLine(map_image,x1,y1,x2,y2,gdStyled); return; } /******************************************************************/ /*********************** GRAPHICS FUNCTIONS ***********************/ /******************************************************************/ /* initialize graphics */ int initialize_graphics(void){ char image_input_file[MAX_INPUT_BUFFER]; if(create_type==CREATE_HTML) return ERROR; /* allocate buffer for storing image */ map_image=gdImageCreate(canvas_width,canvas_height); if(map_image==NULL) return ERROR; /* allocate colors used for drawing */ color_white=gdImageColorAllocate(map_image,255,255,255); color_black=gdImageColorAllocate(map_image,0,0,0); color_grey=gdImageColorAllocate(map_image,128,128,128); color_lightgrey=gdImageColorAllocate(map_image,210,210,210); color_red=gdImageColorAllocate(map_image,255,0,0); color_lightred=gdImageColorAllocate(map_image,215,175,175); color_green=gdImageColorAllocate(map_image,0,175,0); color_lightgreen=gdImageColorAllocate(map_image,210,255,215); color_blue=gdImageColorAllocate(map_image,0,0,255); color_yellow=gdImageColorAllocate(map_image,255,255,0); color_orange=gdImageColorAllocate(map_image,255,100,25); /* set transparency index */ gdImageColorTransparent(map_image,color_white); /* make sure the graphic is interlaced */ gdImageInterlace(map_image,1); /* get the path where we will be reading logo images from (GD2 format)... */ snprintf(physical_logo_images_path,sizeof(physical_logo_images_path)-1,"%slogos/",physical_images_path); physical_logo_images_path[sizeof(physical_logo_images_path)-1]='\x0'; /* load the unknown icon to use for hosts that don't have pretty images associated with them... */ snprintf(image_input_file,sizeof(image_input_file)-1,"%s%s",physical_logo_images_path,UNKNOWN_GD2_ICON); image_input_file[sizeof(image_input_file)-1]='\x0'; unknown_logo_image=load_image_from_file(image_input_file); return OK; } /* loads a graphic image (GD2, JPG or PNG) from file into memory */ gdImagePtr load_image_from_file(char *filename){ FILE *fp; gdImagePtr im=NULL; char *ext; /* make sure we were passed a file name */ if(filename==NULL) return NULL; /* find the file extension */ if((ext=rindex(filename,'.'))==NULL) return NULL; /* open the file for reading (binary mode) */ fp=fopen(filename,"rb"); if(fp==NULL) return NULL; /* attempt to read files in various formats */ if(!strcasecmp(ext,".png")) im=gdImageCreateFromPng(fp); else if(!strcasecmp(ext,".jpg") || !strcasecmp(ext,".jpeg")) im=gdImageCreateFromJpeg(fp); else if(!strcasecmp(ext,".xbm")) im=gdImageCreateFromXbm(fp); else if(!strcasecmp(ext,".gd2")) im=gdImageCreateFromGd2(fp); else if(!strcasecmp(ext,".gd")) im=gdImageCreateFromGd(fp); /* fall back to GD2 image format */ else im=gdImageCreateFromGd2(fp); /* close the file */ fclose(fp); return im; } /* draw graphics */ void write_graphics(void){ FILE *image_output_file=NULL; if(create_type==CREATE_HTML) return; /* use STDOUT for writing the image data... */ image_output_file=stdout; /* write the image out in PNG format */ gdImagePng(map_image,image_output_file); /* or we could write the image out in JPG format... */ /*gdImageJpeg(map_image,image_output_file,99);*/ return; } /* cleanup graphics resources */ void cleanup_graphics(void){ if(create_type==CREATE_HTML) return; /* free memory allocated to image */ gdImageDestroy(map_image); return; } /******************************************************************/ /************************* MISC FUNCTIONS *************************/ /******************************************************************/ /* write JavaScript code an layer for popup window */ void write_popup_code(void){ char *border_color="#000000"; char *background_color="#ffffcc"; int border=1; int padding=3; int x_offset=3; int y_offset=3; printf("\n"); return; } /* adds a layer to the list in memory */ int add_layer(char *group_name){ layer *new_layer; if(group_name==NULL) return ERROR; /* allocate memory for a new layer */ new_layer=(layer *)malloc(sizeof(layer)); if(new_layer==NULL) return ERROR; new_layer->layer_name=(char *)malloc(strlen(group_name)+1); if(new_layer->layer_name==NULL){ free(new_layer); return ERROR; } strcpy(new_layer->layer_name,group_name); /* add new layer to head of layer list */ new_layer->next=layer_list; layer_list=new_layer; return OK; } /* frees memory allocated to the layer list */ void free_layer_list(void){ layer *this_layer; layer *next_layer; return; for(this_layer=layer_list;layer_list!=NULL;this_layer=next_layer){ next_layer=this_layer->next; free(this_layer->layer_name); free(this_layer); } return; } /* checks to see if a host is in the layer list */ int is_host_in_layer_list(host *hst){ hostgroup *temp_hostgroup; layer *temp_layer; if(hst==NULL) return FALSE; /* check each layer... */ for(temp_layer=layer_list;temp_layer!=NULL;temp_layer=temp_layer->next){ /* find the hostgroup */ temp_hostgroup=find_hostgroup(temp_layer->layer_name,NULL); if(temp_hostgroup==NULL) continue; /* is the requested host a member of the hostgroup/layer? */ if(is_host_member_of_hostgroup(temp_hostgroup,hst)==TRUE) return TRUE; } return FALSE; } /* print layer url info */ void print_layer_url(int get_method){ layer *temp_layer; for(temp_layer=layer_list;temp_layer!=NULL;temp_layer=temp_layer->next){ if(get_method==TRUE) printf("&layer=%s",temp_layer->layer_name); else printf("\n",temp_layer->layer_name); } if(get_method==TRUE) printf("&layermode=%s",(exclude_layers==TRUE)?"exclude":"include"); else printf("\n",(exclude_layers==TRUE)?"exclude":"include"); return; } /******************************************************************/ /************************ UTILITY FUNCTIONS ***********************/ /******************************************************************/ /* calculates how many "layers" separate parent and child - used by collapsed tree layout method */ int host_child_depth_separation(host *parent, host *child){ int this_depth=0; int min_depth=0; int have_min_depth=FALSE; host *temp_host; if(child==NULL) return -1; if(parent==child) return 0; if(is_host_immediate_child_of_host(parent,child)==TRUE) return 1; for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){ this_depth=host_child_depth_separation(temp_host,child); if(this_depth>=0 && (have_min_depth==FALSE || (have_min_depth==TRUE && (this_depthnext){ current_layer=host_child_depth_separation(parent,temp_host); if(current_layer==layer) layer_members++; } return layer_members; } /* calculate max number of members on all "layers" beneath and including parent host - used by collapsed tree layout method */ int max_child_host_layer_members(host *parent){ int current_layer; int max_members=1; int current_members=0; for(current_layer=1;;current_layer++){ current_members=number_of_host_layer_members(parent,current_layer); if(current_members<=0) break; if(current_members>max_members) max_members=current_members; } return max_members; } /* calculate max drawing width for host and children - used by balanced tree layout method */ int max_child_host_drawing_width(host *parent){ host *temp_host; int child_width=0; for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ if(is_host_immediate_child_of_host(parent,temp_host)==TRUE) child_width+=max_child_host_drawing_width(temp_host); } /* no children, so set width to 1 for this host */ if(child_width==0) return 1; else return child_width; } /* calculates number of services associated with a particular service */ int number_of_host_services(host *hst){ service *temp_service; int total_services=0; if(hst==NULL) return 0; /* check all the services */ for(temp_service=service_list;temp_service!=NULL;temp_service=temp_service->next){ if(!strcmp(temp_service->host_name,hst->name)) total_services++; } return total_services; } /******************************************************************/ /***************** COORDINATE CALCULATION FUNCTIONS ***************/ /******************************************************************/ /* calculates coords of a host's children - used by balanced tree layout method */ void calculate_balanced_tree_coords(host *parent, int x, int y){ int parent_drawing_width; int start_drawing_x; int current_drawing_x; int this_drawing_width; host *temp_host; hostextinfo *temp_hostextinfo; /* calculate total drawing width of parent host */ parent_drawing_width=max_child_host_drawing_width(parent); /* calculate starting x coord */ start_drawing_x=x-(((DEFAULT_NODE_WIDTH*parent_drawing_width)+(DEFAULT_NODE_HSPACING*(parent_drawing_width-1)))/2); current_drawing_x=start_drawing_x; /* calculate coords for children */ for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ temp_hostextinfo=find_hostextinfo(temp_host->name); if(temp_hostextinfo==NULL) continue; if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){ /* get drawing width of child host */ this_drawing_width=max_child_host_drawing_width(temp_host); temp_hostextinfo->x_2d=current_drawing_x+(((DEFAULT_NODE_WIDTH*this_drawing_width)+(DEFAULT_NODE_HSPACING*(this_drawing_width-1)))/2); temp_hostextinfo->y_2d=y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING; temp_hostextinfo->have_2d_coords=TRUE; temp_hostextinfo->should_be_drawn=TRUE; current_drawing_x+=(this_drawing_width*DEFAULT_NODE_WIDTH)+((this_drawing_width-1)*DEFAULT_NODE_HSPACING)+DEFAULT_NODE_HSPACING; /* recurse into child host ... */ calculate_balanced_tree_coords(temp_host,temp_hostextinfo->x_2d,temp_hostextinfo->y_2d); } } return; } /* calculate coords of all hosts in circular layout method */ void calculate_circular_coords(void){ int min_x=0; int min_y=0; int have_min_x=FALSE; int have_min_y=FALSE; int max_y=0; int have_max_y=FALSE; hostextinfo *temp_hostextinfo; /* calculate all host coords, starting with first layer */ calculate_circular_layer_coords(NULL,0.0,360.0,1,CIRCULAR_DRAWING_RADIUS); /* adjust all calculated coords so none are negative in x or y axis... */ /* calculate min x, y coords */ for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){ if(have_min_x==FALSE || temp_hostextinfo->x_2dx_2d; } if(have_min_y==FALSE || temp_hostextinfo->y_2dy_2d; } } /* offset all drawing coords by the min x,y coords we found */ for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){ if(min_x<0) temp_hostextinfo->x_2d-=min_x; if(min_y<0) temp_hostextinfo->y_2d-=min_y; } if(min_x<0) nagios_icon_x-=min_x; if(min_y<0) nagios_icon_y-=min_y; for(temp_hostextinfo=hostextinfo_list;temp_hostextinfo!=NULL;temp_hostextinfo=temp_hostextinfo->next){ temp_hostextinfo->x_2d+=(DEFAULT_NODE_WIDTH/2); temp_hostextinfo->y_2d+=(DEFAULT_NODE_HEIGHT/2); } nagios_icon_x+=(DEFAULT_NODE_WIDTH/2); nagios_icon_y+=(DEFAULT_NODE_HEIGHT/2); return; } /* calculates coords of all hosts in a particular "layer" in circular layout method */ void calculate_circular_layer_coords(host *parent, double start_angle, double useable_angle, int layer, int radius){ int parent_drawing_width=0; int this_drawing_width=0; int immediate_children=0; double current_drawing_angle=0.0; double this_drawing_angle=0.0; double available_angle=0.0; double clipped_available_angle=0.0; double average_child_angle=0.0; double x_coord=0.0; double y_coord=0.0; host *temp_host; hostextinfo *temp_hostextinfo; /* get the total number of immediate children to this host */ immediate_children=number_of_immediate_child_hosts(parent); /* bail out if we're done */ if(immediate_children==0) return; /* calculate total drawing "width" of parent host */ parent_drawing_width=max_child_host_drawing_width(parent); /* calculate average angle given to each child host */ average_child_angle=(double)(useable_angle/(double)immediate_children); /* calculate initial drawing angle */ current_drawing_angle=start_angle; /* calculate coords for children */ for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ temp_hostextinfo=find_hostextinfo(temp_host->name); if(temp_hostextinfo==NULL) continue; if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){ /* get drawing width of child host */ this_drawing_width=max_child_host_drawing_width(temp_host); /* calculate angle this host gets for drawing */ available_angle=useable_angle*((double)this_drawing_width/(double)parent_drawing_width); /* clip available angle if necessary */ /* this isn't really necessary, but helps keep things looking a bit more sane with less potential connection crossover */ clipped_available_angle=360.0/layer; if(available_angle=360.0) this_drawing_angle-=360.0; while(this_drawing_angle<0.0) this_drawing_angle+=360.0; /* calculate drawing coords of this host using good ol' geometry... */ x_coord=-(sin(-this_drawing_angle*(M_PI/180.0))*radius); y_coord=-(sin((90+this_drawing_angle)*(M_PI/180.0))*radius); temp_hostextinfo->x_2d=(int)x_coord; temp_hostextinfo->y_2d=(int)y_coord; temp_hostextinfo->have_2d_coords=TRUE; temp_hostextinfo->should_be_drawn=TRUE; /* recurse into child host ... */ calculate_circular_layer_coords(temp_host,current_drawing_angle+((available_angle-clipped_available_angle)/2),clipped_available_angle,layer+1,radius+CIRCULAR_DRAWING_RADIUS); /* increment current drawing angle */ current_drawing_angle+=available_angle; } } return; } /* draws background "extras" for all hosts in circular markup layout */ void draw_circular_markup(void){ /* calculate all host sections, starting with first layer */ draw_circular_layer_markup(NULL,0.0,360.0,1,CIRCULAR_DRAWING_RADIUS); return; } /* draws background "extras" for all hosts in a particular "layer" in circular markup layout */ void draw_circular_layer_markup(host *parent, double start_angle, double useable_angle, int layer, int radius){ int parent_drawing_width=0; int this_drawing_width=0; int immediate_children=0; double current_drawing_angle=0.0; double available_angle=0.0; double clipped_available_angle=0.0; double average_child_angle=0.0; double x_coord[4]={0.0,0.0,0.0,0.0}; double y_coord[4]={0.0,0.0,0.0,0.0}; host *temp_host; hoststatus *temp_hoststatus; hostextinfo *temp_hostextinfo; int x_offset=0; int y_offset=0; int center_x=0; int center_y=0; int bgcolor=0; double arc_start_angle=0.0; double arc_end_angle=0.0; int translated_x=0; int translated_y=0; /* get the total number of immediate children to this host */ immediate_children=number_of_immediate_child_hosts(parent); /* bail out if we're done */ if(immediate_children==0) return; /* calculate total drawing "width" of parent host */ parent_drawing_width=max_child_host_drawing_width(parent); /* calculate average angle given to each child host */ average_child_angle=(double)(useable_angle/(double)immediate_children); /* calculate initial drawing angle */ current_drawing_angle=start_angle; /* calculate coords for children */ for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ temp_hostextinfo=find_hostextinfo(temp_host->name); if(temp_hostextinfo==NULL) continue; if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){ /* get drawing width of child host */ this_drawing_width=max_child_host_drawing_width(temp_host); /* calculate angle this host gets for drawing */ available_angle=useable_angle*((double)this_drawing_width/(double)parent_drawing_width); /* clip available angle if necessary */ /* this isn't really necessary, but helps keep things looking a bit more sane with less potential connection crossover */ clipped_available_angle=360.0/layer; if(available_angle1 || layer>1){ /* draw "leftmost" divider */ gdImageLine(map_image,(int)x_coord[0]+x_offset,(int)y_coord[0]+y_offset,(int)x_coord[1]+x_offset,(int)y_coord[1]+y_offset,color_lightgrey); /* draw "rightmost" divider */ gdImageLine(map_image,(int)x_coord[2]+x_offset,(int)y_coord[2]+y_offset,(int)x_coord[3]+x_offset,(int)y_coord[3]+y_offset,color_lightgrey); } /* determine arc drawing angles */ arc_start_angle=current_drawing_angle-90.0; while(arc_start_angle<0.0) arc_start_angle+=360.0; arc_end_angle=arc_start_angle+available_angle; /* draw inner arc */ gdImageArc(map_image,x_offset,y_offset,(radius-(CIRCULAR_DRAWING_RADIUS/2))*2,(radius-(CIRCULAR_DRAWING_RADIUS/2))*2,floor(arc_start_angle),ceil(arc_end_angle),color_lightgrey); /* draw outer arc */ gdImageArc(map_image,x_offset,y_offset,(radius+(CIRCULAR_DRAWING_RADIUS/2))*2,(radius+(CIRCULAR_DRAWING_RADIUS/2))*2,floor(arc_start_angle),ceil(arc_end_angle),color_lightgrey); /* determine center of "slice" and fill with appropriate color */ center_x=-(sin(-(current_drawing_angle+(available_angle/2.0))*(M_PI/180.0))*(radius)); center_y=-(sin((90+current_drawing_angle+(available_angle/2.0))*(M_PI/180.0))*(radius)); translated_x=center_x+x_offset; translated_y=center_y+y_offset; /* determine background color */ temp_hoststatus=find_hoststatus(temp_host->name); if(temp_hoststatus==NULL) bgcolor=color_lightgrey; else if(temp_hoststatus->status==HOST_DOWN || temp_hoststatus->status==HOST_UNREACHABLE) bgcolor=color_lightred; else bgcolor=color_lightgreen; /* fill slice with background color */ /* the fill function only works with coordinates that are in bounds of the actual image */ if(translated_x>0 && translated_y>0 && translated_x