![]() |
Icinga-core 1.4.0
next gen monitoring
|
00001 /***************************************************************************** 00002 * 00003 * STATUSMAP.C - Icinga Network Status Map CGI 00004 * 00005 * Copyright (c) 1999-2008 Ethan Galstad (egalstad@nagios.org) 00006 * Copyright (c) 2009-2011 Icinga Development Team (http://www.icinga.org) 00007 * 00008 * Description: 00009 * 00010 * This CGI will create a map of all hosts that are being monitored on your 00011 * network. 00012 * 00013 * License: 00014 * 00015 * This program is free software; you can redistribute it and/or modify 00016 * it under the terms of the GNU General Public License version 2 as 00017 * published by the Free Software Foundation. 00018 * 00019 * This program is distributed in the hope that it will be useful, 00020 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00021 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00022 * GNU General Public License for more details. 00023 * 00024 * You should have received a copy of the GNU General Public License 00025 * along with this program; if not, write to the Free Software 00026 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00027 * 00028 *****************************************************************************/ 00029 00030 #include "../include/config.h" 00031 #include "../include/common.h" 00032 #include "../include/objects.h" 00033 #include "../include/macros.h" 00034 #include "../include/statusdata.h" 00035 #include "../include/cgiutils.h" 00036 #include "../include/getcgi.h" 00037 #include "../include/cgiauth.h" 00038 00039 #include <gd.h> /* Boutell's GD library function */ 00040 #include <gdfonts.h> /* GD library small font definition */ 00041 00042 static icinga_macros *mac; 00043 00044 /*#define DEBUG*/ 00045 00046 #define UNKNOWN_GD2_ICON "unknown.gd2" 00047 #define UNKNOWN_ICON_IMAGE "unknown.gif" 00048 #define ICINGA_GD2_ICON "icinga.gd2" 00049 00050 extern char main_config_file[MAX_FILENAME_LENGTH]; 00051 extern char url_html_path[MAX_FILENAME_LENGTH]; 00052 extern char physical_images_path[MAX_FILENAME_LENGTH]; 00053 extern char url_images_path[MAX_FILENAME_LENGTH]; 00054 extern char url_logo_images_path[MAX_FILENAME_LENGTH]; 00055 extern char url_stylesheets_path[MAX_FILENAME_LENGTH]; 00056 extern char url_js_path[MAX_FILENAME_LENGTH]; 00057 00058 extern host *host_list; 00059 extern hostgroup *hostgroup_list; 00060 extern service *service_list; 00061 extern hoststatus *hoststatus_list; 00062 extern servicestatus *servicestatus_list; 00063 00064 extern char *statusmap_background_image; 00065 00066 extern int default_statusmap_layout_method; 00067 00068 #define DEFAULT_NODE_WIDTH 40 00069 #define DEFAULT_NODE_HEIGHT 65 00070 00071 #define DEFAULT_NODE_VSPACING 15 00072 #define DEFAULT_NODE_HSPACING 45 00073 00074 #define DEFAULT_PROXIMITY_WIDTH 1000 00075 #define DEFAULT_PROXIMITY_HEIGHT 800 00076 00077 #define MINIMUM_PROXIMITY_WIDTH 250 00078 #define MINIMUM_PROXIMITY_HEIGHT 200 00079 00080 #define COORDS_WARNING_WIDTH 650 00081 #define COORDS_WARNING_HEIGHT 60 00082 00083 #define CIRCULAR_DRAWING_RADIUS 100 00084 00085 #define LAYOUT_USER_SUPPLIED 0 00086 #define LAYOUT_SUBLAYERS 1 00087 #define LAYOUT_COLLAPSED_TREE 2 00088 #define LAYOUT_BALANCED_TREE 3 00089 #define LAYOUT_CIRCULAR 4 00090 #define LAYOUT_CIRCULAR_MARKUP 5 00091 #define LAYOUT_CIRCULAR_BALLOON 6 00092 00093 00094 typedef struct layer_struct{ 00095 char *layer_name; 00096 struct layer_struct *next; 00097 }layer; 00098 00099 int process_cgivars(void); 00100 00101 void display_page_header(void); 00102 void display_map(void); 00103 void calculate_host_coords(void); 00104 void calculate_total_image_bounds(void); 00105 void calculate_canvas_bounds(void); 00106 void calculate_canvas_bounds_from_host(char *); 00107 void calculate_scaling_factor(void); 00108 void find_eligible_hosts(void); 00109 void load_background_image(void); 00110 void draw_background_image(void); 00111 void draw_background_extras(void); 00112 void draw_host_links(void); 00113 void draw_hosts(void); 00114 void draw_host_text(char *,int,int); 00115 void draw_text(char *,int,int,int); 00116 void write_host_popup_text(host *); 00117 00118 int initialize_graphics(void); 00119 gdImagePtr load_image_from_file(char *); 00120 void write_graphics(void); 00121 void cleanup_graphics(void); 00122 void draw_line(int,int,int,int,int); 00123 void draw_dotted_line(int,int,int,int,int); 00124 void draw_dashed_line(int,int,int,int,int); 00125 00126 int is_host_in_layer_list(host *); 00127 int add_layer(char *); 00128 void free_layer_list(void); 00129 void print_layer_url(int); 00130 00131 int number_of_host_layer_members(host *,int); 00132 int max_child_host_layer_members(host *); 00133 int host_child_depth_separation(host *, host *); 00134 int max_child_host_drawing_width(host *); 00135 int number_of_host_services(host *); 00136 00137 void calculate_balanced_tree_coords(host *,int,int); 00138 void calculate_circular_coords(void); 00139 void calculate_circular_layer_coords(host *,double,double,int,int); 00140 00141 void draw_circular_markup(void); 00142 void draw_circular_layer_markup(host *,double,double,int,int); 00143 00144 00145 char physical_logo_images_path[MAX_FILENAME_LENGTH]; 00146 00147 authdata current_authdata; 00148 00149 extern int content_type; 00150 00151 gdImagePtr unknown_logo_image=NULL; 00152 gdImagePtr logo_image=NULL; 00153 gdImagePtr map_image=NULL; 00154 gdImagePtr background_image=NULL; 00155 int color_white=0; 00156 int color_black=0; 00157 int color_red=0; 00158 int color_lightred=0; 00159 int color_green=0; 00160 int color_lightgreen=0; 00161 int color_blue=0; 00162 int color_yellow=0; 00163 int color_orange=0; 00164 int color_grey=0; 00165 int color_lightgrey=0; 00166 int color_transparency_index=0; 00167 extern int color_transparency_index_r; 00168 extern int color_transparency_index_g; 00169 extern int color_transparency_index_b; 00170 00171 extern int embedded; 00172 extern int refresh; 00173 extern int display_header; 00174 extern int daemon_check; 00175 00176 int display_popups=TRUE; 00177 int use_links=TRUE; 00178 int use_text=TRUE; 00179 int use_highlights=TRUE; 00180 int user_supplied_canvas=FALSE; 00181 int user_supplied_scaling=FALSE; 00182 00183 int layout_method=LAYOUT_USER_SUPPLIED; 00184 00185 int proximity_width=DEFAULT_PROXIMITY_WIDTH; 00186 int proximity_height=DEFAULT_PROXIMITY_HEIGHT; 00187 00188 int coordinates_were_specified=FALSE; /* were any coordinates specified in extended host information entries? */ 00189 00190 int scaled_image_width=0; /* size of the image actually displayed on the screen (after scaling) */ 00191 int scaled_image_height=0; 00192 int canvas_width=0; /* actual size of the image (or portion thereof) that we are drawing */ 00193 int canvas_height=0; 00194 int total_image_width=0; /* actual size of the image that would be created if we drew all hosts */ 00195 int total_image_height=0; 00196 int max_image_width=0; /* max image size the user wants (scaled) */ 00197 int max_image_height=0; 00198 double scaling_factor=1.0; /* scaling factor to use */ 00199 double user_scaling_factor=1.0; /* user-supplied scaling factor */ 00200 int background_image_width=0; 00201 int background_image_height=0; 00202 00203 int canvas_x=0; /* upper left coords of drawing canvas */ 00204 int canvas_y=0; 00205 00206 int bottom_margin=0; 00207 00208 int draw_child_links=FALSE; 00209 int draw_parent_links=FALSE; 00210 00211 int draw_nagios_icon=FALSE; /* should we drawn the Icinga process icon? */ 00212 int nagios_icon_x=0; /* coords of Icinga icon */ 00213 int nagios_icon_y=0; 00214 00215 extern hoststatus *hoststatus_list; 00216 00217 extern time_t program_start; 00218 00219 layer *layer_list=NULL; 00220 int exclude_layers=TRUE; 00221 int all_layers=FALSE; 00222 00223 int display_type=DISPLAY_HOSTS; 00224 int show_all_hosts=TRUE; 00225 int show_all_hostgroups=TRUE; 00226 int show_all_servicegroups=TRUE; 00227 00228 char *host_name="all"; 00229 char *host_filter=NULL; 00230 char *hostgroup_name=NULL; 00231 char *servicegroup_name=NULL; 00232 char *service_desc=NULL; 00233 char *service_filter=NULL; 00234 00235 int CGI_ID=STATUSMAP_CGI_ID; 00236 00237 int main(int argc, char **argv){ 00238 int result; 00239 00240 mac = get_global_macros(); 00241 00242 /* reset internal variables */ 00243 reset_cgi_vars(); 00244 00245 /* read the CGI configuration file */ 00246 result=read_cgi_config_file(get_cgi_config_location()); 00247 if(result==ERROR){ 00248 document_header(CGI_ID,FALSE); 00249 if(content_type==HTML_CONTENT) 00250 print_error(get_cgi_config_location(), ERROR_CGI_CFG_FILE); 00251 document_footer(CGI_ID); 00252 return ERROR; 00253 } 00254 00255 /* defaults from CGI config file */ 00256 layout_method=default_statusmap_layout_method; 00257 00258 /* get the arguments passed in the URL */ 00259 process_cgivars(); 00260 00261 /* read the main configuration file */ 00262 result=read_main_config_file(main_config_file); 00263 if(result==ERROR){ 00264 document_header(CGI_ID,FALSE); 00265 if(content_type==HTML_CONTENT) 00266 print_error(main_config_file, ERROR_CGI_MAIN_CFG); 00267 document_footer(CGI_ID); 00268 return ERROR; 00269 } 00270 00271 /* read all object configuration data */ 00272 result=read_all_object_configuration_data(main_config_file,READ_ALL_OBJECT_DATA); 00273 if(result==ERROR){ 00274 document_header(CGI_ID,FALSE); 00275 if(content_type==HTML_CONTENT) 00276 print_error(NULL, ERROR_CGI_OBJECT_DATA); 00277 document_footer(CGI_ID); 00278 return ERROR; 00279 } 00280 00281 /* read all status data */ 00282 result=read_all_status_data(get_cgi_config_location(),READ_ALL_STATUS_DATA); 00283 if(result==ERROR && daemon_check==TRUE){ 00284 document_header(CGI_ID,FALSE); 00285 if(content_type==HTML_CONTENT) 00286 print_error(NULL, ERROR_CGI_STATUS_DATA); 00287 document_footer(CGI_ID); 00288 free_memory(); 00289 return ERROR; 00290 } 00291 00292 /* initialize macros */ 00293 init_macros(); 00294 00295 00296 document_header(CGI_ID,TRUE); 00297 00298 /* get authentication information */ 00299 get_authentication_information(¤t_authdata); 00300 00301 /* display the network map... */ 00302 display_map(); 00303 00304 document_footer(CGI_ID); 00305 00306 /* free all allocated memory */ 00307 free_memory(); 00308 free_layer_list(); 00309 00310 return OK; 00311 } 00312 00313 int process_cgivars(void){ 00314 char **variables; 00315 int error=FALSE; 00316 int x; 00317 00318 variables=getcgivars(); 00319 00320 for(x=0;variables[x]!=NULL;x++){ 00321 00322 /* do some basic length checking on the variable identifier to prevent buffer overflows */ 00323 if(strlen(variables[x])>=MAX_INPUT_BUFFER-1){ 00324 x++; 00325 continue; 00326 } 00327 00328 /* we found the host argument */ 00329 else if(!strcmp(variables[x],"host")){ 00330 x++; 00331 if(variables[x]==NULL){ 00332 error=TRUE; 00333 break; 00334 } 00335 00336 if((host_name=(char *)strdup(variables[x]))==NULL) 00337 host_name="all"; 00338 else 00339 strip_html_brackets(host_name); 00340 00341 if(!strcmp(host_name,"all")) 00342 show_all_hosts=TRUE; 00343 else 00344 show_all_hosts=FALSE; 00345 } 00346 00347 /* we found the image creation option */ 00348 else if(!strcmp(variables[x],"createimage")){ 00349 content_type=IMAGE_CONTENT; 00350 } 00351 00352 /* we found the embed option */ 00353 else if(!strcmp(variables[x],"embedded")) 00354 embedded=TRUE; 00355 00356 /* we found the noheader option */ 00357 else if(!strcmp(variables[x],"noheader")) 00358 display_header=FALSE; 00359 00360 /* we found the canvas origin */ 00361 else if(!strcmp(variables[x],"canvas_x")){ 00362 x++; 00363 if(variables[x]==NULL){ 00364 error=TRUE; 00365 break; 00366 } 00367 canvas_x=atoi(variables[x]); 00368 user_supplied_canvas=TRUE; 00369 } 00370 else if(!strcmp(variables[x],"canvas_y")){ 00371 x++; 00372 if(variables[x]==NULL){ 00373 error=TRUE; 00374 break; 00375 } 00376 canvas_y=atoi(variables[x]); 00377 user_supplied_canvas=TRUE; 00378 } 00379 00380 /* we found the canvas size */ 00381 else if(!strcmp(variables[x],"canvas_width")){ 00382 x++; 00383 if(variables[x]==NULL){ 00384 error=TRUE; 00385 break; 00386 } 00387 canvas_width=atoi(variables[x]); 00388 user_supplied_canvas=TRUE; 00389 } 00390 else if(!strcmp(variables[x],"canvas_height")){ 00391 x++; 00392 if(variables[x]==NULL){ 00393 error=TRUE; 00394 break; 00395 } 00396 canvas_height=atoi(variables[x]); 00397 user_supplied_canvas=TRUE; 00398 } 00399 else if(!strcmp(variables[x],"proximity_width")){ 00400 x++; 00401 if(variables[x]==NULL){ 00402 error=TRUE; 00403 break; 00404 } 00405 proximity_width=atoi(variables[x]); 00406 if(proximity_width<0) 00407 proximity_width=DEFAULT_PROXIMITY_WIDTH; 00408 } 00409 else if(!strcmp(variables[x],"proximity_height")){ 00410 x++; 00411 if(variables[x]==NULL){ 00412 error=TRUE; 00413 break; 00414 } 00415 proximity_height=atoi(variables[x]); 00416 if(proximity_height<0) 00417 proximity_height=DEFAULT_PROXIMITY_HEIGHT; 00418 } 00419 00420 /* we found the scaling factor */ 00421 else if(!strcmp(variables[x],"scaling_factor")){ 00422 x++; 00423 if(variables[x]==NULL){ 00424 error=TRUE; 00425 break; 00426 } 00427 user_scaling_factor=strtod(variables[x],NULL); 00428 if(user_scaling_factor>0.0) 00429 user_supplied_scaling=TRUE; 00430 } 00431 00432 /* we found the max image size */ 00433 else if(!strcmp(variables[x],"max_width")){ 00434 x++; 00435 if(variables[x]==NULL){ 00436 error=TRUE; 00437 break; 00438 } 00439 max_image_width=atoi(variables[x]); 00440 } 00441 else if(!strcmp(variables[x],"max_height")){ 00442 x++; 00443 if(variables[x]==NULL){ 00444 error=TRUE; 00445 break; 00446 } 00447 max_image_height=atoi(variables[x]); 00448 } 00449 00450 /* we found the layout method option */ 00451 else if(!strcmp(variables[x],"layout")){ 00452 x++; 00453 if(variables[x]==NULL){ 00454 error=TRUE; 00455 break; 00456 } 00457 layout_method=atoi(variables[x]); 00458 } 00459 00460 /* we found the no links argument*/ 00461 else if(!strcmp(variables[x],"nolinks")) 00462 use_links=FALSE; 00463 00464 /* we found the no text argument*/ 00465 else if(!strcmp(variables[x],"notext")) 00466 use_text=FALSE; 00467 00468 /* we found the no highlights argument*/ 00469 else if(!strcmp(variables[x],"nohighlights")) 00470 use_highlights=FALSE; 00471 00472 /* we found the no popups argument*/ 00473 else if(!strcmp(variables[x],"nopopups")) 00474 display_popups=FALSE; 00475 00476 /* we found the layer inclusion/exclusion argument */ 00477 else if(!strcmp(variables[x],"layermode")){ 00478 x++; 00479 if(variables[x]==NULL){ 00480 error=TRUE; 00481 break; 00482 } 00483 00484 if(!strcmp(variables[x],"include")) 00485 exclude_layers=FALSE; 00486 else 00487 exclude_layers=TRUE; 00488 } 00489 00490 /* we found the layer argument */ 00491 else if(!strcmp(variables[x],"layer")){ 00492 x++; 00493 if(variables[x]==NULL){ 00494 error=TRUE; 00495 break; 00496 } 00497 00498 strip_html_brackets(variables[x]); 00499 add_layer(variables[x]); 00500 } 00501 00502 /* we found the pause option */ 00503 else if(!strcmp(variables[x],"paused")) 00504 refresh=FALSE; 00505 00506 /* we found the nodaemoncheck option */ 00507 else if(!strcmp(variables[x],"nodaemoncheck")) 00508 daemon_check=FALSE; 00509 00510 } 00511 00512 /* free memory allocated to the CGI variables */ 00513 free_cgivars(variables); 00514 00515 return error; 00516 } 00517 00518 00519 00520 /* top of page */ 00521 void display_page_header(void){ 00522 char temp_buffer[MAX_INPUT_BUFFER]; 00523 int zoom; 00524 int zoom_width, zoom_height; 00525 int zoom_width_granularity=0; 00526 int zoom_height_granularity=0; 00527 int current_zoom_granularity=0; 00528 hostgroup *temp_hostgroup; 00529 layer *temp_layer; 00530 int found=0; 00531 00532 00533 if(content_type!=HTML_CONTENT) 00534 return; 00535 00536 if(display_header==TRUE){ 00537 00538 /* begin top table */ 00539 printf("<table border=0 width=100%% cellspacing=0 cellpadding=0>\n"); 00540 printf("<tr>\n"); 00541 00542 /* left column of the first row */ 00543 printf("<td align=left valign=top>\n"); 00544 00545 if(show_all_hosts==TRUE) 00546 snprintf(temp_buffer,sizeof(temp_buffer)-1,"Network Map For All Hosts"); 00547 else 00548 snprintf(temp_buffer,sizeof(temp_buffer)-1,"Network Map For Host <I>%s</I>",host_name); 00549 temp_buffer[sizeof(temp_buffer)-1]='\x0'; 00550 display_info_table(temp_buffer,refresh,¤t_authdata, daemon_check); 00551 00552 printf("<TABLE BORDER=1 CELLPADDING=0 CELLSPACING=0 CLASS='linkBox'>\n"); 00553 printf("<TR><TD CLASS='linkBox'>\n"); 00554 00555 if(show_all_hosts==FALSE){ 00556 printf("<a href='%s?host=all&max_width=%d&max_height=%d'>View Status Map For All Hosts</a><BR>",STATUSMAP_CGI,max_image_width,max_image_height); 00557 printf("<a href='%s?host=%s'>View Status Detail For This Host</a><BR>\n",STATUS_CGI,url_encode(host_name)); 00558 } 00559 printf("<a href='%s?host=all'>View Status Detail For All Hosts</a><BR>\n",STATUS_CGI); 00560 printf("<a href='%s?hostgroup=all'>View Status Overview For All Hosts</a>\n",STATUS_CGI); 00561 00562 printf("</TD></TR>\n"); 00563 printf("</TABLE>\n"); 00564 00565 printf("</td>\n"); 00566 00567 00568 00569 /* center column of top row */ 00570 printf("<td align=center valign=center>\n"); 00571 00572 /* print image size and scaling info */ 00573 #ifdef DEBUG 00574 printf("<p><div align=center><font size=-1>\n"); 00575 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)); 00576 printf("</font></div></p>\n"); 00577 00578 printf("<p><div align=center><font size=-1>\n"); 00579 printf("[ Canvas_x: %d | Canvas_y: %d | Canvas_width: %d | Canvas_height: %d ]",canvas_x,canvas_y,canvas_width,canvas_height); 00580 printf("</font></div></p>\n"); 00581 #endif 00582 00583 /* zoom links */ 00584 if(user_supplied_canvas==FALSE && strcmp(host_name,"all") && display_header==TRUE){ 00585 00586 printf("<p><div align=center>\n"); 00587 00588 zoom_width_granularity=((total_image_width-MINIMUM_PROXIMITY_WIDTH)/11); 00589 if(zoom_width_granularity==0) 00590 zoom_width_granularity=1; 00591 zoom_height_granularity=((total_image_height-MINIMUM_PROXIMITY_HEIGHT)/11); 00592 00593 if(proximity_width<=0) 00594 current_zoom_granularity=0; 00595 else 00596 current_zoom_granularity=(total_image_width-proximity_width)/zoom_width_granularity; 00597 if(current_zoom_granularity>10) 00598 current_zoom_granularity=10; 00599 00600 printf("<table border=0 cellpadding=0 cellspacing=2>\n"); 00601 printf("<tr>\n"); 00602 printf("<td valign=center class='zoomTitle'>Zoom Out </td>\n"); 00603 00604 for(zoom=0;zoom<=10;zoom++){ 00605 00606 zoom_width=total_image_width-(zoom*zoom_width_granularity); 00607 zoom_height=total_image_height-(zoom*zoom_height_granularity); 00608 00609 printf("<td valign=center><a href='%s?host=%s&layout=%d&max_width=%d&max_height=%d&proximity_width=%d&proximity_height=%d%s%s",STATUSMAP_CGI,url_encode(host_name),layout_method,max_image_width,max_image_height,zoom_width,zoom_height,(display_header==TRUE)?"":"&noheader",(display_popups==FALSE)?"&nopopups":""); 00610 if(user_supplied_scaling==TRUE) 00611 printf("&scaling_factor=%2.1f",user_scaling_factor); 00612 print_layer_url(TRUE); 00613 printf("'>"); 00614 printf("<img src='%s%s' border=0 alt='%d' title='%d'></a></td>\n",url_images_path,(current_zoom_granularity==zoom)?ZOOM2_ICON:ZOOM1_ICON,zoom,zoom); 00615 } 00616 00617 printf("<td valign=center class='zoomTitle'> Zoom In</td>\n"); 00618 printf("</tr>\n"); 00619 printf("</table>\n"); 00620 00621 printf("</div></p>\n"); 00622 } 00623 00624 printf("</td>\n"); 00625 00626 00627 00628 /* right hand column of top row */ 00629 printf("<td align=right valign=top>\n"); 00630 00631 printf("<form method=\"POST\" action=\"%s\">\n",STATUSMAP_CGI); 00632 printf("<table border=0 CLASS='optBox'>\n"); 00633 printf("<tr><td valign=top>\n"); 00634 printf("<input type='hidden' name='host' value='%s'>\n",escape_string(host_name)); 00635 printf("<input type='hidden' name='layout' value='%d'>\n",layout_method); 00636 00637 printf("</td><td valign=top>\n"); 00638 00639 printf("<table border=0>\n"); 00640 00641 printf("<tr><td CLASS='optBoxItem'>\n"); 00642 printf("Layout Method:<br>\n"); 00643 printf("<select name='layout'>\n"); 00644 #ifndef DUMMY_INSTALL 00645 printf("<option value=%d %s>User-supplied coords\n",LAYOUT_USER_SUPPLIED,(layout_method==LAYOUT_USER_SUPPLIED)?"selected":""); 00646 #endif 00647 printf("<option value=%d %s>Depth layers\n",LAYOUT_SUBLAYERS,(layout_method==LAYOUT_SUBLAYERS)?"selected":""); 00648 printf("<option value=%d %s>Collapsed tree\n",LAYOUT_COLLAPSED_TREE,(layout_method==LAYOUT_COLLAPSED_TREE)?"selected":""); 00649 printf("<option value=%d %s>Balanced tree\n",LAYOUT_BALANCED_TREE,(layout_method==LAYOUT_BALANCED_TREE)?"selected":""); 00650 printf("<option value=%d %s>Circular\n",LAYOUT_CIRCULAR,(layout_method==LAYOUT_CIRCULAR)?"selected":""); 00651 printf("<option value=%d %s>Circular (Marked Up)\n",LAYOUT_CIRCULAR_MARKUP,(layout_method==LAYOUT_CIRCULAR_MARKUP)?"selected":""); 00652 printf("<option value=%d %s>Circular (Balloon)\n",LAYOUT_CIRCULAR_BALLOON,(layout_method==LAYOUT_CIRCULAR_BALLOON)?"selected":""); 00653 printf("</select>\n"); 00654 printf("</td>\n"); 00655 printf("<td CLASS='optBoxItem'>\n"); 00656 printf("Scaling factor:<br>\n"); 00657 printf("<input type='text' name='scaling_factor' maxlength='5' size='4' value='%2.1f'>\n",(user_supplied_scaling==TRUE)?user_scaling_factor:0.0); 00658 printf("</td></tr>\n"); 00659 00660 /* 00661 printf("<tr><td CLASS='optBoxItem'>\n"); 00662 printf("Max image width:<br>\n"); 00663 printf("<input type='text' name='max_width' maxlength='5' size='4' value='%d'>\n",max_image_width); 00664 printf("</td>\n"); 00665 printf("<td CLASS='optBoxItem'>\n"); 00666 printf("Max image height:<br>\n"); 00667 printf("<input type='text' name='max_height' maxlength='5' size='4' value='%d'>\n",max_image_height); 00668 printf("</td></tr>\n"); 00669 00670 printf("<tr><td CLASS='optBoxItem'>\n"); 00671 printf("Proximity width:<br>\n"); 00672 printf("<input type='text' name='proximity_width' maxlength='5' size='4' value='%d'>\n",proximity_width); 00673 printf("</td>\n"); 00674 printf("<td CLASS='optBoxItem'>\n"); 00675 printf("Proximity height:<br>\n"); 00676 printf("<input type='text' name='proximity_height' maxlength='5' size='4' value='%d'>\n",proximity_height); 00677 printf("</td></tr>\n"); 00678 */ 00679 00680 printf("<input type='hidden' name='max_width' value='%d'>\n",max_image_width); 00681 printf("<input type='hidden' name='max_height' value='%d'>\n",max_image_height); 00682 printf("<input type='hidden' name='proximity_width' value='%d'>\n",proximity_width); 00683 printf("<input type='hidden' name='proximity_height' value='%d'>\n",proximity_height); 00684 00685 printf("<tr><td CLASS='optBoxItem'>Drawing Layers:<br>\n"); 00686 printf("<select multiple name='layer' size='4'>\n"); 00687 for(temp_hostgroup=hostgroup_list;temp_hostgroup!=NULL;temp_hostgroup=temp_hostgroup->next){ 00688 if(is_authorized_for_hostgroup(temp_hostgroup,¤t_authdata)==FALSE) 00689 continue; 00690 found=0; 00691 for(temp_layer=layer_list;temp_layer!=NULL;temp_layer=temp_layer->next){ 00692 if(!strcmp(temp_layer->layer_name,temp_hostgroup->group_name)){ 00693 found=1; 00694 break; 00695 } 00696 } 00697 printf("<option value='%s' %s>%s\n",escape_string(temp_hostgroup->group_name),(found==1)?"SELECTED":"",temp_hostgroup->alias); 00698 } 00699 printf("</select>\n"); 00700 printf("</td><td CLASS='optBoxItem' valign=top>Layer mode:<br>"); 00701 printf("<input type='radio' name='layermode' value='include' %s>Include<br>\n",(exclude_layers==FALSE)?"CHECKED":""); 00702 printf("<input type='radio' name='layermode' value='exclude' %s>Exclude\n",(exclude_layers==TRUE)?"CHECKED":""); 00703 printf("</td></tr>\n"); 00704 00705 printf("<tr><td CLASS='optBoxItem'>\n"); 00706 printf("Suppress popups:<br>\n"); 00707 printf("<input type='checkbox' name='nopopups' %s>\n",(display_popups==FALSE)?"CHECKED":""); 00708 printf("</td><td CLASS='optBoxItem'>\n"); 00709 printf("<input type='submit' value='Update'>\n"); 00710 printf("</td></tr>\n"); 00711 00712 /* display context-sensitive help */ 00713 printf("<tr><td></td><td align=right valign=bottom>\n"); 00714 display_context_help(CONTEXTHELP_MAP); 00715 printf("</td></tr>\n"); 00716 00717 printf("</table>\n"); 00718 00719 printf("</td></tr>\n"); 00720 printf("</table>\n"); 00721 printf("</form>\n"); 00722 00723 printf("</td>\n"); 00724 00725 /* end of top table */ 00726 printf("</tr>\n"); 00727 printf("</table>\n"); 00728 } 00729 00730 00731 return; 00732 } 00733 00734 00735 00736 /* top-level map generation... */ 00737 void display_map(void){ 00738 00739 load_background_image(); 00740 calculate_host_coords(); 00741 calculate_total_image_bounds(); 00742 calculate_canvas_bounds(); 00743 calculate_scaling_factor(); 00744 find_eligible_hosts(); 00745 00746 /* display page header */ 00747 display_page_header(); 00748 00749 initialize_graphics(); 00750 draw_background_image(); 00751 draw_background_extras(); 00752 draw_host_links(); 00753 00754 if(content_type==HTML_CONTENT) 00755 printf("<map name='statusmap'>\n"); 00756 00757 draw_hosts(); 00758 00759 if(content_type==HTML_CONTENT) 00760 printf("</map>\n"); 00761 00762 write_graphics(); 00763 cleanup_graphics(); 00764 00765 00766 /* write the URL location for the image we just generated - the web browser will come and get it... */ 00767 if(content_type==HTML_CONTENT){ 00768 printf("<P><DIV ALIGN=center>\n"); 00769 printf("<img src='%s?host=%s&createimage&time=%lu",STATUSMAP_CGI,url_encode(host_name),(unsigned long)time(NULL)); 00770 printf("&canvas_x=%d&canvas_y=%d&canvas_width=%d&canvas_height=%d&max_width=%d&max_height=%d&layout=%d%s%s%s",canvas_x,canvas_y,canvas_width,canvas_height,max_image_width,max_image_height,layout_method,(use_links==FALSE)?"&nolinks":"",(use_text==FALSE)?"¬ext":"",(use_highlights==FALSE)?"&nohighlights":""); 00771 print_layer_url(TRUE); 00772 printf("' width=%d height=%d border=0 name='statusimage' useMap='#statusmap'>\n",(int)(canvas_width*scaling_factor),(int)(canvas_height*scaling_factor)); 00773 printf("</DIV></P>\n"); 00774 } 00775 00776 return; 00777 } 00778 00779 00780 00781 /******************************************************************/ 00782 /********************* CALCULATION FUNCTIONS **********************/ 00783 /******************************************************************/ 00784 00785 /* calculates host drawing coordinates */ 00786 void calculate_host_coords(void){ 00787 host *this_host; 00788 host *temp_host; 00789 int child_hosts=0; 00790 int parent_hosts=0; 00791 int max_layer_width=1; 00792 int current_child_host=0; 00793 int current_parent_host=0; 00794 int center_x=0; 00795 int offset_x=DEFAULT_NODE_WIDTH/2; 00796 int offset_y=DEFAULT_NODE_WIDTH/2; 00797 int current_layer=0; 00798 int layer_members=0; 00799 int current_layer_member=0; 00800 int max_drawing_width=0; 00801 00802 00803 /******************************/ 00804 /***** MANUAL LAYOUT MODE *****/ 00805 /******************************/ 00806 00807 /* user-supplied coords */ 00808 if(layout_method==LAYOUT_USER_SUPPLIED){ 00809 00810 /* see which hosts we should draw and calculate drawing coords */ 00811 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 00812 00813 if(temp_host->have_2d_coords==TRUE) 00814 temp_host->should_be_drawn=TRUE; 00815 else 00816 temp_host->should_be_drawn=FALSE; 00817 } 00818 00819 return; 00820 } 00821 00822 00823 /*****************************/ 00824 /***** AUTO-LAYOUT MODES *****/ 00825 /*****************************/ 00826 00827 /***** DEPTH LAYER MODE *****/ 00828 if(layout_method==LAYOUT_SUBLAYERS){ 00829 00830 /* find the "main" host we're displaying */ 00831 if(show_all_hosts==TRUE) 00832 this_host=NULL; 00833 else 00834 this_host=find_host(host_name); 00835 00836 /* find total number of immediate parents/children for this host */ 00837 child_hosts=number_of_immediate_child_hosts(this_host); 00838 parent_hosts=number_of_immediate_parent_hosts(this_host); 00839 00840 if(child_hosts==0 && parent_hosts==0) 00841 max_layer_width=1; 00842 else 00843 max_layer_width=(child_hosts>parent_hosts)?child_hosts:parent_hosts; 00844 00845 /* calculate center x coord */ 00846 center_x=(((DEFAULT_NODE_WIDTH*max_layer_width)+(DEFAULT_NODE_HSPACING*(max_layer_width-1)))/2)+offset_x; 00847 00848 /* coords for Icinga icon if necessary */ 00849 if(this_host==NULL || this_host->parent_hosts==NULL){ 00850 nagios_icon_x=center_x; 00851 nagios_icon_y=offset_y; 00852 draw_nagios_icon=TRUE; 00853 } 00854 00855 /* do we need to draw a link to parent(s)? */ 00856 if(this_host!=NULL && is_host_immediate_child_of_host(NULL,this_host)==FALSE){ 00857 draw_parent_links=TRUE; 00858 offset_y+=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING; 00859 } 00860 00861 /* see which hosts we should draw and calculate drawing coords */ 00862 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 00863 00864 /* this is an immediate parent of the "main" host we're drawing */ 00865 if(is_host_immediate_parent_of_host(this_host,temp_host)==TRUE){ 00866 temp_host->should_be_drawn=TRUE; 00867 temp_host->have_2d_coords=TRUE; 00868 temp_host->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); 00869 temp_host->y_2d=offset_y; 00870 current_parent_host++; 00871 } 00872 00873 /* this is the "main" host we're drawing */ 00874 else if(this_host==temp_host){ 00875 temp_host->should_be_drawn=TRUE; 00876 temp_host->have_2d_coords=TRUE; 00877 temp_host->x_2d=center_x; 00878 temp_host->y_2d=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y; 00879 } 00880 00881 /* this is an immediate child of the "main" host we're drawing */ 00882 else if(is_host_immediate_child_of_host(this_host,temp_host)==TRUE){ 00883 temp_host->should_be_drawn=TRUE; 00884 temp_host->have_2d_coords=TRUE; 00885 temp_host->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); 00886 if(this_host==NULL) 00887 temp_host->y_2d=(DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)+offset_y; 00888 else 00889 temp_host->y_2d=((DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)*2)+offset_y; 00890 current_child_host++; 00891 if(number_of_immediate_child_hosts(temp_host)>0){ 00892 bottom_margin=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING; 00893 draw_child_links=TRUE; 00894 } 00895 } 00896 00897 /* else do not draw this host */ 00898 else{ 00899 temp_host->should_be_drawn=FALSE; 00900 temp_host->have_2d_coords=FALSE; 00901 } 00902 } 00903 } 00904 00905 00906 00907 /***** COLLAPSED TREE MODE *****/ 00908 else if(layout_method==LAYOUT_COLLAPSED_TREE){ 00909 00910 /* find the "main" host we're displaying - DO NOT USE THIS (THIS IS THE OLD METHOD) */ 00911 /* 00912 if(show_all_hosts==TRUE) 00913 this_host=NULL; 00914 else 00915 this_host=find_host(host_name); 00916 */ 00917 00918 /* always use NULL as the "main" host, screen coords/dimensions are adjusted automatically */ 00919 this_host=NULL; 00920 00921 /* find total number of immediate parents for this host */ 00922 parent_hosts=number_of_immediate_parent_hosts(this_host); 00923 00924 /* find the max layer width we have... */ 00925 max_layer_width=max_child_host_layer_members(this_host); 00926 if(parent_hosts>max_layer_width) 00927 max_layer_width=parent_hosts; 00928 00929 /* calculate center x coord */ 00930 center_x=(((DEFAULT_NODE_WIDTH*max_layer_width)+(DEFAULT_NODE_HSPACING*(max_layer_width-1)))/2)+offset_x; 00931 00932 /* coords for Icinga icon if necessary */ 00933 if(this_host==NULL || this_host->parent_hosts==NULL){ 00934 nagios_icon_x=center_x; 00935 nagios_icon_y=offset_y; 00936 draw_nagios_icon=TRUE; 00937 } 00938 00939 /* do we need to draw a link to parent(s)? */ 00940 if(this_host!=NULL && is_host_immediate_child_of_host(NULL,this_host)==FALSE){ 00941 draw_parent_links=TRUE; 00942 offset_y+=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING; 00943 } 00944 00945 /* see which hosts we should draw and calculate drawing coords */ 00946 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 00947 00948 /* this is an immediate parent of the "main" host we're drawing */ 00949 if(is_host_immediate_parent_of_host(this_host,temp_host)==TRUE){ 00950 temp_host->should_be_drawn=TRUE; 00951 temp_host->have_2d_coords=TRUE; 00952 temp_host->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); 00953 temp_host->y_2d=offset_y; 00954 current_parent_host++; 00955 } 00956 00957 /* this is the "main" host we're drawing */ 00958 else if(this_host==temp_host){ 00959 temp_host->should_be_drawn=TRUE; 00960 temp_host->have_2d_coords=TRUE; 00961 temp_host->x_2d=center_x; 00962 temp_host->y_2d=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y; 00963 } 00964 00965 /* else do not draw this host (we might if its a child - see below, but assume no for now) */ 00966 else{ 00967 temp_host->should_be_drawn=FALSE; 00968 temp_host->have_2d_coords=FALSE; 00969 } 00970 } 00971 00972 00973 /* TODO: REORDER CHILD LAYER MEMBERS SO THAT WE MINIMIZE LINK CROSSOVERS FROM PARENT HOSTS */ 00974 00975 /* draw hosts in child "layers" */ 00976 for(current_layer=1;;current_layer++){ 00977 00978 /* how many members in this layer? */ 00979 layer_members=number_of_host_layer_members(this_host,current_layer); 00980 00981 if(layer_members==0) 00982 break; 00983 00984 current_layer_member=0; 00985 00986 /* see which hosts are members of this layer and calculate drawing coords */ 00987 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 00988 00989 /* is this host a member of the current child layer? */ 00990 if(host_child_depth_separation(this_host,temp_host)==current_layer){ 00991 temp_host->should_be_drawn=TRUE; 00992 temp_host->have_2d_coords=TRUE; 00993 temp_host->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); 00994 if(this_host==NULL) 00995 temp_host->y_2d=((DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)*current_layer)+offset_y; 00996 else 00997 temp_host->y_2d=((DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING)*(current_layer+1))+offset_y; 00998 current_layer_member++; 00999 } 01000 } 01001 } 01002 01003 } 01004 01005 01006 /***** "BALANCED" TREE MODE *****/ 01007 else if(layout_method==LAYOUT_BALANCED_TREE){ 01008 01009 /* find the "main" host we're displaying - DO NOT USE THIS (THIS IS THE OLD METHOD) */ 01010 /* 01011 if(show_all_hosts==TRUE) 01012 this_host=NULL; 01013 else 01014 this_host=find_host(host_name); 01015 */ 01016 01017 /* always use NULL as the "main" host, screen coords/dimensions are adjusted automatically */ 01018 this_host=NULL; 01019 01020 /* find total number of immediate parents for this host */ 01021 parent_hosts=number_of_immediate_parent_hosts(this_host); 01022 01023 /* find the max drawing width we have... */ 01024 max_drawing_width=max_child_host_drawing_width(this_host); 01025 if(parent_hosts>max_drawing_width) 01026 max_drawing_width=parent_hosts; 01027 01028 /* calculate center x coord */ 01029 center_x=(((DEFAULT_NODE_WIDTH*max_drawing_width)+(DEFAULT_NODE_HSPACING*(max_drawing_width-1)))/2)+offset_x; 01030 01031 /* coords for Icinga icon if necessary */ 01032 if(this_host==NULL || this_host->parent_hosts==NULL){ 01033 nagios_icon_x=center_x; 01034 nagios_icon_y=offset_y; 01035 draw_nagios_icon=TRUE; 01036 } 01037 01038 /* do we need to draw a link to parent(s)? */ 01039 if(this_host!=NULL && is_host_immediate_child_of_host(NULL,this_host)==FALSE){ 01040 draw_parent_links=TRUE; 01041 offset_y+=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING; 01042 } 01043 01044 /* see which hosts we should draw and calculate drawing coords */ 01045 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 01046 01047 /* this is an immediate parent of the "main" host we're drawing */ 01048 if(is_host_immediate_parent_of_host(this_host,temp_host)==TRUE){ 01049 temp_host->should_be_drawn=TRUE; 01050 temp_host->have_2d_coords=TRUE; 01051 temp_host->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); 01052 temp_host->y_2d=offset_y; 01053 current_parent_host++; 01054 } 01055 01056 /* this is the "main" host we're drawing */ 01057 else if(this_host==temp_host){ 01058 temp_host->should_be_drawn=TRUE; 01059 temp_host->have_2d_coords=TRUE; 01060 temp_host->x_2d=center_x; 01061 temp_host->y_2d=DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y; 01062 } 01063 01064 /* else do not draw this host (we might if its a child - see below, but assume no for now) */ 01065 else{ 01066 temp_host->should_be_drawn=FALSE; 01067 temp_host->have_2d_coords=FALSE; 01068 } 01069 } 01070 01071 /* draw all children hosts */ 01072 calculate_balanced_tree_coords(this_host,center_x,DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING+offset_y); 01073 01074 } 01075 01076 01077 /***** CIRCULAR LAYOUT MODE *****/ 01078 else if(layout_method==LAYOUT_CIRCULAR || layout_method==LAYOUT_CIRCULAR_MARKUP || layout_method==LAYOUT_CIRCULAR_BALLOON){ 01079 01080 /* draw process icon */ 01081 nagios_icon_x=0; 01082 nagios_icon_y=0; 01083 draw_nagios_icon=TRUE; 01084 01085 /* calculate coordinates for all hosts */ 01086 calculate_circular_coords(); 01087 } 01088 01089 return; 01090 } 01091 01092 01093 01094 /* calculates max possible image dimensions */ 01095 void calculate_total_image_bounds(void){ 01096 host *temp_host; 01097 01098 total_image_width=0; 01099 total_image_height=0; 01100 01101 /* check all extended host information entries... */ 01102 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 01103 01104 /* only check entries that have 2-D coords specified */ 01105 if(temp_host->have_2d_coords==FALSE) 01106 continue; 01107 01108 /* skip hosts we shouldn't be drawing */ 01109 if(temp_host->should_be_drawn==FALSE) 01110 continue; 01111 01112 if(temp_host->x_2d>total_image_width) 01113 total_image_width=temp_host->x_2d; 01114 if(temp_host->y_2d>total_image_height) 01115 total_image_height=temp_host->y_2d; 01116 01117 coordinates_were_specified=TRUE; 01118 } 01119 01120 /* add some space for icon size and overlapping text... */ 01121 if(coordinates_were_specified==TRUE){ 01122 01123 total_image_width+=(DEFAULT_NODE_WIDTH*2); 01124 total_image_height+=DEFAULT_NODE_HEIGHT; 01125 01126 /* add space for bottom margin if necessary */ 01127 total_image_height+=bottom_margin; 01128 } 01129 01130 /* image size should be at least as large as dimensions of background image */ 01131 if(total_image_width<background_image_width) 01132 total_image_width=background_image_width; 01133 if(total_image_height<background_image_height) 01134 total_image_height=background_image_height; 01135 01136 /* we didn't find any hosts that had user-supplied coordinates, so we're going to display a warning */ 01137 if(coordinates_were_specified==FALSE){ 01138 coordinates_were_specified=FALSE; 01139 total_image_width=COORDS_WARNING_WIDTH; 01140 total_image_height=COORDS_WARNING_HEIGHT; 01141 } 01142 01143 return; 01144 } 01145 01146 01147 /* calculates canvas coordinates/dimensions */ 01148 void calculate_canvas_bounds(void){ 01149 01150 if(user_supplied_canvas==FALSE && strcmp(host_name,"all")) 01151 calculate_canvas_bounds_from_host(host_name); 01152 01153 /* calculate canvas origin (based on total image bounds) */ 01154 if(canvas_x<=0 || canvas_width>total_image_width) 01155 canvas_x=0; 01156 if(canvas_y<=0 || canvas_height>total_image_height) 01157 canvas_y=0; 01158 01159 /* calculate canvas dimensions */ 01160 if(canvas_height<=0) 01161 canvas_height=(total_image_height-canvas_y); 01162 if(canvas_width<=0) 01163 canvas_width=(total_image_width-canvas_x); 01164 01165 if(canvas_x+canvas_width>total_image_width) 01166 canvas_width=total_image_width-canvas_x; 01167 if(canvas_y+canvas_height>total_image_height) 01168 canvas_height=total_image_height-canvas_y; 01169 01170 return; 01171 } 01172 01173 01174 /* calculates canvas coordinates/dimensions around a particular host */ 01175 void calculate_canvas_bounds_from_host(char *host_name){ 01176 host *temp_host; 01177 int zoom_width; 01178 int zoom_height; 01179 01180 /* find the extended host info */ 01181 temp_host=find_host(host_name); 01182 if(temp_host==NULL) 01183 return; 01184 01185 /* make sure we have 2-D coords */ 01186 if(temp_host->have_2d_coords==FALSE) 01187 return; 01188 01189 if(max_image_width>0 && proximity_width>max_image_width) 01190 zoom_width=max_image_width; 01191 else 01192 zoom_width=proximity_width; 01193 if(max_image_height>0 && proximity_height>max_image_height) 01194 zoom_height=max_image_height; 01195 else 01196 zoom_height=proximity_height; 01197 01198 canvas_width=zoom_width; 01199 if(canvas_width>=total_image_width) 01200 canvas_x=0; 01201 else 01202 canvas_x=(temp_host->x_2d-(zoom_width/2)); 01203 01204 canvas_height=zoom_height; 01205 if(canvas_height>=total_image_height) 01206 canvas_y=0; 01207 else 01208 canvas_y=(temp_host->y_2d-(zoom_height/2)); 01209 01210 01211 return; 01212 } 01213 01214 01215 /* calculates scaling factor used in image generation */ 01216 void calculate_scaling_factor(void){ 01217 double x_scaling=1.0; 01218 double y_scaling=1.0; 01219 01220 /* calculate horizontal scaling factor */ 01221 if(max_image_width<=0 || canvas_width<=max_image_width) 01222 x_scaling=1.0; 01223 else 01224 x_scaling=(double)((double)max_image_width/(double)canvas_width); 01225 01226 /* calculate vertical scaling factor */ 01227 if(max_image_height<=0 || canvas_height<=max_image_height) 01228 y_scaling=1.0; 01229 else 01230 y_scaling=(double)((double)max_image_height/(double)canvas_height); 01231 01232 /* calculate general scaling factor to use */ 01233 if(x_scaling<y_scaling) 01234 scaling_factor=x_scaling; 01235 else 01236 scaling_factor=y_scaling; 01237 01238 /*** USER-SUPPLIED SCALING FACTOR ***/ 01239 if(user_supplied_scaling==TRUE) 01240 scaling_factor=user_scaling_factor; 01241 01242 return; 01243 } 01244 01245 01246 /* finds hosts that can be drawn in the canvas area */ 01247 void find_eligible_hosts(void){ 01248 int total_eligible_hosts=0; 01249 host *temp_host; 01250 01251 /* check all extended host information entries... */ 01252 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 01253 01254 /* only include hosts that have 2-D coords supplied */ 01255 if(temp_host->have_2d_coords==FALSE) 01256 temp_host->should_be_drawn=FALSE; 01257 01258 /* make sure coords are all positive */ 01259 else if(temp_host->x_2d<0 || temp_host->y_2d<0) 01260 temp_host->should_be_drawn=FALSE; 01261 01262 /* make sure x coordinates fall within canvas bounds */ 01263 else if(temp_host->x_2d<(canvas_x-DEFAULT_NODE_WIDTH) || temp_host->x_2d>(canvas_x+canvas_width)) 01264 temp_host->should_be_drawn=FALSE; 01265 01266 /* make sure y coordinates fall within canvas bounds */ 01267 else if(temp_host->y_2d<(canvas_y-DEFAULT_NODE_HEIGHT) || temp_host->y_2d>(canvas_y+canvas_height)) 01268 temp_host->should_be_drawn=FALSE; 01269 01270 /* see if the user is authorized to view the host */ 01271 else if(is_authorized_for_host(temp_host,¤t_authdata)==FALSE) 01272 temp_host->should_be_drawn=FALSE; 01273 01274 /* all checks passed, so we can draw the host! */ 01275 else{ 01276 temp_host->should_be_drawn=TRUE; 01277 total_eligible_hosts++; 01278 } 01279 } 01280 01281 return; 01282 } 01283 01284 01285 01286 /******************************************************************/ 01287 /*********************** DRAWING FUNCTIONS ************************/ 01288 /******************************************************************/ 01289 01290 01291 /* loads background image from file */ 01292 void load_background_image(void){ 01293 char temp_buffer[MAX_INPUT_BUFFER]; 01294 01295 /* bail out if we shouldn't be drawing a background image */ 01296 if(layout_method!=LAYOUT_USER_SUPPLIED || statusmap_background_image==NULL) 01297 return; 01298 01299 snprintf(temp_buffer,sizeof(temp_buffer)-1,"%s%s",physical_images_path,statusmap_background_image); 01300 temp_buffer[sizeof(temp_buffer)-1]='\x0'; 01301 01302 /* read the background image into memory */ 01303 background_image=load_image_from_file(temp_buffer); 01304 01305 /* grab background image dimensions for calculating total image width later */ 01306 if(background_image!=NULL){ 01307 background_image_width=background_image->sx; 01308 background_image_height=background_image->sy; 01309 } 01310 01311 /* if we are just creating the html, we don't need the image anymore */ 01312 if(content_type==HTML_CONTENT && background_image!=NULL) 01313 gdImageDestroy(background_image); 01314 01315 return; 01316 } 01317 01318 01319 /* draws background image on drawing canvas */ 01320 void draw_background_image(void){ 01321 01322 /* bail out if we shouldn't be drawing a background image */ 01323 if(content_type==HTML_CONTENT || layout_method!=LAYOUT_USER_SUPPLIED || statusmap_background_image==NULL) 01324 return; 01325 01326 /* bail out if we don't have an image */ 01327 if(background_image==NULL) 01328 return; 01329 01330 /* copy the background image to the canvas */ 01331 gdImageCopy(map_image,background_image,0,0,canvas_x,canvas_y,canvas_width,canvas_height); 01332 01333 /* free memory for background image, as we don't need it anymore */ 01334 gdImageDestroy(background_image); 01335 01336 return; 01337 } 01338 01339 01340 01341 /* draws background "extras" */ 01342 void draw_background_extras(void){ 01343 01344 /* bail out if we shouldn't be here */ 01345 if(content_type==HTML_CONTENT) 01346 return; 01347 01348 /* circular layout stuff... */ 01349 if(layout_method==LAYOUT_CIRCULAR_MARKUP){ 01350 01351 /* draw colored sections... */ 01352 draw_circular_markup(); 01353 } 01354 01355 return; 01356 } 01357 01358 01359 /* draws host links */ 01360 void draw_host_links(void){ 01361 host *this_host; 01362 host *main_host; 01363 host *parent_host; 01364 hostsmember *temp_hostsmember; 01365 int status_color=color_black; 01366 hoststatus *this_hoststatus; 01367 hoststatus *parent_hoststatus; 01368 int child_in_layer_list=FALSE; 01369 int parent_in_layer_list=FALSE; 01370 int dotted_line=FALSE; 01371 int x=0; 01372 int y=0; 01373 01374 if(content_type==HTML_CONTENT) 01375 return; 01376 01377 if(use_links==FALSE) 01378 return; 01379 01380 /* find the "main" host we're drawing */ 01381 main_host=find_host(host_name); 01382 if(show_all_hosts==TRUE) 01383 main_host=NULL; 01384 01385 /* check all extended host information entries... */ 01386 for(this_host=host_list;this_host!=NULL;this_host=this_host->next){ 01387 01388 /* only draw link if user is authorized to view this host */ 01389 if(is_authorized_for_host(this_host,¤t_authdata)==FALSE) 01390 continue; 01391 01392 /* this is a "root" host, so draw link to Icinga process icon if using auto-layout mode */ 01393 if(this_host->parent_hosts==NULL && layout_method!=LAYOUT_USER_SUPPLIED && draw_nagios_icon==TRUE){ 01394 01395 x=this_host->x_2d+(DEFAULT_NODE_WIDTH/2)-canvas_x; 01396 y=this_host->y_2d+(DEFAULT_NODE_WIDTH/2)-canvas_y; 01397 01398 draw_line(x,y,nagios_icon_x+(DEFAULT_NODE_WIDTH/2)-canvas_x,nagios_icon_y+(DEFAULT_NODE_WIDTH/2)-canvas_y,color_black); 01399 } 01400 01401 /* this is a child of the main host we're drawing in auto-layout mode... */ 01402 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){ 01403 /* determine color to use when drawing links to children */ 01404 this_hoststatus=find_hoststatus(this_host->name); 01405 if(this_hoststatus!=NULL){ 01406 if(this_hoststatus->status==HOST_DOWN || this_hoststatus->status==HOST_UNREACHABLE) 01407 status_color=color_red; 01408 else 01409 status_color=color_black; 01410 } 01411 else 01412 status_color=color_black; 01413 01414 x=this_host->x_2d+(DEFAULT_NODE_WIDTH/2)-canvas_x; 01415 y=(this_host->y_2d+(DEFAULT_NODE_WIDTH)/2)-canvas_y; 01416 01417 draw_dashed_line(x,y,x,y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING,status_color); 01418 01419 /* draw arrow tips */ 01420 draw_line(x,y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING,x-5,y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING-5,color_black); 01421 draw_line(x,y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING,x+5,y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING-5,color_black); 01422 } 01423 01424 /* this is a parent of the main host we're drawing in auto-layout mode... */ 01425 if(layout_method!=LAYOUT_USER_SUPPLIED && draw_parent_links==TRUE && is_host_immediate_child_of_host(this_host,main_host)==TRUE){ 01426 01427 x=this_host->x_2d+(DEFAULT_NODE_WIDTH/2)-canvas_x; 01428 y=this_host->y_2d+(DEFAULT_NODE_WIDTH/2)-canvas_y; 01429 01430 draw_dashed_line(x,y,x,y-DEFAULT_NODE_HEIGHT-DEFAULT_NODE_VSPACING,color_black); 01431 01432 /* draw arrow tips */ 01433 draw_line(x,y-DEFAULT_NODE_HEIGHT-DEFAULT_NODE_VSPACING,x-5,y-DEFAULT_NODE_HEIGHT-DEFAULT_NODE_VSPACING+5,color_black); 01434 draw_line(x,y-DEFAULT_NODE_HEIGHT-DEFAULT_NODE_VSPACING,x+5,y-DEFAULT_NODE_HEIGHT-DEFAULT_NODE_VSPACING+5,color_black); 01435 } 01436 01437 /* draw links to all parent hosts */ 01438 for(temp_hostsmember=this_host->parent_hosts;temp_hostsmember!=NULL;temp_hostsmember=temp_hostsmember->next){ 01439 01440 /* find the parent host config entry */ 01441 parent_host=find_host(temp_hostsmember->host_name); 01442 if(parent_host==NULL) 01443 continue; 01444 01445 /* don't draw the link if we don't have the coords */ 01446 if(parent_host->have_2d_coords==FALSE || this_host->have_2d_coords==FALSE) 01447 continue; 01448 01449 /* only draw link if user is authorized for this parent host */ 01450 if(is_authorized_for_host(parent_host,¤t_authdata)==FALSE) 01451 continue; 01452 01453 /* are the hosts in the layer list? */ 01454 child_in_layer_list=is_host_in_layer_list(this_host); 01455 parent_in_layer_list=is_host_in_layer_list(parent_host); 01456 01457 /* use dotted or solid line? */ 01458 /* either the child or parent should not be drawn, so use a dotted line */ 01459 if((child_in_layer_list==TRUE && parent_in_layer_list==FALSE) || (child_in_layer_list==FALSE && parent_in_layer_list==TRUE)) 01460 dotted_line=TRUE; 01461 /* both hosts should not be drawn, so use a dotted line */ 01462 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)) 01463 dotted_line=TRUE; 01464 /* both hosts should be drawn, so use a solid line */ 01465 else 01466 dotted_line=FALSE; 01467 01468 /* determine color to use when drawing links to parent host */ 01469 parent_hoststatus=find_hoststatus(parent_host->name); 01470 if(parent_hoststatus!=NULL){ 01471 if(parent_hoststatus->status==HOST_DOWN || parent_hoststatus->status==HOST_UNREACHABLE) 01472 status_color=color_red; 01473 else 01474 status_color=color_black; 01475 } 01476 else 01477 status_color=color_black; 01478 01479 /* draw the link */ 01480 if(dotted_line==TRUE) 01481 draw_dotted_line((this_host->x_2d+(DEFAULT_NODE_WIDTH/2))-canvas_x,(this_host->y_2d+(DEFAULT_NODE_WIDTH)/2)-canvas_y,(parent_host->x_2d+(DEFAULT_NODE_WIDTH/2))-canvas_x,(parent_host->y_2d+(DEFAULT_NODE_WIDTH/2))-canvas_y,status_color); 01482 else 01483 draw_line((this_host->x_2d+(DEFAULT_NODE_WIDTH/2))-canvas_x,(this_host->y_2d+(DEFAULT_NODE_WIDTH)/2)-canvas_y,(parent_host->x_2d+(DEFAULT_NODE_WIDTH/2))-canvas_x,(parent_host->y_2d+(DEFAULT_NODE_WIDTH/2))-canvas_y,status_color); 01484 } 01485 01486 } 01487 01488 return; 01489 } 01490 01491 01492 01493 /* draws hosts */ 01494 void draw_hosts(void){ 01495 host *temp_host; 01496 int x1, x2; 01497 int y1, y2; 01498 int has_image=FALSE; 01499 char image_input_file[MAX_INPUT_BUFFER]; 01500 int current_radius=0; 01501 int status_color=color_black; 01502 hoststatus *temp_hoststatus; 01503 int in_layer_list=FALSE; 01504 int average_host_services; 01505 int host_services; 01506 double host_services_ratio; 01507 int outer_radius; 01508 int inner_radius; 01509 int time_color=0; 01510 time_t current_time; 01511 int translated_x; 01512 int translated_y; 01513 01514 01515 /* user didn't supply any coordinates for hosts, so display a warning */ 01516 if(coordinates_were_specified==FALSE){ 01517 01518 if(content_type==IMAGE_CONTENT){ 01519 draw_text("You have not supplied any host drawing coordinates, so you cannot use this layout method.",(COORDS_WARNING_WIDTH/2),30,color_black); 01520 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); 01521 } 01522 01523 return; 01524 } 01525 01526 /* draw Icinga process icon if using auto-layout mode */ 01527 if(layout_method!=LAYOUT_USER_SUPPLIED && draw_nagios_icon==TRUE){ 01528 01529 /* get coords of bounding box */ 01530 x1=nagios_icon_x-canvas_x; 01531 x2=x1+DEFAULT_NODE_WIDTH; 01532 y1=nagios_icon_y-canvas_y; 01533 y2=y1+DEFAULT_NODE_HEIGHT; 01534 01535 /* get the name of the image file to open for the logo */ 01536 snprintf(image_input_file,sizeof(image_input_file)-1,"%s%s",physical_logo_images_path,ICINGA_GD2_ICON); 01537 image_input_file[sizeof(image_input_file)-1]='\x0'; 01538 01539 /* read in the image from file... */ 01540 logo_image=load_image_from_file(image_input_file); 01541 01542 /* copy the logo image to the canvas image... */ 01543 if(logo_image!=NULL){ 01544 gdImageCopy(map_image,logo_image,x1,y1,0,0,logo_image->sx,logo_image->sy); 01545 gdImageDestroy(logo_image); 01546 } 01547 01548 /* if we don't have an image, draw a bounding box */ 01549 else{ 01550 draw_line(x1,y1,x1,y1+DEFAULT_NODE_WIDTH,color_black); 01551 draw_line(x1,y1+DEFAULT_NODE_WIDTH,x2,y1+DEFAULT_NODE_WIDTH,color_black); 01552 draw_line(x2,y1+DEFAULT_NODE_WIDTH,x2,y1,color_black); 01553 draw_line(x2,y1,x1,y1,color_black); 01554 } 01555 01556 if(content_type==IMAGE_CONTENT) 01557 draw_text("Icinga Process",x1+(DEFAULT_NODE_WIDTH/2),y1+DEFAULT_NODE_HEIGHT,color_black); 01558 } 01559 01560 /* calculate average services per host */ 01561 average_host_services=4; 01562 01563 /* draw all hosts... */ 01564 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 01565 01566 /* skip hosts that should not be drawn */ 01567 if(temp_host->should_be_drawn==FALSE) 01568 continue; 01569 01570 /* is this host in the layer inclusion/exclusion list? */ 01571 in_layer_list=is_host_in_layer_list(temp_host); 01572 if((in_layer_list==TRUE && exclude_layers==TRUE) || (in_layer_list==FALSE && exclude_layers==FALSE)) 01573 continue; 01574 01575 /* get coords of host bounding box */ 01576 x1=temp_host->x_2d-canvas_x; 01577 x2=x1+DEFAULT_NODE_WIDTH; 01578 y1=temp_host->y_2d-canvas_y; 01579 y2=y1+DEFAULT_NODE_HEIGHT; 01580 01581 if(content_type==IMAGE_CONTENT){ 01582 01583 01584 temp_hoststatus=find_hoststatus(temp_host->name); 01585 if(temp_hoststatus!=NULL){ 01586 if(temp_hoststatus->status==HOST_DOWN) 01587 status_color=color_red; 01588 else if(temp_hoststatus->status==HOST_UNREACHABLE) 01589 status_color=color_red; 01590 else if(temp_hoststatus->status==HOST_UP) 01591 status_color=color_green; 01592 else if(temp_hoststatus->status==HOST_PENDING) 01593 status_color=color_grey; 01594 } 01595 else 01596 status_color=color_black; 01597 01598 01599 /* use balloons instead of icons... */ 01600 if(layout_method==LAYOUT_CIRCULAR_BALLOON){ 01601 01602 /* get the number of services associated with the host */ 01603 host_services=number_of_host_services(temp_host); 01604 01605 if(average_host_services==0) 01606 host_services_ratio=0.0; 01607 else 01608 host_services_ratio=(double)((double)host_services/(double)average_host_services); 01609 01610 /* calculate size of node */ 01611 if(host_services_ratio>=2.0) 01612 outer_radius=DEFAULT_NODE_WIDTH; 01613 else if(host_services_ratio>=1.5) 01614 outer_radius=DEFAULT_NODE_WIDTH*0.8; 01615 else if(host_services_ratio>=1.0) 01616 outer_radius=DEFAULT_NODE_WIDTH*0.6; 01617 else if(host_services_ratio>=0.5) 01618 outer_radius=DEFAULT_NODE_WIDTH*0.4; 01619 else 01620 outer_radius=DEFAULT_NODE_WIDTH*0.2; 01621 01622 /* calculate width of border */ 01623 if(temp_hoststatus==NULL) 01624 inner_radius=outer_radius; 01625 else if((temp_hoststatus->status==HOST_DOWN || temp_hoststatus->status==HOST_UNREACHABLE) && temp_hoststatus->problem_has_been_acknowledged==FALSE) 01626 inner_radius=outer_radius-3; 01627 else 01628 inner_radius=outer_radius; 01629 01630 /* fill node with color based on how long its been in this state... */ 01631 gdImageArc(map_image,x1+(DEFAULT_NODE_WIDTH/2),y1+(DEFAULT_NODE_WIDTH/2),outer_radius,outer_radius,0,360,color_blue); 01632 01633 /* determine fill color */ 01634 time(¤t_time); 01635 if(temp_hoststatus==NULL) 01636 time_color=color_white; 01637 else if(current_time-temp_hoststatus->last_state_change<=900) 01638 time_color=color_orange; 01639 else if(current_time-temp_hoststatus->last_state_change<=3600) 01640 time_color=color_yellow; 01641 else 01642 time_color=color_white; 01643 01644 /* fill node with appropriate time color */ 01645 /* the fill function only works with coordinates that are in bounds of the actual image */ 01646 translated_x=x1+(DEFAULT_NODE_WIDTH/2); 01647 translated_y=y1+(DEFAULT_NODE_WIDTH/2); 01648 if(translated_x>0 && translated_y>0 && translated_x<canvas_width && translated_y<canvas_height) 01649 gdImageFillToBorder(map_image,translated_x,translated_y,color_blue,time_color); 01650 01651 /* border of node should reflect current state */ 01652 for(current_radius=outer_radius;current_radius>=inner_radius;current_radius--) 01653 gdImageArc(map_image,x1+(DEFAULT_NODE_WIDTH/2),y1+(DEFAULT_NODE_WIDTH/2),current_radius,current_radius,0,360,status_color); 01654 01655 /* draw circles around the selected host (if there is one) */ 01656 if(!strcmp(host_name,temp_host->name) && use_highlights==TRUE){ 01657 for(current_radius=DEFAULT_NODE_WIDTH*2;current_radius>0;current_radius-=10) 01658 gdImageArc(map_image,x1+(DEFAULT_NODE_WIDTH/2),y1+(DEFAULT_NODE_WIDTH/2),current_radius,current_radius,0,360,status_color); 01659 } 01660 } 01661 01662 01663 /* normal method is to use icons for hosts... */ 01664 else{ 01665 01666 /* draw a target around root hosts (hosts with no parents) */ 01667 if(temp_host!=NULL && use_highlights==TRUE){ 01668 if(temp_host->parent_hosts==NULL){ 01669 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); 01670 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); 01671 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); 01672 } 01673 } 01674 01675 /* draw circles around the selected host (if there is one) */ 01676 if(!strcmp(host_name,temp_host->name) && use_highlights==TRUE){ 01677 for(current_radius=DEFAULT_NODE_WIDTH*2;current_radius>0;current_radius-=10) 01678 gdImageArc(map_image,x1+(DEFAULT_NODE_WIDTH/2),y1+(DEFAULT_NODE_WIDTH/2),current_radius,current_radius,0,360,status_color); 01679 } 01680 01681 01682 if(temp_host->statusmap_image!=NULL) 01683 has_image=TRUE; 01684 else 01685 has_image=FALSE; 01686 01687 /* load the logo associated with this host */ 01688 if(has_image==TRUE){ 01689 01690 /* get the name of the image file to open for the logo */ 01691 snprintf(image_input_file,sizeof(image_input_file)-1,"%s%s",physical_logo_images_path,temp_host->statusmap_image); 01692 image_input_file[sizeof(image_input_file)-1]='\x0'; 01693 01694 /* read in the logo image from file... */ 01695 logo_image=load_image_from_file(image_input_file); 01696 01697 /* copy the logo image to the canvas image... */ 01698 if(logo_image!=NULL){ 01699 gdImageCopy(map_image,logo_image,x1,y1,0,0,logo_image->sx,logo_image->sy); 01700 gdImageDestroy(logo_image); 01701 } 01702 else 01703 has_image=FALSE; 01704 } 01705 01706 /* 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 */ 01707 if(has_image==FALSE){ 01708 01709 if(unknown_logo_image!=NULL) 01710 gdImageCopy(map_image,unknown_logo_image,x1,y1,0,0,unknown_logo_image->sx,unknown_logo_image->sy); 01711 01712 else{ 01713 01714 /* last ditch effort - draw a host bounding box */ 01715 draw_line(x1,y1,x1,y1+DEFAULT_NODE_WIDTH,color_black); 01716 draw_line(x1,y1+DEFAULT_NODE_WIDTH,x2,y1+DEFAULT_NODE_WIDTH,color_black); 01717 draw_line(x2,y1+DEFAULT_NODE_WIDTH,x2,y1,color_black); 01718 draw_line(x2,y1,x1,y1,color_black); 01719 } 01720 } 01721 } 01722 01723 01724 /* draw host name, status, etc. */ 01725 draw_host_text((temp_host->display_name!=NULL)?temp_host->display_name:temp_host->name,x1+(DEFAULT_NODE_WIDTH/2),y1+DEFAULT_NODE_HEIGHT); 01726 } 01727 01728 /* we're creating HTML image map... */ 01729 else{ 01730 printf("<AREA shape='rect' "); 01731 01732 /* coordinates */ 01733 printf("coords='%d,%d,%d,%d' ",(int)(x1*scaling_factor),(int)(y1*scaling_factor),(int)((x1+DEFAULT_NODE_WIDTH)*scaling_factor),(int)((y1+DEFAULT_NODE_HEIGHT)*scaling_factor)); 01734 01735 /* URL */ 01736 if(!strcmp(host_name,temp_host->name)) 01737 printf("href='%s?host=%s' ",STATUS_CGI,url_encode(temp_host->name)); 01738 else{ 01739 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_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":""); 01740 if(user_supplied_scaling==TRUE) 01741 printf("&scaling_factor=%2.1f",user_scaling_factor); 01742 print_layer_url(TRUE); 01743 printf("' "); 01744 } 01745 01746 /* popup text */ 01747 if(display_popups==TRUE){ 01748 01749 printf("onMouseOver='showPopup(\""); 01750 write_host_popup_text(find_host(temp_host->name)); 01751 printf("\",event)' onMouseOut='hidePopup()'"); 01752 } 01753 01754 printf(">\n"); 01755 } 01756 01757 } 01758 01759 return; 01760 } 01761 01762 01763 /* draws text */ 01764 void draw_text(char *buffer,int x,int y,int text_color){ 01765 int string_width=0; 01766 int string_height=0; 01767 01768 /* write the string to the generated image... */ 01769 string_height=gdFontSmall->h; 01770 string_width=gdFontSmall->w*strlen(buffer); 01771 if(layout_method!=LAYOUT_CIRCULAR_MARKUP) 01772 gdImageFilledRectangle(map_image,x-(string_width/2)-2,y-(2*string_height),x+(string_width/2)+2,y-string_height,color_white); 01773 gdImageString(map_image,gdFontSmall,x-(string_width/2),y-(2*string_height),(unsigned char *)buffer,text_color); 01774 01775 return; 01776 } 01777 01778 01779 /* draws host text */ 01780 void draw_host_text(char *name,int x,int y){ 01781 hoststatus *temp_hoststatus; 01782 int status_color=color_black; 01783 char temp_buffer[MAX_INPUT_BUFFER]; 01784 01785 if(use_text==FALSE) 01786 return; 01787 01788 strncpy(temp_buffer,name,sizeof(temp_buffer)-1); 01789 temp_buffer[sizeof(temp_buffer)-1]='\x0'; 01790 01791 /* write the host status string to the generated image... */ 01792 draw_text(temp_buffer,x,y,color_black); 01793 01794 /* find the status entry for this host */ 01795 temp_hoststatus=find_hoststatus(name); 01796 01797 /* get the status of the host (pending, up, down, or unreachable) */ 01798 if(temp_hoststatus!=NULL){ 01799 01800 /* draw the status string */ 01801 if(temp_hoststatus->status==HOST_DOWN){ 01802 strncpy(temp_buffer,"Down",sizeof(temp_buffer)); 01803 status_color=color_red; 01804 } 01805 else if(temp_hoststatus->status==HOST_UNREACHABLE){ 01806 strncpy(temp_buffer,"Unreachable",sizeof(temp_buffer)); 01807 status_color=color_red; 01808 } 01809 else if(temp_hoststatus->status==HOST_UP){ 01810 strncpy(temp_buffer,"Up",sizeof(temp_buffer)); 01811 status_color=color_green; 01812 } 01813 else if(temp_hoststatus->status==HOST_PENDING){ 01814 strncpy(temp_buffer,"Pending",sizeof(temp_buffer)); 01815 status_color=color_grey; 01816 } 01817 else{ 01818 strncpy(temp_buffer,"Unknown",sizeof(temp_buffer)); 01819 status_color=color_orange; 01820 } 01821 01822 temp_buffer[sizeof(temp_buffer)-1]='\x0'; 01823 01824 /* write the host status string to the generated image... */ 01825 draw_text(temp_buffer,x,y+gdFontSmall->h,status_color); 01826 } 01827 01828 return; 01829 } 01830 01831 01832 /* writes popup text for a specific host */ 01833 void write_host_popup_text(host *hst){ 01834 hoststatus *temp_status=NULL; 01835 hostsmember *temp_hostsmember=NULL; 01836 char *processed_string=NULL; 01837 int service_totals; 01838 char date_time[48]; 01839 time_t current_time; 01840 time_t t; 01841 char state_duration[48]; 01842 int days; 01843 int hours; 01844 int minutes; 01845 int seconds; 01846 01847 if(hst==NULL){ 01848 printf("Host data not found"); 01849 return; 01850 } 01851 01852 /* find the status entry for this host */ 01853 temp_status=find_hoststatus(hst->name); 01854 if(temp_status==NULL){ 01855 printf("Host status information not found"); 01856 return; 01857 } 01858 01859 /* grab macros */ 01860 grab_host_macros_r(mac, hst); 01861 01862 /* strip nasty stuff from plugin output */ 01863 sanitize_plugin_output(temp_status->plugin_output); 01864 01865 printf("<table border=0 cellpadding=0 cellspacing=5>"); 01866 01867 printf("<tr><td><img src=\\\"%s",url_logo_images_path); 01868 if(hst->icon_image==NULL) 01869 printf("%s",UNKNOWN_ICON_IMAGE); 01870 else{ 01871 process_macros_r(mac, hst->icon_image,&processed_string,0); 01872 printf("%s",processed_string); 01873 free(processed_string); 01874 } 01875 printf("\\\" border=0 width=40 height=40></td>"); 01876 printf("<td class=\\\"popupText\\\"><i>%s</i></td></tr>",(hst->icon_image_alt==NULL)?"":html_encode(hst->icon_image_alt,TRUE)); 01877 01878 printf("<tr><td class=\\\"popupText\\\">Name:</td><td class=\\\"popupText\\\"><b>%s</b></td></tr>",escape_string(hst->name)); 01879 printf("<tr><td class=\\\"popupText\\\">Alias:</td><td class=\\\"popupText\\\"><b>%s</b></td></tr>",escape_string(hst->alias)); 01880 printf("<tr><td class=\\\"popupText\\\">Address:</td><td class=\\\"popupText\\\"><b>%s</b></td></tr>",html_encode(hst->address,TRUE)); 01881 printf("<tr><td class=\\\"popupText\\\">Address6:</td><td class=\\\"popupText\\\"><b>%s</b></td></tr>",html_encode(hst->address6,TRUE)); 01882 printf("<tr><td class=\\\"popupText\\\">State:</td><td class=\\\"popupText\\\"><b>"); 01883 01884 /* get the status of the host (pending, up, down, or unreachable) */ 01885 if(temp_status->status==HOST_DOWN){ 01886 printf("<font color=red>Down"); 01887 if(temp_status->problem_has_been_acknowledged==TRUE) 01888 printf(" (Acknowledged)"); 01889 printf("</font>"); 01890 } 01891 01892 else if(temp_status->status==HOST_UNREACHABLE){ 01893 printf("<font color=red>Unreachable"); 01894 if(temp_status->problem_has_been_acknowledged==TRUE) 01895 printf(" (Acknowledged)"); 01896 printf("</font>"); 01897 } 01898 01899 else if(temp_status->status==HOST_UP) 01900 printf("<font color=green>Up</font>"); 01901 01902 else if(temp_status->status==HOST_PENDING) 01903 printf("Pending"); 01904 01905 printf("</b></td></tr>"); 01906 printf("<tr><td class=\\\"popupText\\\">Status Information:</td><td class=\\\"popupText\\\"><b>%s</b></td></tr>",(temp_status->plugin_output==NULL)?"":temp_status->plugin_output); 01907 01908 current_time=time(NULL); 01909 if(temp_status->last_state_change==(time_t)0) 01910 t=current_time-program_start; 01911 else 01912 t=current_time-temp_status->last_state_change; 01913 get_time_breakdown((unsigned long)t,&days,&hours,&minutes,&seconds); 01914 snprintf(state_duration,sizeof(state_duration)-1,"%2dd %2dh %2dm %2ds%s",days,hours,minutes,seconds,(temp_status->last_state_change==(time_t)0)?"+":""); 01915 state_duration[sizeof(state_duration)-1]='\x0'; 01916 printf("<tr><td class=\\\"popupText\\\">State Duration:</td><td class=\\\"popupText\\\"><b>%s</b></td></tr>",state_duration); 01917 01918 get_time_string(&temp_status->last_check,date_time,(int)sizeof(date_time),SHORT_DATE_TIME); 01919 printf("<tr><td class=\\\"popupText\\\">Last Status Check:</td><td class=\\\"popupText\\\"><b>%s</b></td></tr>",(temp_status->last_check==(time_t)0)?"N/A":date_time); 01920 get_time_string(&temp_status->last_state_change,date_time,(int)sizeof(date_time),SHORT_DATE_TIME); 01921 printf("<tr><td class=\\\"popupText\\\">Last State Change:</td><td class=\\\"popupText\\\"><b>%s</b></td></tr>",(temp_status->last_state_change==(time_t)0)?"N/A":date_time); 01922 01923 printf("<tr><td class=\\\"popupText\\\">Parent Host(s):</td><td class=\\\"popupText\\\"><b>"); 01924 if(hst->parent_hosts==NULL) 01925 printf("None (This is a root host)"); 01926 else{ 01927 for(temp_hostsmember=hst->parent_hosts;temp_hostsmember!=NULL;temp_hostsmember=temp_hostsmember->next) 01928 printf("%s%s",(temp_hostsmember==hst->parent_hosts)?"":", ",html_encode(temp_hostsmember->host_name,TRUE)); 01929 } 01930 printf("</b></td></tr>"); 01931 01932 printf("<tr><td class=\\\"popupText\\\">Immediate Child Hosts:</td><td class=\\\"popupText\\\"><b>"); 01933 printf("%d",number_of_immediate_child_hosts(hst)); 01934 printf("</b></td></tr>"); 01935 01936 printf("</table>"); 01937 01938 printf("<br><b><u>Services:</u></b><br>"); 01939 01940 service_totals=get_servicestatus_count(hst->name,SERVICE_OK); 01941 if(service_totals>0) 01942 printf("- <font color=green>%d ok</font><br>",service_totals); 01943 service_totals=get_servicestatus_count(hst->name,SERVICE_CRITICAL); 01944 if(service_totals>0) 01945 printf("- <font color=red>%d critical</font><br>",service_totals); 01946 service_totals=get_servicestatus_count(hst->name,SERVICE_WARNING); 01947 if(service_totals>0) 01948 printf("- <font color=orange>%d warning</font><br>",service_totals); 01949 service_totals=get_servicestatus_count(hst->name,SERVICE_UNKNOWN); 01950 if(service_totals>0) 01951 printf("- <font color=orange>%d unknown</font><br>",service_totals); 01952 service_totals=get_servicestatus_count(hst->name,SERVICE_PENDING); 01953 if(service_totals>0) 01954 printf("- %d pending<br>",service_totals); 01955 01956 return; 01957 } 01958 01959 01960 01961 /* draws a solid line */ 01962 void draw_line(int x1,int y1,int x2,int y2,int color){ 01963 01964 if(content_type==HTML_CONTENT) 01965 return; 01966 01967 gdImageLine(map_image,x1,y1,x2,y2,color); 01968 01969 return; 01970 } 01971 01972 01973 /* draws a dotted line */ 01974 void draw_dotted_line(int x1,int y1,int x2,int y2,int color){ 01975 int styleDotted[12]; 01976 01977 styleDotted[0]=color; 01978 styleDotted[1]=gdTransparent; 01979 styleDotted[2]=gdTransparent; 01980 styleDotted[3]=gdTransparent; 01981 styleDotted[4]=gdTransparent; 01982 styleDotted[5]=gdTransparent; 01983 styleDotted[6]=color; 01984 styleDotted[7]=gdTransparent; 01985 styleDotted[8]=gdTransparent; 01986 styleDotted[9]=gdTransparent; 01987 styleDotted[10]=gdTransparent; 01988 styleDotted[11]=gdTransparent; 01989 01990 /* sets current style to a dashed line */ 01991 gdImageSetStyle(map_image,styleDotted,12); 01992 01993 /* draws a line (dotted) */ 01994 gdImageLine(map_image,x1,y1,x2,y2,gdStyled); 01995 01996 return; 01997 } 01998 01999 /* draws a dashed line */ 02000 void draw_dashed_line(int x1,int y1,int x2,int y2,int color){ 02001 int styleDashed[12]; 02002 02003 styleDashed[0]=color; 02004 styleDashed[1]=color; 02005 styleDashed[2]=color; 02006 styleDashed[3]=color; 02007 styleDashed[4]=gdTransparent; 02008 styleDashed[5]=gdTransparent; 02009 styleDashed[6]=color; 02010 styleDashed[7]=color; 02011 styleDashed[8]=color; 02012 styleDashed[9]=color; 02013 styleDashed[10]=gdTransparent; 02014 styleDashed[11]=gdTransparent; 02015 02016 /* sets current style to a dashed line */ 02017 gdImageSetStyle(map_image,styleDashed,12); 02018 02019 /* draws a line (dashed) */ 02020 gdImageLine(map_image,x1,y1,x2,y2,gdStyled); 02021 02022 return; 02023 } 02024 02025 02026 02027 /******************************************************************/ 02028 /*********************** GRAPHICS FUNCTIONS ***********************/ 02029 /******************************************************************/ 02030 02031 /* initialize graphics */ 02032 int initialize_graphics(void){ 02033 char image_input_file[MAX_INPUT_BUFFER]; 02034 02035 if(content_type==HTML_CONTENT) 02036 return ERROR; 02037 02038 /* allocate buffer for storing image */ 02039 #ifndef HAVE_GDIMAGECREATETRUECOLOR 02040 map_image=gdImageCreate(canvas_width,canvas_height); 02041 #else 02042 map_image=gdImageCreateTrueColor(canvas_width,canvas_height); 02043 #endif 02044 if(map_image==NULL) 02045 return ERROR; 02046 02047 /* allocate colors used for drawing */ 02048 color_white=gdImageColorAllocate(map_image,255,255,255); 02049 color_black=gdImageColorAllocate(map_image,0,0,0); 02050 color_grey=gdImageColorAllocate(map_image,128,128,128); 02051 color_lightgrey=gdImageColorAllocate(map_image,210,210,210); 02052 color_red=gdImageColorAllocate(map_image,255,0,0); 02053 color_lightred=gdImageColorAllocate(map_image,215,175,175); 02054 color_green=gdImageColorAllocate(map_image,0,175,0); 02055 color_lightgreen=gdImageColorAllocate(map_image,210,255,215); 02056 color_blue=gdImageColorAllocate(map_image,0,0,255); 02057 color_yellow=gdImageColorAllocate(map_image,255,255,0); 02058 color_orange=gdImageColorAllocate(map_image,255,100,25); 02059 color_transparency_index=gdImageColorAllocate(map_image,color_transparency_index_r,color_transparency_index_g,color_transparency_index_b); 02060 02061 /* set transparency index */ 02062 #ifndef HAVE_GDIMAGECREATETRUECOLOR 02063 gdImageColorTransparent(map_image,color_white); 02064 #else 02065 gdImageColorTransparent(map_image,color_transparency_index); 02066 02067 /* set background */ 02068 gdImageFill(map_image, 0, 0, color_transparency_index); 02069 #endif 02070 02071 /* make sure the graphic is interlaced */ 02072 gdImageInterlace(map_image,1); 02073 02074 /* get the path where we will be reading logo images from (GD2 format)... */ 02075 snprintf(physical_logo_images_path,sizeof(physical_logo_images_path)-1,"%slogos/",physical_images_path); 02076 physical_logo_images_path[sizeof(physical_logo_images_path)-1]='\x0'; 02077 02078 /* load the unknown icon to use for hosts that don't have pretty images associated with them... */ 02079 snprintf(image_input_file,sizeof(image_input_file)-1,"%s%s",physical_logo_images_path,UNKNOWN_GD2_ICON); 02080 image_input_file[sizeof(image_input_file)-1]='\x0'; 02081 unknown_logo_image=load_image_from_file(image_input_file); 02082 02083 return OK; 02084 } 02085 02086 02087 02088 /* loads a graphic image (GD2, JPG or PNG) from file into memory */ 02089 gdImagePtr load_image_from_file(char *filename){ 02090 FILE *fp; 02091 gdImagePtr im=NULL; 02092 char *ext; 02093 02094 /* make sure we were passed a file name */ 02095 if(filename==NULL) 02096 return NULL; 02097 02098 /* find the file extension */ 02099 if((ext=rindex(filename,'.'))==NULL) 02100 return NULL; 02101 02102 /* open the file for reading (binary mode) */ 02103 fp=fopen(filename,"rb"); 02104 if(fp==NULL) 02105 return NULL; 02106 02107 /* attempt to read files in various formats */ 02108 if(!strcasecmp(ext,".png")) 02109 im=gdImageCreateFromPng(fp); 02110 else if(!strcasecmp(ext,".jpg") || !strcasecmp(ext,".jpeg")) 02111 im=gdImageCreateFromJpeg(fp); 02112 else if(!strcasecmp(ext,".xbm")) 02113 im=gdImageCreateFromXbm(fp); 02114 else if(!strcasecmp(ext,".gd2")) 02115 im=gdImageCreateFromGd2(fp); 02116 else if(!strcasecmp(ext,".gd")) 02117 im=gdImageCreateFromGd(fp); 02118 02119 /* fall back to GD2 image format */ 02120 else 02121 im=gdImageCreateFromGd2(fp); 02122 02123 /* close the file */ 02124 fclose(fp); 02125 02126 return im; 02127 } 02128 02129 02130 02131 /* draw graphics */ 02132 void write_graphics(void){ 02133 FILE *image_output_file=NULL; 02134 02135 if(content_type==HTML_CONTENT) 02136 return; 02137 02138 /* use STDOUT for writing the image data... */ 02139 image_output_file=stdout; 02140 02141 /* write the image out in PNG format */ 02142 gdImagePng(map_image,image_output_file); 02143 02144 /* or we could write the image out in JPG format... */ 02145 /*gdImageJpeg(map_image,image_output_file,99);*/ 02146 02147 return; 02148 } 02149 02150 02151 /* cleanup graphics resources */ 02152 void cleanup_graphics(void){ 02153 02154 if(content_type==HTML_CONTENT) 02155 return; 02156 02157 /* free memory allocated to image */ 02158 gdImageDestroy(map_image); 02159 02160 return; 02161 } 02162 02163 02164 02165 02166 /******************************************************************/ 02167 /************************* MISC FUNCTIONS *************************/ 02168 /******************************************************************/ 02169 02170 /* adds a layer to the list in memory */ 02171 int add_layer(char *group_name){ 02172 layer *new_layer; 02173 02174 if(group_name==NULL) 02175 return ERROR; 02176 02177 /* allocate memory for a new layer */ 02178 new_layer=(layer *)malloc(sizeof(layer)); 02179 if(new_layer==NULL) 02180 return ERROR; 02181 02182 new_layer->layer_name=(char *)malloc(strlen(group_name)+1); 02183 if(new_layer->layer_name==NULL){ 02184 free(new_layer); 02185 return ERROR; 02186 } 02187 02188 strcpy(new_layer->layer_name,group_name); 02189 02190 /* add new layer to head of layer list */ 02191 new_layer->next=layer_list; 02192 layer_list=new_layer; 02193 02194 return OK; 02195 } 02196 02197 02198 02199 /* frees memory allocated to the layer list */ 02200 void free_layer_list(void){ 02201 layer *this_layer; 02202 layer *next_layer; 02203 02204 return; 02205 02206 for(this_layer=layer_list;layer_list!=NULL;this_layer=next_layer){ 02207 next_layer=this_layer->next; 02208 free(this_layer->layer_name); 02209 free(this_layer); 02210 } 02211 02212 return; 02213 } 02214 02215 02216 /* checks to see if a host is in the layer list */ 02217 int is_host_in_layer_list(host *hst){ 02218 hostgroup *temp_hostgroup; 02219 layer *temp_layer; 02220 02221 if(hst==NULL) 02222 return FALSE; 02223 02224 /* check each layer... */ 02225 for(temp_layer=layer_list;temp_layer!=NULL;temp_layer=temp_layer->next){ 02226 02227 /* find the hostgroup */ 02228 temp_hostgroup=find_hostgroup(temp_layer->layer_name); 02229 if(temp_hostgroup==NULL) 02230 continue; 02231 02232 /* is the requested host a member of the hostgroup/layer? */ 02233 if(is_host_member_of_hostgroup(temp_hostgroup,hst)==TRUE) 02234 return TRUE; 02235 } 02236 02237 return FALSE; 02238 } 02239 02240 02241 /* print layer url info */ 02242 void print_layer_url(int get_method){ 02243 layer *temp_layer; 02244 02245 for(temp_layer=layer_list;temp_layer!=NULL;temp_layer=temp_layer->next){ 02246 if(get_method==TRUE) 02247 printf("&layer=%s",escape_string(temp_layer->layer_name)); 02248 else 02249 printf("<input type='hidden' name='layer' value='%s'>\n",escape_string(temp_layer->layer_name)); 02250 } 02251 02252 if(get_method==TRUE) 02253 printf("&layermode=%s",(exclude_layers==TRUE)?"exclude":"include"); 02254 else 02255 printf("<input type='hidden' name='layermode' value='%s'>\n",(exclude_layers==TRUE)?"exclude":"include"); 02256 02257 return; 02258 } 02259 02260 02261 02262 02263 /******************************************************************/ 02264 /************************ UTILITY FUNCTIONS ***********************/ 02265 /******************************************************************/ 02266 02267 /* calculates how many "layers" separate parent and child - used by collapsed tree layout method */ 02268 int host_child_depth_separation(host *parent, host *child){ 02269 int this_depth=0; 02270 int min_depth=0; 02271 int have_min_depth=FALSE; 02272 host *temp_host; 02273 02274 if(child==NULL) 02275 return -1; 02276 02277 if(parent==child) 02278 return 0; 02279 02280 if(is_host_immediate_child_of_host(parent,child)==TRUE) 02281 return 1; 02282 02283 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 02284 02285 if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){ 02286 02287 this_depth=host_child_depth_separation(temp_host,child); 02288 02289 if(this_depth>=0 && (have_min_depth==FALSE || (have_min_depth==TRUE && (this_depth<min_depth)))){ 02290 have_min_depth=TRUE; 02291 min_depth=this_depth; 02292 } 02293 } 02294 } 02295 02296 if(have_min_depth==FALSE) 02297 return -1; 02298 else 02299 return min_depth+1; 02300 } 02301 02302 02303 02304 /* calculates how many hosts reside on a specific "layer" - used by collapsed tree layout method */ 02305 int number_of_host_layer_members(host *parent, int layer){ 02306 int current_layer; 02307 int layer_members=0; 02308 host *temp_host; 02309 02310 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 02311 02312 current_layer=host_child_depth_separation(parent,temp_host); 02313 02314 if(current_layer==layer) 02315 layer_members++; 02316 } 02317 02318 return layer_members; 02319 } 02320 02321 02322 02323 /* calculate max number of members on all "layers" beneath and including parent host - used by collapsed tree layout method */ 02324 int max_child_host_layer_members(host *parent){ 02325 int current_layer; 02326 int max_members=1; 02327 int current_members=0; 02328 02329 for(current_layer=1;;current_layer++){ 02330 02331 current_members=number_of_host_layer_members(parent,current_layer); 02332 02333 if(current_members<=0) 02334 break; 02335 02336 if(current_members>max_members) 02337 max_members=current_members; 02338 } 02339 02340 return max_members; 02341 } 02342 02343 02344 02345 /* calculate max drawing width for host and children - used by balanced tree layout method */ 02346 int max_child_host_drawing_width(host *parent){ 02347 host *temp_host; 02348 int child_width=0; 02349 02350 02351 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 02352 02353 if(is_host_immediate_child_of_host(parent,temp_host)==TRUE) 02354 child_width+=max_child_host_drawing_width(temp_host); 02355 } 02356 02357 /* no children, so set width to 1 for this host */ 02358 if(child_width==0) 02359 return 1; 02360 02361 else 02362 return child_width; 02363 } 02364 02365 02366 02367 /* calculates number of services associated with a particular service */ 02368 int number_of_host_services(host *hst){ 02369 service *temp_service; 02370 int total_services=0; 02371 02372 if(hst==NULL) 02373 return 0; 02374 02375 /* check all the services */ 02376 for(temp_service=service_list;temp_service!=NULL;temp_service=temp_service->next){ 02377 if(!strcmp(temp_service->host_name,hst->name)) 02378 total_services++; 02379 } 02380 02381 return total_services; 02382 } 02383 02384 02385 02386 /******************************************************************/ 02387 /***************** COORDINATE CALCULATION FUNCTIONS ***************/ 02388 /******************************************************************/ 02389 02390 /* calculates coords of a host's children - used by balanced tree layout method */ 02391 void calculate_balanced_tree_coords(host *parent, int x, int y){ 02392 int parent_drawing_width; 02393 int start_drawing_x; 02394 int current_drawing_x; 02395 int this_drawing_width; 02396 host *temp_host; 02397 02398 /* calculate total drawing width of parent host */ 02399 parent_drawing_width=max_child_host_drawing_width(parent); 02400 02401 /* calculate starting x coord */ 02402 start_drawing_x=x-(((DEFAULT_NODE_WIDTH*parent_drawing_width)+(DEFAULT_NODE_HSPACING*(parent_drawing_width-1)))/2); 02403 current_drawing_x=start_drawing_x; 02404 02405 02406 /* calculate coords for children */ 02407 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 02408 02409 if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){ 02410 02411 /* get drawing width of child host */ 02412 this_drawing_width=max_child_host_drawing_width(temp_host); 02413 02414 temp_host->x_2d=current_drawing_x+(((DEFAULT_NODE_WIDTH*this_drawing_width)+(DEFAULT_NODE_HSPACING*(this_drawing_width-1)))/2); 02415 temp_host->y_2d=y+DEFAULT_NODE_HEIGHT+DEFAULT_NODE_VSPACING; 02416 temp_host->have_2d_coords=TRUE; 02417 temp_host->should_be_drawn=TRUE; 02418 02419 current_drawing_x+=(this_drawing_width*DEFAULT_NODE_WIDTH)+((this_drawing_width-1)*DEFAULT_NODE_HSPACING)+DEFAULT_NODE_HSPACING; 02420 02421 /* recurse into child host ... */ 02422 calculate_balanced_tree_coords(temp_host,temp_host->x_2d,temp_host->y_2d); 02423 } 02424 02425 } 02426 02427 return; 02428 } 02429 02430 02431 /* calculate coords of all hosts in circular layout method */ 02432 void calculate_circular_coords(void){ 02433 int min_x=0; 02434 int min_y=0; 02435 int have_min_x=FALSE; 02436 int have_min_y=FALSE; 02437 host *temp_host; 02438 02439 /* calculate all host coords, starting with first layer */ 02440 calculate_circular_layer_coords(NULL,0.0,360.0,1,CIRCULAR_DRAWING_RADIUS); 02441 02442 /* adjust all calculated coords so none are negative in x or y axis... */ 02443 02444 /* calculate min x, y coords */ 02445 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 02446 if(have_min_x==FALSE || temp_host->x_2d<min_x){ 02447 have_min_x=TRUE; 02448 min_x=temp_host->x_2d; 02449 } 02450 if(have_min_y==FALSE || temp_host->y_2d<min_y){ 02451 have_min_y=TRUE; 02452 min_y=temp_host->y_2d; 02453 } 02454 } 02455 02456 /* offset all drawing coords by the min x,y coords we found */ 02457 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 02458 if(min_x<0) 02459 temp_host->x_2d-=min_x; 02460 if(min_y<0) 02461 temp_host->y_2d-=min_y; 02462 } 02463 02464 if(min_x<0) 02465 nagios_icon_x-=min_x; 02466 if(min_y<0) 02467 nagios_icon_y-=min_y; 02468 02469 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 02470 temp_host->x_2d+=(DEFAULT_NODE_WIDTH/2); 02471 temp_host->y_2d+=(DEFAULT_NODE_HEIGHT/2); 02472 } 02473 nagios_icon_x+=(DEFAULT_NODE_WIDTH/2); 02474 nagios_icon_y+=(DEFAULT_NODE_HEIGHT/2); 02475 02476 return; 02477 } 02478 02479 02480 /* calculates coords of all hosts in a particular "layer" in circular layout method */ 02481 void calculate_circular_layer_coords(host *parent, double start_angle, double useable_angle, int layer, int radius){ 02482 int parent_drawing_width=0; 02483 int this_drawing_width=0; 02484 int immediate_children=0; 02485 double current_drawing_angle=0.0; 02486 double this_drawing_angle=0.0; 02487 double available_angle=0.0; 02488 double clipped_available_angle=0.0; 02489 double average_child_angle=0.0; 02490 double x_coord=0.0; 02491 double y_coord=0.0; 02492 host *temp_host; 02493 02494 02495 /* get the total number of immediate children to this host */ 02496 immediate_children=number_of_immediate_child_hosts(parent); 02497 02498 /* bail out if we're done */ 02499 if(immediate_children==0) 02500 return; 02501 02502 /* calculate total drawing "width" of parent host */ 02503 parent_drawing_width=max_child_host_drawing_width(parent); 02504 02505 /* calculate average angle given to each child host */ 02506 average_child_angle=(double)(useable_angle/(double)immediate_children); 02507 02508 /* calculate initial drawing angle */ 02509 current_drawing_angle=start_angle; 02510 02511 02512 /* calculate coords for children */ 02513 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 02514 02515 if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){ 02516 02517 /* get drawing width of child host */ 02518 this_drawing_width=max_child_host_drawing_width(temp_host); 02519 02520 /* calculate angle this host gets for drawing */ 02521 available_angle=useable_angle*((double)this_drawing_width/(double)parent_drawing_width); 02522 02523 /* clip available angle if necessary */ 02524 /* this isn't really necessary, but helps keep things looking a bit more sane with less potential connection crossover */ 02525 clipped_available_angle=360.0/layer; 02526 if(available_angle<clipped_available_angle) 02527 clipped_available_angle=available_angle; 02528 02529 /* calculate the exact angle at which we should draw this child */ 02530 this_drawing_angle=current_drawing_angle+(available_angle/2.0); 02531 02532 /* compensate for angle overflow */ 02533 while(this_drawing_angle>=360.0) 02534 this_drawing_angle-=360.0; 02535 while(this_drawing_angle<0.0) 02536 this_drawing_angle+=360.0; 02537 02538 /* calculate drawing coords of this host using good ol' geometry... */ 02539 x_coord=-(sin(-this_drawing_angle*(M_PI/180.0))*radius); 02540 y_coord=-(sin((90+this_drawing_angle)*(M_PI/180.0))*radius); 02541 02542 temp_host->x_2d=(int)x_coord; 02543 temp_host->y_2d=(int)y_coord; 02544 temp_host->have_2d_coords=TRUE; 02545 temp_host->should_be_drawn=TRUE; 02546 02547 /* recurse into child host ... */ 02548 calculate_circular_layer_coords(temp_host,current_drawing_angle+((available_angle-clipped_available_angle)/2),clipped_available_angle,layer+1,radius+CIRCULAR_DRAWING_RADIUS); 02549 02550 /* increment current drawing angle */ 02551 current_drawing_angle+=available_angle; 02552 } 02553 } 02554 02555 return; 02556 } 02557 02558 02559 02560 /* draws background "extras" for all hosts in circular markup layout */ 02561 void draw_circular_markup(void){ 02562 02563 /* calculate all host sections, starting with first layer */ 02564 draw_circular_layer_markup(NULL,0.0,360.0,1,CIRCULAR_DRAWING_RADIUS); 02565 02566 return; 02567 } 02568 02569 02570 /* draws background "extras" for all hosts in a particular "layer" in circular markup layout */ 02571 void draw_circular_layer_markup(host *parent, double start_angle, double useable_angle, int layer, int radius){ 02572 int parent_drawing_width=0; 02573 int this_drawing_width=0; 02574 int immediate_children=0; 02575 double current_drawing_angle=0.0; 02576 double available_angle=0.0; 02577 double clipped_available_angle=0.0; 02578 double average_child_angle=0.0; 02579 double x_coord[4]={0.0,0.0,0.0,0.0}; 02580 double y_coord[4]={0.0,0.0,0.0,0.0}; 02581 hoststatus *temp_hoststatus; 02582 host *temp_host; 02583 int x_offset=0; 02584 int y_offset=0; 02585 int center_x=0; 02586 int center_y=0; 02587 int bgcolor=0; 02588 double arc_start_angle=0.0; 02589 double arc_end_angle=0.0; 02590 int translated_x=0; 02591 int translated_y=0; 02592 02593 /* get the total number of immediate children to this host */ 02594 immediate_children=number_of_immediate_child_hosts(parent); 02595 02596 /* bail out if we're done */ 02597 if(immediate_children==0) 02598 return; 02599 02600 /* calculate total drawing "width" of parent host */ 02601 parent_drawing_width=max_child_host_drawing_width(parent); 02602 02603 /* calculate average angle given to each child host */ 02604 average_child_angle=(double)(useable_angle/(double)immediate_children); 02605 02606 /* calculate initial drawing angle */ 02607 current_drawing_angle=start_angle; 02608 02609 /* calculate coords for children */ 02610 for(temp_host=host_list;temp_host!=NULL;temp_host=temp_host->next){ 02611 02612 if(is_host_immediate_child_of_host(parent,temp_host)==TRUE){ 02613 02614 /* get drawing width of child host */ 02615 this_drawing_width=max_child_host_drawing_width(temp_host); 02616 02617 /* calculate angle this host gets for drawing */ 02618 available_angle=useable_angle*((double)this_drawing_width/(double)parent_drawing_width); 02619 02620 /* clip available angle if necessary */ 02621 /* this isn't really necessary, but helps keep things looking a bit more sane with less potential connection crossover */ 02622 clipped_available_angle=360.0/layer; 02623 if(available_angle<clipped_available_angle) 02624 clipped_available_angle=available_angle; 02625 02626 /* calculate drawing coords of "leftmost" divider using good ol' geometry... */ 02627 x_coord[0]=-(sin(-current_drawing_angle*(M_PI/180.0))*(radius-(CIRCULAR_DRAWING_RADIUS/2))); 02628 y_coord[0]=-(sin((90+current_drawing_angle)*(M_PI/180.0))*(radius-(CIRCULAR_DRAWING_RADIUS/2))); 02629 x_coord[1]=-(sin(-current_drawing_angle*(M_PI/180.0))*(radius+(CIRCULAR_DRAWING_RADIUS/2))); 02630 y_coord[1]=-(sin((90+current_drawing_angle)*(M_PI/180.0))*(radius+(CIRCULAR_DRAWING_RADIUS/2))); 02631 02632 /* calculate drawing coords of "rightmost" divider using good ol' geometry... */ 02633 x_coord[2]=-(sin((-(current_drawing_angle+available_angle))*(M_PI/180.0))*(radius-(CIRCULAR_DRAWING_RADIUS/2))); 02634 y_coord[2]=-(sin((90+current_drawing_angle+available_angle)*(M_PI/180.0))*(radius-(CIRCULAR_DRAWING_RADIUS/2))); 02635 x_coord[3]=-(sin((-(current_drawing_angle+available_angle))*(M_PI/180.0))*(radius+(CIRCULAR_DRAWING_RADIUS/2))); 02636 y_coord[3]=-(sin((90+current_drawing_angle+available_angle)*(M_PI/180.0))*(radius+(CIRCULAR_DRAWING_RADIUS/2))); 02637 02638 02639 x_offset=nagios_icon_x+(DEFAULT_NODE_WIDTH/2)-canvas_x; 02640 y_offset=nagios_icon_y+(DEFAULT_NODE_HEIGHT/2)-canvas_y; 02641 02642 /* if the host should be drawn */ 02643 /* this enforces the privacy of hosts that are not eligble to be drawn */ 02644 if(temp_host->should_be_drawn==TRUE){ 02645 02646 /* draw "slice" dividers */ 02647 if(immediate_children>1 || layer>1){ 02648 02649 /* draw "leftmost" divider */ 02650 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); 02651 02652 /* draw "rightmost" divider */ 02653 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); 02654 } 02655 02656 02657 /* determine arc drawing angles */ 02658 arc_start_angle=current_drawing_angle-90.0; 02659 while(arc_start_angle<0.0) 02660 arc_start_angle+=360.0; 02661 arc_end_angle=arc_start_angle+available_angle; 02662 02663 /* draw inner arc */ 02664 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); 02665 02666 /* draw outer arc */ 02667 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); 02668 02669 02670 /* determine center of "slice" and fill with appropriate color */ 02671 center_x=-(sin(-(current_drawing_angle+(available_angle/2.0))*(M_PI/180.0))*(radius)); 02672 center_y=-(sin((90+current_drawing_angle+(available_angle/2.0))*(M_PI/180.0))*(radius)); 02673 translated_x=center_x+x_offset; 02674 translated_y=center_y+y_offset; 02675 02676 /* determine background color */ 02677 temp_hoststatus=find_hoststatus(temp_host->name); 02678 if(temp_hoststatus==NULL) 02679 bgcolor=color_lightgrey; 02680 else if(temp_hoststatus->status==HOST_DOWN || temp_hoststatus->status==HOST_UNREACHABLE) 02681 bgcolor=color_lightred; 02682 else 02683 bgcolor=color_lightgreen; 02684 02685 02686 /* fill slice with background color */ 02687 /* the fill function only works with coordinates that are in bounds of the actual image */ 02688 if(translated_x>0 && translated_y>0 && translated_x<canvas_width && translated_y<canvas_height) 02689 gdImageFillToBorder(map_image,translated_x,translated_y,color_lightgrey,bgcolor); 02690 02691 } 02692 02693 /* recurse into child host ... */ 02694 draw_circular_layer_markup(temp_host,current_drawing_angle+((available_angle-clipped_available_angle)/2),clipped_available_angle,layer+1,radius+CIRCULAR_DRAWING_RADIUS); 02695 02696 /* increment current drawing angle */ 02697 current_drawing_angle+=available_angle; 02698 } 02699 } 02700 02701 return; 02702 } 02703