1 /**************************************************************************
2  *
3  * TRENDS.C -  Nagios State Trends CGI
4  *
5  *
6  * License:
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *************************************************************************/
21 
22 #include "../include/config.h"
23 #include "../include/common.h"
24 #include "../include/objects.h"
25 #include "../include/comments.h"
26 #include "../include/statusdata.h"
27 
28 #include "../include/cgiutils.h"
29 #include "../include/getcgi.h"
30 #include "../include/cgiauth.h"
31 
32 #include <gd.h>			/* Boutell's GD library function */
33 #include <gdfonts.h>		/* GD library small font definition */
34 
35 
36 /*#define DEBUG			1*/
37 
38 
39 extern char main_config_file[MAX_FILENAME_LENGTH];
40 extern char url_html_path[MAX_FILENAME_LENGTH];
41 extern char url_images_path[MAX_FILENAME_LENGTH];
42 extern char url_stylesheets_path[MAX_FILENAME_LENGTH];
43 extern char physical_images_path[MAX_FILENAME_LENGTH];
44 extern char *status_file;
45 
46 extern int     log_rotation_method;
47 
48 /* archived state types */
49 #define AS_CURRENT_STATE        -1   /* special case for initial assumed state */
50 #define AS_NO_DATA		0
51 #define AS_PROGRAM_END		1
52 #define AS_PROGRAM_START	2
53 #define AS_HOST_UP		3
54 #define AS_HOST_DOWN		4
55 #define AS_HOST_UNREACHABLE	5
56 #define AS_SVC_OK		6
57 #define AS_SVC_UNKNOWN		7
58 #define AS_SVC_WARNING		8
59 #define AS_SVC_CRITICAL		9
60 
61 #define AS_SOFT_STATE           1
62 #define AS_HARD_STATE           2
63 
64 /* display types */
65 #define DISPLAY_HOST_TRENDS	0
66 #define DISPLAY_SERVICE_TRENDS	1
67 #define DISPLAY_NO_TRENDS	2
68 
69 /* input types */
70 #define GET_INPUT_NONE          0
71 #define GET_INPUT_TARGET_TYPE   1
72 #define GET_INPUT_HOST_TARGET   2
73 #define GET_INPUT_SERVICE_TARGET 3
74 #define GET_INPUT_OPTIONS       4
75 
76 /* modes */
77 #define CREATE_HTML		0
78 #define CREATE_IMAGE		1
79 
80 /* standard report times */
81 #define TIMEPERIOD_CUSTOM	0
82 #define TIMEPERIOD_TODAY	1
83 #define TIMEPERIOD_YESTERDAY	2
84 #define TIMEPERIOD_THISWEEK	3
85 #define TIMEPERIOD_LASTWEEK	4
86 #define TIMEPERIOD_THISMONTH	5
87 #define TIMEPERIOD_LASTMONTH	6
88 #define TIMEPERIOD_THISQUARTER	7
89 #define TIMEPERIOD_LASTQUARTER	8
90 #define TIMEPERIOD_THISYEAR	9
91 #define TIMEPERIOD_LASTYEAR	10
92 #define TIMEPERIOD_LAST24HOURS	11
93 #define TIMEPERIOD_LAST7DAYS	12
94 #define TIMEPERIOD_LAST31DAYS	13
95 #define TIMEPERIOD_NEXTPROBLEM	14
96 
97 #define MIN_TIMESTAMP_SPACING	10
98 
99 #define MAX_ARCHIVE_SPREAD	65
100 #define MAX_ARCHIVE		65
101 #define MAX_ARCHIVE_BACKTRACKS	60
102 
103 authdata current_authdata;
104 
105 typedef struct archived_state_struct {
106 	time_t  time_stamp;
107 	int     entry_type;
108 	int     processed_state;
109 	int     state_type;
110 	char    *state_info;
111 	struct archived_state_struct *next;
112 	} archived_state;
113 
114 
115 archived_state *as_list = NULL;
116 
117 time_t t1;
118 time_t t2;
119 
120 int start_second = 0;
121 int start_minute = 0;
122 int start_hour = 0;
123 int start_day = 1;
124 int start_month = 1;
125 int start_year = 2000;
126 int end_second = 0;
127 int end_minute = 0;
128 int end_hour = 24;
129 int end_day = 1;
130 int end_month = 1;
131 int end_year = 2000;
132 
133 int display_type = DISPLAY_NO_TRENDS;
134 int mode = CREATE_HTML;
135 int input_type = GET_INPUT_NONE;
136 int timeperiod_type = TIMEPERIOD_LAST24HOURS;
137 int compute_time_from_parts = FALSE;
138 
139 int display_popups = TRUE;
140 int use_map = TRUE;
141 int small_image = FALSE;
142 int embedded = FALSE;
143 int display_header = TRUE;
144 
145 int assume_initial_states = TRUE;
146 int assume_state_retention = TRUE;
147 int assume_states_during_notrunning = TRUE;
148 int include_soft_states = FALSE;
149 
150 char *host_name = "";
151 char *svc_description = "";
152 
153 
154 
155 void graph_all_trend_data(void);
156 void graph_trend_data(int, int, time_t, time_t, time_t, char *);
157 void draw_timestamps(void);
158 void draw_timestamp(int, time_t);
159 void draw_time_breakdowns(void);
160 void draw_horizontal_grid_lines(void);
161 void draw_dashed_line(int, int, int, int, int);
162 
163 int convert_host_state_to_archived_state(int);
164 int convert_service_state_to_archived_state(int);
165 void add_archived_state(int, int, time_t, char *);
166 void free_archived_state_list(void);
167 void read_archived_state_data(void);
168 void scan_log_file_for_archived_state_data(char *);
169 void convert_timeperiod_to_times(int);
170 void compute_report_times(void);
171 void get_time_breakdown_string(unsigned long, unsigned long, char *, char *buffer, int);
172 
173 void document_header(int);
174 void document_footer(void);
175 int process_cgivars(void);
176 void write_popup_code(void);
177 
178 gdImagePtr trends_image = 0;
179 int color_white = 0;
180 int color_black = 0;
181 int color_red = 0;
182 int color_darkred = 0;
183 int color_green = 0;
184 int color_darkgreen = 0;
185 int color_yellow = 0;
186 int color_orange = 0;
187 FILE *image_file = NULL;
188 
189 int image_width = 900;
190 int image_height = 300;
191 
192 #define HOST_DRAWING_WIDTH	498
193 #define HOST_DRAWING_HEIGHT	70
194 #define HOST_DRAWING_X_OFFSET	116
195 #define HOST_DRAWING_Y_OFFSET	55
196 
197 #define SVC_DRAWING_WIDTH	498
198 #define SVC_DRAWING_HEIGHT	90
199 #define SVC_DRAWING_X_OFFSET	116
200 #define SVC_DRAWING_Y_OFFSET	55
201 
202 #define SMALL_HOST_DRAWING_WIDTH    500
203 #define SMALL_HOST_DRAWING_HEIGHT   20
204 #define SMALL_HOST_DRAWING_X_OFFSET 0
205 #define SMALL_HOST_DRAWING_Y_OFFSET 0
206 
207 #define SMALL_SVC_DRAWING_WIDTH     500
208 #define SMALL_SVC_DRAWING_HEIGHT    20
209 #define SMALL_SVC_DRAWING_X_OFFSET  0
210 #define SMALL_SVC_DRAWING_Y_OFFSET  0
211 
212 int drawing_width = 0;
213 int drawing_height = 0;
214 
215 int drawing_x_offset = 0;
216 int drawing_y_offset = 0;
217 
218 int last_known_state = AS_NO_DATA;
219 
220 int zoom_factor = 4;
221 int backtrack_archives = 2;
222 int earliest_archive = 0;
223 time_t earliest_time;
224 time_t latest_time;
225 int earliest_state = AS_NO_DATA;
226 int latest_state = AS_NO_DATA;
227 
228 int initial_assumed_host_state = AS_NO_DATA;
229 int initial_assumed_service_state = AS_NO_DATA;
230 
231 unsigned long time_up = 0L;
232 unsigned long time_down = 0L;
233 unsigned long time_unreachable = 0L;
234 unsigned long time_ok = 0L;
235 unsigned long time_warning = 0L;
236 unsigned long time_unknown = 0L;
237 unsigned long time_critical = 0L;
238 
239 int problem_found;
240 
241 
242 
main(int argc,char ** argv)243 int main(int argc, char **argv) {
244 	int result = OK;
245 	char temp_buffer[MAX_INPUT_BUFFER];
246 	char image_template[MAX_INPUT_BUFFER];
247 	char start_time[MAX_INPUT_BUFFER];
248 	char end_time[MAX_INPUT_BUFFER];
249 	int string_width;
250 	int string_height;
251 	char start_timestring[MAX_INPUT_BUFFER];
252 	char end_timestring[MAX_INPUT_BUFFER];
253 	host *temp_host;
254 	service *temp_service;
255 	int is_authorized = TRUE;
256 	int found = FALSE;
257 	int days, hours, minutes, seconds;
258 	char *first_service = NULL;
259 	time_t t3;
260 	time_t current_time;
261 	struct tm *t;
262 
263 
264 	/* reset internal CGI variables */
265 	reset_cgi_vars();
266 
267 	/* Initialize shared configuration variables */
268 	init_shared_cfg_vars(1);
269 
270 	/* read the CGI configuration file */
271 	result = read_cgi_config_file(get_cgi_config_location(), NULL);
272 	if(result == ERROR) {
273 		if(mode == CREATE_HTML) {
274 			document_header(FALSE);
275 			cgi_config_file_error(get_cgi_config_location());
276 			document_footer();
277 			}
278 		return ERROR;
279 		}
280 
281 	/* read the main configuration file */
282 	result = read_main_config_file(main_config_file);
283 	if(result == ERROR) {
284 		if(mode == CREATE_HTML) {
285 			document_header(FALSE);
286 			main_config_file_error(main_config_file);
287 			document_footer();
288 			}
289 		return ERROR;
290 		}
291 
292 
293 	/* initialize time period to last 24 hours */
294 	time(&current_time);
295 	t2 = current_time;
296 	t1 = (time_t)(current_time - (60 * 60 * 24));
297 
298 	/* default number of backtracked archives */
299 	switch(log_rotation_method) {
300 		case LOG_ROTATION_MONTHLY:
301 			backtrack_archives = 1;
302 			break;
303 		case LOG_ROTATION_WEEKLY:
304 			backtrack_archives = 2;
305 			break;
306 		case LOG_ROTATION_DAILY:
307 			backtrack_archives = 4;
308 			break;
309 		case LOG_ROTATION_HOURLY:
310 			backtrack_archives = 8;
311 			break;
312 		default:
313 			backtrack_archives = 2;
314 			break;
315 		}
316 
317 	/* get the arguments passed in the URL */
318 	process_cgivars();
319 
320 	/* get authentication information */
321 	get_authentication_information(&current_authdata);
322 
323 	result = read_all_object_configuration_data(main_config_file, READ_ALL_OBJECT_DATA);
324 	if(result == ERROR) {
325 		if(mode == CREATE_HTML) {
326 			document_header(FALSE);
327 			object_data_error();
328 			document_footer();
329 			}
330 		return ERROR;
331 		}
332 
333 	/* read all status data */
334 	result = read_all_status_data(status_file, READ_ALL_STATUS_DATA);
335 	if(result == ERROR) {
336 		if(mode == CREATE_HTML) {
337 			document_header(FALSE);
338 			status_data_error();
339 			document_footer();
340 			}
341 		return ERROR;
342 		}
343 
344 	document_header(TRUE);
345 
346 	if(compute_time_from_parts == TRUE)
347 		compute_report_times();
348 
349 	/* make sure times are sane, otherwise swap them */
350 	if(t2 < t1) {
351 		t3 = t2;
352 		t2 = t1;
353 		t1 = t3;
354 		}
355 
356 	/* don't let user create reports in the future */
357 	if(t2 > current_time) {
358 		t2 = current_time;
359 		if(t1 > t2)
360 			t1 = t2 - (60 * 60 * 24);
361 		}
362 
363 	if(mode == CREATE_HTML && display_header == TRUE) {
364 		time_t old_t1 = t1, old_t2 = t2;
365 
366 		/* begin top table */
367 		printf("<table border=0 width=100%% cellspacing=0 cellpadding=0>\n");
368 		printf("<tr>\n");
369 
370 		/* left column of the first row */
371 		printf("<td align=left valign=top width=33%%>\n");
372 
373 		if(display_type == DISPLAY_HOST_TRENDS)
374 			snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host State Trends");
375 		else if(display_type == DISPLAY_SERVICE_TRENDS)
376 			snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Service State Trends");
377 		else
378 			snprintf(temp_buffer, sizeof(temp_buffer) - 1, "Host and Service State Trends");
379 		temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
380 		display_info_table(temp_buffer, FALSE, &current_authdata);
381 
382 		if(timeperiod_type == TIMEPERIOD_NEXTPROBLEM) {
383 			archived_state *temp_as;
384 			time_t problem_t1, problem_t2 = 0;
385 
386 			t1 = t2;
387 			t2 = current_time;
388 			read_archived_state_data();
389 
390 			problem_found = FALSE;
391 			if(display_type == DISPLAY_HOST_TRENDS) {
392 				for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
393 					if((temp_as->entry_type == SD_HOST_DOWN || temp_as->entry_type == SD_HOST_UNREACHABLE) && temp_as->time_stamp > t1) {
394 						problem_t1 = temp_as->time_stamp;
395 						problem_found = TRUE;
396 						break;
397 						}
398 					}
399 				if(problem_found == TRUE) {
400 					for(; temp_as != NULL; temp_as = temp_as->next) {
401 						if(temp_as->entry_type == AS_HOST_UP && temp_as->time_stamp > problem_t1) {
402 							problem_t2 = temp_as->time_stamp;
403 							break;
404 							}
405 						}
406 					}
407 				}
408 			else {
409 				for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
410 					if((temp_as->entry_type == AS_SVC_UNKNOWN || temp_as->entry_type == AS_SVC_CRITICAL || temp_as->entry_type == AS_SVC_WARNING) && temp_as->time_stamp > t1) {
411 						problem_t1 = temp_as->time_stamp;
412 						problem_found = TRUE;
413 						break;
414 						}
415 					}
416 				if(problem_found == TRUE) {
417 					for(; temp_as != NULL; temp_as = temp_as->next) {
418 						if(temp_as->entry_type == AS_SVC_OK && temp_as->time_stamp > problem_t1) {
419 							problem_t2 = temp_as->time_stamp;
420 							break;
421 							}
422 						}
423 					}
424 				}
425 			if(problem_found == TRUE) {
426 				time_t margin;
427 
428 				if(problem_t2 == 0) {
429 					margin = 12 * 60 * 60;
430 					problem_t2 = problem_t1;
431 					}
432 				else
433 					margin = (problem_t2 - problem_t1) / 2;
434 
435 				t1 = problem_t1 - margin;
436 				t2 = problem_t2 + margin;
437 				}
438 			}
439 
440 		if(timeperiod_type == TIMEPERIOD_NEXTPROBLEM && problem_found == FALSE) {
441 			t1 = old_t1;
442 			t2 = old_t2;
443 			}
444 
445 		if(display_type != DISPLAY_NO_TRENDS && input_type == GET_INPUT_NONE) {
446 
447 			printf("<TABLE BORDER=1 CELLPADDING=0 CELLSPACING=0 CLASS='linkBox'>\n");
448 			printf("<TR><TD CLASS='linkBox'>\n");
449 
450 			if(display_type == DISPLAY_HOST_TRENDS) {
451 				printf("<a href='%s?host=%s&t1=%lu&t2=%lu&includesoftstates=%s&assumestateretention=%s&assumeinitialstates=%s&assumestatesduringnotrunning=%s&initialassumedhoststate=%d&backtrack=%d&show_log_entries'>View Availability Report For This Host</a><BR>\n", AVAIL_CGI, url_encode(host_name), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_host_state, backtrack_archives);
452 #ifdef USE_HISTOGRAM
453 				printf("<a href='%s?host=%s&t1=%lu&t2=%lu&assumestateretention=%s'>View Alert Histogram For This Host</a><BR>\n", HISTOGRAM_CGI, url_encode(host_name), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
454 #endif
455 				printf("<a href='%s?host=%s'>View Status Detail For This Host</a><BR>\n", STATUS_CGI, url_encode(host_name));
456 				printf("<a href='%s?host=%s'>View Alert History For This Host</a><BR>\n", HISTORY_CGI, url_encode(host_name));
457 				printf("<a href='%s?host=%s'>View Notifications For This Host</a><BR>\n", NOTIFICATIONS_CGI, url_encode(host_name));
458 				}
459 			else {
460 #ifdef LEGACY_GRAPHICAL_CGIS
461 				printf("<a href='%s?host=%s&t1=%lu&t2=%lu&includesoftstates=%s&assumestateretention=%s&assumeinitialstates=%s&assumestatesduringnotrunning=%s&initialassumedservicestate=%d&backtrack=%d'>View Trends For This Host</a><BR>\n", TRENDS_CGI, url_encode(host_name), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives);
462 #else
463 				printf("<a href='%s?host=%s&t1=%lu&t2=%lu&includesoftstates=%s&assumestateretention=%s&assumeinitialstates=%s&assumestatesduringnotrunning=%s&initialassumedservicestate=%d&backtrack=%d'>View Trends For This Host</a><BR>\n", LEGACY_TRENDS_CGI, url_encode(host_name), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives);
464 #endif
465 				printf("<a href='%s?host=%s", AVAIL_CGI, url_encode(host_name));
466 				printf("&service=%s&t1=%lu&t2=%lu&assumestateretention=%s&includesoftstates=%s&assumeinitialstates=%s&assumestatesduringnotrunning=%s&initialassumedservicestate=%d&backtrack=%d&show_log_entries'>View Availability Report For This Service</a><BR>\n", url_encode(svc_description), t1, t2, (include_soft_states == TRUE) ? "yes" : "no", (assume_state_retention == TRUE) ? "yes" : "no", (assume_initial_states == TRUE) ? "yes" : "no", (assume_states_during_notrunning == TRUE) ? "yes" : "no", initial_assumed_service_state, backtrack_archives);
467 				printf("<a href='%s?host=%s", HISTOGRAM_CGI, url_encode(host_name));
468 				printf("&service=%s&t1=%lu&t2=%lu&assumestateretention=%s'>View Alert Histogram For This Service</a><BR>\n", url_encode(svc_description), t1, t2, (assume_state_retention == TRUE) ? "yes" : "no");
469 				printf("<A HREF='%s?host=%s&", HISTORY_CGI, url_encode(host_name));
470 				printf("service=%s'>View Alert History For This Service</A><BR>\n", url_encode(svc_description));
471 				printf("<A HREF='%s?host=%s&", NOTIFICATIONS_CGI, url_encode(host_name));
472 				printf("service=%s'>View Notifications For This Service</A><BR>\n", url_encode(svc_description));
473 				}
474 
475 			printf("</TD></TR>\n");
476 			printf("</TABLE>\n");
477 			}
478 
479 		printf("</td>\n");
480 
481 		/* center column of top row */
482 		printf("<td align=center valign=top width=33%%>\n");
483 
484 		if(display_type != DISPLAY_NO_TRENDS && input_type == GET_INPUT_NONE) {
485 
486 			printf("<DIV ALIGN=CENTER CLASS='dataTitle'>\n");
487 			if(display_type == DISPLAY_HOST_TRENDS)
488 				printf("Host '%s'", host_name);
489 			else if(display_type == DISPLAY_SERVICE_TRENDS)
490 				printf("Service '%s' On Host '%s'", svc_description, host_name);
491 			printf("</DIV>\n");
492 
493 			printf("<BR>\n");
494 
495 			printf("<IMG SRC='%s%s' BORDER=0 ALT='%s State Trends' TITLE='%s State Trends'>\n", url_images_path, TRENDS_ICON, (display_type == DISPLAY_HOST_TRENDS) ? "Host" : "Service", (display_type == DISPLAY_HOST_TRENDS) ? "Host" : "Service");
496 
497 			printf("<BR CLEAR=ALL>\n");
498 
499 			get_time_string(&t1, start_timestring, sizeof(start_timestring) - 1, SHORT_DATE_TIME);
500 			get_time_string(&t2, end_timestring, sizeof(end_timestring) - 1, SHORT_DATE_TIME);
501 			printf("<div align=center class='reportRange'>%s to %s</div>\n", start_timestring, end_timestring);
502 
503 			get_time_breakdown((time_t)(t2 - t1), &days, &hours, &minutes, &seconds);
504 			printf("<div align=center class='reportDuration'>Duration: %dd %dh %dm %ds</div>\n", days, hours, minutes, seconds);
505 			}
506 
507 		printf("</td>\n");
508 
509 		/* right hand column of top row */
510 		printf("<td align=right valign=bottom width=33%%>\n");
511 
512 #ifdef LEGACY_GRAPHICAL_CGIS
513 		printf("<form method=\"GET\" action=\"%s\">\n", TRENDS_CGI);
514 #else
515 		printf("<form method=\"GET\" action=\"%s\">\n", LEGACY_TRENDS_CGI);
516 #endif
517 		printf("<table border=0 CLASS='optBox'>\n");
518 
519 		if(display_type != DISPLAY_NO_TRENDS && input_type == GET_INPUT_NONE) {
520 
521 			printf("<tr><td CLASS='optBoxItem' valign=top align=left>First assumed %s state:</td><td CLASS='optBoxItem' valign=top align=left>Backtracked archives:</td></tr>\n", (display_type == DISPLAY_HOST_TRENDS) ? "host" : "service");
522 			printf("<tr><td CLASS='optBoxItem' valign=top align=left>");
523 			if(display_popups == FALSE)
524 				printf("<input type='hidden' name='nopopups' value=''>\n");
525 			if(use_map == FALSE)
526 				printf("<input type='hidden' name='nomap' value=''>\n");
527 			printf("<input type='hidden' name='t1' value='%lu'>\n", (unsigned long)t1);
528 			printf("<input type='hidden' name='t2' value='%lu'>\n", (unsigned long)t2);
529 			printf("<input type='hidden' name='host' value='%s'>\n", escape_string(host_name));
530 			if(display_type == DISPLAY_SERVICE_TRENDS)
531 				printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
532 
533 			printf("<input type='hidden' name='assumeinitialstates' value='%s'>\n", (assume_initial_states == TRUE) ? "yes" : "no");
534 			printf("<input type='hidden' name='assumestateretention' value='%s'>\n", (assume_state_retention == TRUE) ? "yes" : "no");
535 			printf("<input type='hidden' name='assumestatesduringnotrunning' value='%s'>\n", (assume_states_during_notrunning == TRUE) ? "yes" : "no");
536 			printf("<input type='hidden' name='includesoftstates' value='%s'>\n", (include_soft_states == TRUE) ? "yes" : "no");
537 
538 			if(display_type == DISPLAY_HOST_TRENDS) {
539 				printf("<input type='hidden' name='initialassumedservicestate' value='%d'>", initial_assumed_service_state);
540 				printf("<select name='initialassumedhoststate'>\n");
541 				printf("<option value=%d %s>Unspecified\n", AS_NO_DATA, (initial_assumed_host_state == AS_NO_DATA) ? "SELECTED" : "");
542 				printf("<option value=%d %s>Current State\n", AS_CURRENT_STATE, (initial_assumed_host_state == AS_CURRENT_STATE) ? "SELECTED" : "");
543 				printf("<option value=%d %s>Host Up\n", AS_HOST_UP, (initial_assumed_host_state == AS_HOST_UP) ? "SELECTED" : "");
544 				printf("<option value=%d %s>Host Down\n", AS_HOST_DOWN, (initial_assumed_host_state == AS_HOST_DOWN) ? "SELECTED" : "");
545 				printf("<option value=%d %s>Host Unreachable\n", AS_HOST_UNREACHABLE, (initial_assumed_host_state == AS_HOST_UNREACHABLE) ? "SELECTED" : "");
546 				}
547 			else {
548 				printf("<input type='hidden' name='initialassumedhoststate' value='%d'>", initial_assumed_host_state);
549 				printf("<select name='initialassumedservicestate'>\n");
550 				printf("<option value=%d %s>Unspecified\n", AS_NO_DATA, (initial_assumed_service_state == AS_NO_DATA) ? "SELECTED" : "");
551 				printf("<option value=%d %s>Current State\n", AS_CURRENT_STATE, (initial_assumed_service_state == AS_CURRENT_STATE) ? "SELECTED" : "");
552 				printf("<option value=%d %s>Service Ok\n", AS_SVC_OK, (initial_assumed_service_state == AS_SVC_OK) ? "SELECTED" : "");
553 				printf("<option value=%d %s>Service Warning\n", AS_SVC_WARNING, (initial_assumed_service_state == AS_SVC_WARNING) ? "SELECTED" : "");
554 				printf("<option value=%d %s>Service Unknown\n", AS_SVC_UNKNOWN, (initial_assumed_service_state == AS_SVC_UNKNOWN) ? "SELECTED" : "");
555 				printf("<option value=%d %s>Service Critical\n", AS_SVC_CRITICAL, (initial_assumed_service_state == AS_SVC_CRITICAL) ? "SELECTED" : "");
556 				}
557 			printf("</select>\n");
558 			printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
559 			printf("<input type='text' name='backtrack' size='2' maxlength='2' value='%d'>\n", backtrack_archives);
560 			printf("</td></tr>\n");
561 
562 			printf("<tr><td CLASS='optBoxItem' valign=top align=left>Report period:</td><td CLASS='optBoxItem' valign=top align=left>Zoom factor:</td></tr>\n");
563 			printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
564 			printf("<select name='timeperiod'>\n");
565 			printf("<option>[ Current time range ]\n");
566 			printf("<option value=today %s>Today\n", (timeperiod_type == TIMEPERIOD_TODAY) ? "SELECTED" : "");
567 			printf("<option value=last24hours %s>Last 24 Hours\n", (timeperiod_type == TIMEPERIOD_LAST24HOURS) ? "SELECTED" : "");
568 			printf("<option value=yesterday %s>Yesterday\n", (timeperiod_type == TIMEPERIOD_YESTERDAY) ? "SELECTED" : "");
569 			printf("<option value=thisweek %s>This Week\n", (timeperiod_type == TIMEPERIOD_THISWEEK) ? "SELECTED" : "");
570 			printf("<option value=last7days %s>Last 7 Days\n", (timeperiod_type == TIMEPERIOD_LAST7DAYS) ? "SELECTED" : "");
571 			printf("<option value=lastweek %s>Last Week\n", (timeperiod_type == TIMEPERIOD_LASTWEEK) ? "SELECTED" : "");
572 			printf("<option value=thismonth %s>This Month\n", (timeperiod_type == TIMEPERIOD_THISMONTH) ? "SELECTED" : "");
573 			printf("<option value=last31days %s>Last 31 Days\n", (timeperiod_type == TIMEPERIOD_LAST31DAYS) ? "SELECTED" : "");
574 			printf("<option value=lastmonth %s>Last Month\n", (timeperiod_type == TIMEPERIOD_LASTMONTH) ? "SELECTED" : "");
575 			printf("<option value=thisyear %s>This Year\n", (timeperiod_type == TIMEPERIOD_THISYEAR) ? "SELECTED" : "");
576 			printf("<option value=lastyear %s>Last Year\n", (timeperiod_type == TIMEPERIOD_LASTYEAR) ? "SELECTED" : "");
577 			if(display_type == DISPLAY_HOST_TRENDS)
578 				printf("<option value=nextproblem %s>Next Host Problem\n", (timeperiod_type == TIMEPERIOD_NEXTPROBLEM) ? "SELECTED" : "");
579 			else
580 				printf("<option value=nextproblem %s>Next Service Problem\n", (timeperiod_type == TIMEPERIOD_NEXTPROBLEM) ? "SELECTED" : "");
581 			printf("</select>\n");
582 			printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
583 			printf("<select name='zoom'>\n");
584 			printf("<option value=%d selected>%d\n", zoom_factor, zoom_factor);
585 			printf("<option value=+2>+2\n");
586 			printf("<option value=+3>+3\n");
587 			printf("<option value=+4>+4\n");
588 			printf("<option value=-2>-2\n");
589 			printf("<option value=-3>-3\n");
590 			printf("<option value=-4>-4\n");
591 			printf("</select>\n");
592 			printf("</td></tr>\n");
593 
594 			printf("<tr><td CLASS='optBoxItem' valign=top align=left>\n");
595 			printf("</td><td CLASS='optBoxItem' valign=top align=left>\n");
596 			printf("<input type='submit' value='Update'>\n");
597 			printf("</td></tr>\n");
598 			}
599 
600 		/* display context-sensitive help */
601 		printf("<tr><td></td><td align=right valign=bottom>\n");
602 		if(display_type != DISPLAY_NO_TRENDS && input_type == GET_INPUT_NONE) {
603 			if(display_type == DISPLAY_HOST_TRENDS)
604 				display_context_help(CONTEXTHELP_TRENDS_HOST);
605 			else
606 				display_context_help(CONTEXTHELP_TRENDS_SERVICE);
607 			}
608 		else if(display_type == DISPLAY_NO_TRENDS || input_type != GET_INPUT_NONE) {
609 			if(input_type == GET_INPUT_NONE)
610 				display_context_help(CONTEXTHELP_TRENDS_MENU1);
611 			else if(input_type == GET_INPUT_TARGET_TYPE)
612 				display_context_help(CONTEXTHELP_TRENDS_MENU1);
613 			else if(input_type == GET_INPUT_HOST_TARGET)
614 				display_context_help(CONTEXTHELP_TRENDS_MENU2);
615 			else if(input_type == GET_INPUT_SERVICE_TARGET)
616 				display_context_help(CONTEXTHELP_TRENDS_MENU3);
617 			else if(input_type == GET_INPUT_OPTIONS)
618 				display_context_help(CONTEXTHELP_TRENDS_MENU4);
619 			}
620 		printf("</td></tr>\n");
621 
622 		printf("</table>\n");
623 		printf("</form>\n");
624 
625 		printf("</td>\n");
626 
627 		/* end of top table */
628 		printf("</tr>\n");
629 		printf("</table>\n");
630 		}
631 
632 
633 #ifndef DEBUG
634 
635 	/* check authorization... */
636 	if(display_type == DISPLAY_HOST_TRENDS) {
637 		temp_host = find_host(host_name);
638 		if(temp_host == NULL || is_authorized_for_host(temp_host, &current_authdata) == FALSE)
639 			is_authorized = FALSE;
640 		}
641 	else if(display_type == DISPLAY_SERVICE_TRENDS) {
642 		temp_service = find_service(host_name, svc_description);
643 		if(temp_service == NULL || is_authorized_for_service(temp_service, &current_authdata) == FALSE)
644 			is_authorized = FALSE;
645 		}
646 	if(is_authorized == FALSE) {
647 
648 		if(mode == CREATE_HTML)
649 			printf("<P><DIV ALIGN=CENTER CLASS='errorMessage'>It appears as though you are not authorized to view information for the specified %s...</DIV></P>\n", (display_type == DISPLAY_HOST_TRENDS) ? "host" : "service");
650 
651 		document_footer();
652 		free_memory();
653 		return ERROR;
654 		}
655 #endif
656 
657 
658 	if(timeperiod_type == TIMEPERIOD_NEXTPROBLEM && problem_found == FALSE) {
659 		printf("<P><DIV ALIGN=CENTER CLASS='errorMessage'>No problem found between end of display and end of recording</DIV></P>\n");
660 
661 		document_footer();
662 		free_memory();
663 		return ERROR;
664 		}
665 	/* set drawing parameters, etc */
666 
667 	if(small_image == TRUE) {
668 		image_height = 20;
669 		image_width = 500;
670 		}
671 	else {
672 		image_height = 300;
673 		image_width = 900;
674 		}
675 
676 	if(display_type == DISPLAY_HOST_TRENDS) {
677 
678 		if(small_image == TRUE) {
679 			drawing_width = SMALL_HOST_DRAWING_WIDTH;
680 			drawing_height = SMALL_HOST_DRAWING_HEIGHT;
681 			drawing_x_offset = SMALL_HOST_DRAWING_X_OFFSET;
682 			drawing_y_offset = SMALL_HOST_DRAWING_Y_OFFSET;
683 			}
684 		else {
685 			drawing_width = HOST_DRAWING_WIDTH;
686 			drawing_height = HOST_DRAWING_HEIGHT;
687 			drawing_x_offset = HOST_DRAWING_X_OFFSET;
688 			drawing_y_offset = HOST_DRAWING_Y_OFFSET;
689 			}
690 		}
691 	else if(display_type == DISPLAY_SERVICE_TRENDS) {
692 
693 		if(small_image == TRUE) {
694 			drawing_width = SMALL_SVC_DRAWING_WIDTH;
695 			drawing_height = SMALL_SVC_DRAWING_HEIGHT;
696 			drawing_x_offset = SMALL_SVC_DRAWING_X_OFFSET;
697 			drawing_y_offset = SMALL_SVC_DRAWING_Y_OFFSET;
698 			}
699 		else {
700 			drawing_width = SVC_DRAWING_WIDTH;
701 			drawing_height = SVC_DRAWING_HEIGHT;
702 			drawing_x_offset = SVC_DRAWING_X_OFFSET;
703 			drawing_y_offset = SVC_DRAWING_Y_OFFSET;
704 			}
705 		}
706 
707 	/* last known state should always be initially set to indeterminate! */
708 	last_known_state = AS_NO_DATA;
709 
710 
711 	/* initialize PNG image */
712 	if(display_type != DISPLAY_NO_TRENDS && mode == CREATE_IMAGE) {
713 
714 		if(small_image == TRUE) {
715 			trends_image = gdImageCreate(image_width, image_height);
716 			if(trends_image == NULL) {
717 #ifdef DEBUG
718 				printf("Error: Could not allocate memory for image\n");
719 #endif
720 				return ERROR;
721 				}
722 			}
723 
724 		else {
725 
726 			if(display_type == DISPLAY_HOST_TRENDS)
727 				snprintf(image_template, sizeof(image_template) - 1, "%s/trendshost.png", physical_images_path);
728 			else
729 				snprintf(image_template, sizeof(image_template) - 1, "%s/trendssvc.png", physical_images_path);
730 			image_template[sizeof(image_template) - 1] = '\x0';
731 
732 			/* allocate buffer for storing image */
733 			trends_image = NULL;
734 			image_file = fopen(image_template, "r");
735 			if(image_file != NULL) {
736 				trends_image = gdImageCreateFromPng(image_file);
737 				fclose(image_file);
738 				}
739 			if(trends_image == NULL)
740 				trends_image = gdImageCreate(image_width, image_height);
741 			if(trends_image == NULL) {
742 #ifdef DEBUG
743 				printf("Error: Could not allocate memory for image\n");
744 #endif
745 				return ERROR;
746 				}
747 			}
748 
749 		/* allocate colors used for drawing */
750 		color_white = gdImageColorAllocate(trends_image, 255, 255, 255);
751 		color_black = gdImageColorAllocate(trends_image, 0, 0, 0);
752 		color_red = gdImageColorAllocate(trends_image, 255, 0, 0);
753 		color_darkred = gdImageColorAllocate(trends_image, 128, 0, 0);
754 		color_green = gdImageColorAllocate(trends_image, 0, 210, 0);
755 		color_darkgreen = gdImageColorAllocate(trends_image, 0, 128, 0);
756 		color_yellow = gdImageColorAllocate(trends_image, 176, 178, 20);
757 		color_orange = gdImageColorAllocate(trends_image, 255, 100, 25);
758 
759 		/* set transparency index */
760 		gdImageColorTransparent(trends_image, color_white);
761 
762 		/* make sure the graphic is interlaced */
763 		gdImageInterlace(trends_image, 1);
764 
765 		if(small_image == FALSE) {
766 
767 			/* title */
768 			snprintf(start_time, sizeof(start_time) - 1, "%s", ctime(&t1));
769 			start_time[sizeof(start_time) - 1] = '\x0';
770 			start_time[strlen(start_time) - 1] = '\x0';
771 			snprintf(end_time, sizeof(end_time) - 1, "%s", ctime(&t2));
772 			end_time[sizeof(end_time) - 1] = '\x0';
773 			end_time[strlen(end_time) - 1] = '\x0';
774 
775 			string_height = gdFontSmall->h;
776 
777 			if(display_type == DISPLAY_HOST_TRENDS)
778 				snprintf(temp_buffer, sizeof(temp_buffer) - 1, "State History For Host '%s'", host_name);
779 			else
780 				snprintf(temp_buffer, sizeof(temp_buffer) - 1, "State History For Service '%s' On Host '%s'", svc_description, host_name);
781 			temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
782 			string_width = gdFontSmall->w * strlen(temp_buffer);
783 			gdImageString(trends_image, gdFontSmall, (drawing_width / 2) - (string_width / 2) + drawing_x_offset, string_height, (unsigned char *)temp_buffer, color_black);
784 
785 			snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s to %s", start_time, end_time);
786 			temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
787 			string_width = gdFontSmall->w * strlen(temp_buffer);
788 			gdImageString(trends_image, gdFontSmall, (drawing_width / 2) - (string_width / 2) + drawing_x_offset, (string_height * 2) + 5, (unsigned char *)temp_buffer, color_black);
789 
790 
791 			/* first time stamp */
792 			snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s", start_time);
793 			temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
794 			string_width = gdFontSmall->w * strlen(temp_buffer);
795 			gdImageStringUp(trends_image, gdFontSmall, drawing_x_offset - (string_height / 2), drawing_y_offset + drawing_height + string_width + 5, (unsigned char *)temp_buffer, color_black);
796 			}
797 		}
798 
799 	if(display_type != DISPLAY_NO_TRENDS && input_type == GET_INPUT_NONE) {
800 
801 
802 		if(mode == CREATE_IMAGE || (mode == CREATE_HTML && use_map == TRUE)) {
803 
804 			/* read in all necessary archived state data */
805 			read_archived_state_data();
806 
807 			/* graph archived state trend data */
808 			graph_all_trend_data();
809 			}
810 
811 		/* print URL to image */
812 		if(mode == CREATE_HTML) {
813 
814 			printf("<BR><BR>\n");
815 			printf("<DIV ALIGN=CENTER>\n");
816 #ifdef LEGACY_GRAPHICAL_CGIS
817 			printf("<IMG SRC='%s?createimage&t1=%lu&t2=%lu", TRENDS_CGI, (unsigned long)t1, (unsigned long)t2);
818 #else
819 			printf("<IMG SRC='%s?createimage&t1=%lu&t2=%lu", LEGACY_TRENDS_CGI, (unsigned long)t1, (unsigned long)t2);
820 #endif
821 			printf("&assumeinitialstates=%s", (assume_initial_states == TRUE) ? "yes" : "no");
822 			printf("&assumestatesduringnotrunning=%s", (assume_states_during_notrunning == TRUE) ? "yes" : "no");
823 			printf("&initialassumedhoststate=%d", initial_assumed_host_state);
824 			printf("&initialassumedservicestate=%d", initial_assumed_service_state);
825 			printf("&assumestateretention=%s", (assume_state_retention == TRUE) ? "yes" : "no");
826 			printf("&includesoftstates=%s", (include_soft_states == TRUE) ? "yes" : "no");
827 			printf("&host=%s", url_encode(host_name));
828 			if(display_type == DISPLAY_SERVICE_TRENDS)
829 				printf("&service=%s", url_encode(svc_description));
830 			if(backtrack_archives > 0)
831 				printf("&backtrack=%d", backtrack_archives);
832 			printf("&zoom=%d", zoom_factor);
833 			printf("' BORDER=0 name='trendsimage' useMap='#trendsmap' width=%d>\n", image_width);
834 			printf("</DIV>\n");
835 			}
836 
837 		if(mode == CREATE_IMAGE || (mode == CREATE_HTML && use_map == TRUE)) {
838 
839 			/* draw timestamps */
840 			draw_timestamps();
841 
842 			/* draw horizontal lines */
843 			draw_horizontal_grid_lines();
844 
845 			/* draw state time breakdowns */
846 			draw_time_breakdowns();
847 			}
848 
849 		if(mode == CREATE_IMAGE) {
850 
851 			/* use STDOUT for writing the image data... */
852 			image_file = stdout;
853 
854 #ifndef DEBUG
855 			/* write the image to file */
856 			gdImagePng(trends_image, image_file);
857 #endif
858 #ifdef DEBUG
859 			image_file = fopen("trends.png", "w");
860 			if(image_file == NULL)
861 				printf("Could not open trends.png for writing!\n");
862 			else {
863 				gdImagePng(trends_image, image_file);
864 				fclose(image_file);
865 				}
866 #endif
867 
868 			/* free memory allocated to image */
869 			gdImageDestroy(trends_image);
870 			}
871 		}
872 
873 
874 	/* show user a selection of hosts and services to choose from... */
875 	if(display_type == DISPLAY_NO_TRENDS || input_type != GET_INPUT_NONE) {
876 
877 		/* ask the user for what host they want a report for */
878 		if(input_type == GET_INPUT_HOST_TARGET) {
879 
880 			printf("<P><DIV ALIGN=CENTER>\n");
881 			printf("<DIV CLASS='reportSelectTitle'>Step 2: Select Host</DIV>\n");
882 			printf("</DIV></P>\n");
883 
884 			printf("<P><DIV ALIGN=CENTER>\n");
885 
886 #ifdef LEGACY_GRAPHICAL_CGIS
887 			printf("<form method=\"GET\" action=\"%s\">\n", TRENDS_CGI);
888 #else
889 			printf("<form method=\"GET\" action=\"%s\">\n", LEGACY_TRENDS_CGI);
890 #endif
891 			printf("<input type='hidden' name='input' value='getoptions'>\n");
892 			printf("<TABLE BORDER=0 cellspacing=0 cellpadding=10>\n");
893 
894 			printf("<tr><td class='reportSelectSubTitle' valign=center>Host:</td>\n");
895 			printf("<td class='reportSelectItem' valign=center>\n");
896 			printf("<select name='host'>\n");
897 
898 			for(temp_host = host_list; temp_host != NULL; temp_host = temp_host->next) {
899 				if(is_authorized_for_host(temp_host, &current_authdata) == TRUE)
900 					printf("<option value='%s'>%s\n", escape_string(temp_host->name), temp_host->name);
901 				}
902 
903 			printf("</select>\n");
904 			printf("</td></tr>\n");
905 
906 			printf("<tr><td></td><td class='reportSelectItem'>\n");
907 			printf("<input type='submit' value='Continue to Step 3'>\n");
908 			printf("</td></tr>\n");
909 
910 			printf("</TABLE>\n");
911 			printf("</form>\n");
912 
913 			printf("</DIV></P>\n");
914 			}
915 
916 		/* ask the user for what service they want a report for */
917 		else if(input_type == GET_INPUT_SERVICE_TARGET) {
918 
919 			printf("<SCRIPT LANGUAGE='JavaScript'>\n");
920 			printf("function gethostname(hostindex){\n");
921 			printf("hostnames=[");
922 
923 			for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
924 				if(is_authorized_for_service(temp_service, &current_authdata) == TRUE) {
925 					if(found == TRUE)
926 						printf(",");
927 					else
928 						first_service = temp_service->host_name;
929 					printf(" \"%s\"", temp_service->host_name);
930 					found = TRUE;
931 					}
932 				}
933 
934 			printf(" ]\n");
935 			printf("return hostnames[hostindex];\n");
936 			printf("}\n");
937 			printf("</SCRIPT>\n");
938 
939 
940 			printf("<P><DIV ALIGN=CENTER>\n");
941 			printf("<DIV CLASS='reportSelectTitle'>Step 2: Select Service</DIV>\n");
942 			printf("</DIV></P>\n");
943 
944 			printf("<P><DIV ALIGN=CENTER>\n");
945 
946 #ifdef LEGACY_GRAPHICAL_CGIS
947 			printf("<form method=\"GET\" action=\"%s\" name=\"serviceform\">\n", TRENDS_CGI);
948 #else
949 			printf("<form method=\"GET\" action=\"%s\" name=\"serviceform\">\n", LEGACY_TRENDS_CGI);
950 #endif
951 			printf("<input type='hidden' name='input' value='getoptions'>\n");
952 			printf("<input type='hidden' name='host' value='%s'>\n", (first_service == NULL) ? "unknown" : (char *)escape_string(first_service));
953 			printf("<TABLE BORDER=0 cellpadding=5>\n");
954 
955 			printf("<tr><td class='reportSelectSubTitle'>Service:</td>\n");
956 			printf("<td class='reportSelectItem'>\n");
957 			printf("<select name='service' onFocus='document.serviceform.host.value=gethostname(this.selectedIndex);' onChange='document.serviceform.host.value=gethostname(this.selectedIndex);'>\n");
958 
959 			for(temp_service = service_list; temp_service != NULL; temp_service = temp_service->next) {
960 				if(is_authorized_for_service(temp_service, &current_authdata) == TRUE)
961 					printf("<option value='%s'>%s;%s\n", escape_string(temp_service->description), temp_service->host_name, temp_service->description);
962 				}
963 
964 			printf("</select>\n");
965 			printf("</td></tr>\n");
966 
967 			printf("<tr><td></td><td class='reportSelectItem'>\n");
968 			printf("<input type='submit' value='Continue to Step 3'>\n");
969 			printf("</td></tr>\n");
970 
971 			printf("</TABLE>\n");
972 			printf("</form>\n");
973 
974 			printf("</DIV></P>\n");
975 			}
976 
977 		/* ask the user for report range and options */
978 		else if(input_type == GET_INPUT_OPTIONS) {
979 
980 			time(&current_time);
981 			t = localtime(&current_time);
982 
983 			start_day = 1;
984 			start_year = t->tm_year + 1900;
985 			end_day = t->tm_mday;
986 			end_year = t->tm_year + 1900;
987 
988 			printf("<P><DIV ALIGN=CENTER>\n");
989 			printf("<DIV CLASS='reportSelectTitle'>Step 3: Select Report Options</DIV>\n");
990 			printf("</DIV></P>\n");
991 
992 			printf("<P><DIV ALIGN=CENTER>\n");
993 
994 #ifdef LEGACY_GRAPHICAL_CGIS
995 			printf("<form method=\"GET\" action=\"%s\">\n", TRENDS_CGI);
996 #else
997 			printf("<form method=\"GET\" action=\"%s\">\n", LEGACY_TRENDS_CGI);
998 #endif
999 			printf("<input type='hidden' name='host' value='%s'>\n", escape_string(host_name));
1000 			if(display_type == DISPLAY_SERVICE_TRENDS)
1001 				printf("<input type='hidden' name='service' value='%s'>\n", escape_string(svc_description));
1002 			printf("<TABLE BORDER=0 CELLPADDING=5>\n");
1003 
1004 			printf("<tr><td class='reportSelectSubTitle' align=right>Report period:</td>\n");
1005 			printf("<td class='reportSelectItem'>\n");
1006 			printf("<select name='timeperiod'>\n");
1007 			printf("<option value=today>Today\n");
1008 			printf("<option value=last24hours>Last 24 Hours\n");
1009 			printf("<option value=yesterday>Yesterday\n");
1010 			printf("<option value=thisweek>This Week\n");
1011 			printf("<option value=last7days SELECTED>Last 7 Days\n");
1012 			printf("<option value=lastweek>Last Week\n");
1013 			printf("<option value=thismonth>This Month\n");
1014 			printf("<option value=last31days>Last 31 Days\n");
1015 			printf("<option value=lastmonth>Last Month\n");
1016 			printf("<option value=thisyear>This Year\n");
1017 			printf("<option value=lastyear>Last Year\n");
1018 			printf("<option value=custom>* CUSTOM REPORT PERIOD *\n");
1019 			printf("</select>\n");
1020 			printf("</td></tr>\n");
1021 
1022 			printf("<tr><td valign=top class='reportSelectSubTitle'>If Custom Report Period...</td></tr>\n");
1023 
1024 			printf("<tr>");
1025 			printf("<td valign=top class='reportSelectSubTitle'>Start Date (Inclusive):</td>\n");
1026 			printf("<td align=left valign=top class='reportSelectItem'>");
1027 			printf("<select name='smon'>\n");
1028 			printf("<option value='1' %s>January\n", (t->tm_mon == 0) ? "SELECTED" : "");
1029 			printf("<option value='2' %s>February\n", (t->tm_mon == 1) ? "SELECTED" : "");
1030 			printf("<option value='3' %s>March\n", (t->tm_mon == 2) ? "SELECTED" : "");
1031 			printf("<option value='4' %s>April\n", (t->tm_mon == 3) ? "SELECTED" : "");
1032 			printf("<option value='5' %s>May\n", (t->tm_mon == 4) ? "SELECTED" : "");
1033 			printf("<option value='6' %s>June\n", (t->tm_mon == 5) ? "SELECTED" : "");
1034 			printf("<option value='7' %s>July\n", (t->tm_mon == 6) ? "SELECTED" : "");
1035 			printf("<option value='8' %s>August\n", (t->tm_mon == 7) ? "SELECTED" : "");
1036 			printf("<option value='9' %s>September\n", (t->tm_mon == 8) ? "SELECTED" : "");
1037 			printf("<option value='10' %s>October\n", (t->tm_mon == 9) ? "SELECTED" : "");
1038 			printf("<option value='11' %s>November\n", (t->tm_mon == 10) ? "SELECTED" : "");
1039 			printf("<option value='12' %s>December\n", (t->tm_mon == 11) ? "SELECTED" : "");
1040 			printf("</select>\n ");
1041 			printf("<input type='text' size='2' maxlength='2' name='sday' value='%d'> ", start_day);
1042 			printf("<input type='text' size='4' maxlength='4' name='syear' value='%d'>", start_year);
1043 			printf("<input type='hidden' name='shour' value='0'>\n");
1044 			printf("<input type='hidden' name='smin' value='0'>\n");
1045 			printf("<input type='hidden' name='ssec' value='0'>\n");
1046 			printf("</td>\n");
1047 			printf("</tr>\n");
1048 
1049 			printf("<tr>");
1050 			printf("<td valign=top class='reportSelectSubTitle'>End Date (Inclusive):</td>\n");
1051 			printf("<td align=left valign=top class='reportSelectItem'>");
1052 			printf("<select name='emon'>\n");
1053 			printf("<option value='1' %s>January\n", (t->tm_mon == 0) ? "SELECTED" : "");
1054 			printf("<option value='2' %s>February\n", (t->tm_mon == 1) ? "SELECTED" : "");
1055 			printf("<option value='3' %s>March\n", (t->tm_mon == 2) ? "SELECTED" : "");
1056 			printf("<option value='4' %s>April\n", (t->tm_mon == 3) ? "SELECTED" : "");
1057 			printf("<option value='5' %s>May\n", (t->tm_mon == 4) ? "SELECTED" : "");
1058 			printf("<option value='6' %s>June\n", (t->tm_mon == 5) ? "SELECTED" : "");
1059 			printf("<option value='7' %s>July\n", (t->tm_mon == 6) ? "SELECTED" : "");
1060 			printf("<option value='8' %s>August\n", (t->tm_mon == 7) ? "SELECTED" : "");
1061 			printf("<option value='9' %s>September\n", (t->tm_mon == 8) ? "SELECTED" : "");
1062 			printf("<option value='10' %s>October\n", (t->tm_mon == 9) ? "SELECTED" : "");
1063 			printf("<option value='11' %s>November\n", (t->tm_mon == 10) ? "SELECTED" : "");
1064 			printf("<option value='12' %s>December\n", (t->tm_mon == 11) ? "SELECTED" : "");
1065 			printf("</select>\n ");
1066 			printf("<input type='text' size='2' maxlength='2' name='eday' value='%d'> ", end_day);
1067 			printf("<input type='text' size='4' maxlength='4' name='eyear' value='%d'>", end_year);
1068 			printf("<input type='hidden' name='ehour' value='24'>\n");
1069 			printf("<input type='hidden' name='emin' value='0'>\n");
1070 			printf("<input type='hidden' name='esec' value='0'>\n");
1071 			printf("</td>\n");
1072 			printf("</tr>\n");
1073 
1074 			printf("<tr><td colspan=2><br></td></tr>\n");
1075 
1076 			printf("<tr><td class='reportSelectSubTitle' align=right>Assume Initial States:</td>\n");
1077 			printf("<td class='reportSelectItem'>\n");
1078 			printf("<select name='assumeinitialstates'>\n");
1079 			printf("<option value=yes>Yes\n");
1080 			printf("<option value=no>No\n");
1081 			printf("</select>\n");
1082 			printf("</td></tr>\n");
1083 
1084 			printf("<tr><td class='reportSelectSubTitle' align=right>Assume State Retention:</td>\n");
1085 			printf("<td class='reportSelectItem'>\n");
1086 			printf("<select name='assumestateretention'>\n");
1087 			printf("<option value=yes>Yes\n");
1088 			printf("<option value=no>No\n");
1089 			printf("</select>\n");
1090 			printf("</td></tr>\n");
1091 
1092 			printf("<tr><td class='reportSelectSubTitle' align=right>Assume States During Program Downtime:</td>\n");
1093 			printf("<td class='reportSelectItem'>\n");
1094 			printf("<select name='assumestatesduringnotrunning'>\n");
1095 			printf("<option value=yes>Yes\n");
1096 			printf("<option value=no>No\n");
1097 			printf("</select>\n");
1098 			printf("</td></tr>\n");
1099 
1100 			printf("<tr><td class='reportSelectSubTitle' align=right>Include Soft States:</td>\n");
1101 			printf("<td class='reportSelectItem'>\n");
1102 			printf("<select name='includesoftstates'>\n");
1103 			printf("<option value=yes>Yes\n");
1104 			printf("<option value=no SELECTED>No\n");
1105 			printf("</select>\n");
1106 			printf("</td></tr>\n");
1107 
1108 			printf("<tr><td class='reportSelectSubTitle' align=right>First Assumed %s State:</td>\n", (display_type == DISPLAY_HOST_TRENDS) ? "Host" : "Service");
1109 			printf("<td class='reportSelectItem'>\n");
1110 			if(display_type == DISPLAY_HOST_TRENDS) {
1111 				printf("<select name='initialassumedhoststate'>\n");
1112 				printf("<option value=%d>Unspecified\n", AS_NO_DATA);
1113 				printf("<option value=%d>Current State\n", AS_CURRENT_STATE);
1114 				printf("<option value=%d>Host Up\n", AS_HOST_UP);
1115 				printf("<option value=%d>Host Down\n", AS_HOST_DOWN);
1116 				printf("<option value=%d>Host Unreachable\n", AS_HOST_UNREACHABLE);
1117 				}
1118 			else {
1119 				printf("<select name='initialassumedservicestate'>\n");
1120 				printf("<option value=%d>Unspecified\n", AS_NO_DATA);
1121 				printf("<option value=%d>Current State\n", AS_CURRENT_STATE);
1122 				printf("<option value=%d>Service Ok\n", AS_SVC_OK);
1123 				printf("<option value=%d>Service Warning\n", AS_SVC_WARNING);
1124 				printf("<option value=%d>Service Unknown\n", AS_SVC_UNKNOWN);
1125 				printf("<option value=%d>Service Critical\n", AS_SVC_CRITICAL);
1126 				}
1127 			printf("</select>\n");
1128 			printf("</td></tr>\n");
1129 
1130 			printf("<tr><td class='reportSelectSubTitle' align=right>Backtracked Archives (To Scan For Initial States):</td>\n");
1131 			printf("<td class='reportSelectItem'>\n");
1132 			printf("<input type='text' name='backtrack' size='2' maxlength='2' value='%d'>\n", backtrack_archives);
1133 			printf("</td></tr>\n");
1134 
1135 			printf("<tr><td class='reportSelectSubTitle' align=right>Suppress image map:</td><td class='reportSelectItem'><input type='checkbox' name='nomap'></td></tr>");
1136 			printf("<tr><td class='reportSelectSubTitle' align=right>Suppress popups:</td><td class='reportSelectItem'><input type='checkbox' name='nopopups'></td></tr>\n");
1137 
1138 			printf("<tr><td></td><td class='reportSelectItem'><input type='submit' value='Create Report'></td></tr>\n");
1139 
1140 			printf("</TABLE>\n");
1141 			printf("</form>\n");
1142 
1143 			printf("</DIV></P>\n");
1144 
1145 			/*
1146 			printf("<P><DIV ALIGN=CENTER CLASS='helpfulHint'>\n");
1147 			printf("Note: Choosing the 'suppress image map' option will make the report run approximately twice as fast as it would otherwise, but it will prevent you from being able to zoom in on specific time periods.\n");
1148 			printf("</DIV></P>\n");
1149 			*/
1150 			}
1151 
1152 		/* as the user whether they want a graph for a host or service */
1153 		else {
1154 			printf("<P><DIV ALIGN=CENTER>\n");
1155 			printf("<DIV CLASS='reportSelectTitle'>Step 1: Select Report Type</DIV>\n");
1156 			printf("</DIV></P>\n");
1157 
1158 			printf("<P><DIV ALIGN=CENTER>\n");
1159 
1160 #ifdef LEGACY_GRAPHICAL_CGIS
1161 			printf("<form method=\"GET\" action=\"%s\">\n", TRENDS_CGI);
1162 #else
1163 			printf("<form method=\"GET\" action=\"%s\">\n", LEGACY_TRENDS_CGI);
1164 #endif
1165 			printf("<TABLE BORDER=0 cellpadding=5>\n");
1166 
1167 			printf("<tr><td class='reportSelectSubTitle' align=right>Type:</td>\n");
1168 			printf("<td class='reportSelectItem'>\n");
1169 			printf("<select name='input'>\n");
1170 			printf("<option value=gethost>Host\n");
1171 			printf("<option value=getservice>Service\n");
1172 			printf("</select>\n");
1173 			printf("</td></tr>\n");
1174 
1175 			printf("<tr><td></td><td class='reportSelectItem'>\n");
1176 			printf("<input type='submit' value='Continue to Step 2'>\n");
1177 			printf("</td></tr>\n");
1178 
1179 			printf("</TABLE>\n");
1180 			printf("</form>\n");
1181 
1182 			printf("</DIV></P>\n");
1183 			}
1184 
1185 		}
1186 
1187 	document_footer();
1188 
1189 	/* free memory allocated to the archived state data list */
1190 	free_archived_state_list();
1191 
1192 	/* free all other allocated memory */
1193 	free_memory();
1194 
1195 	return OK;
1196 	}
1197 
1198 
1199 
document_header(int use_stylesheet)1200 void document_header(int use_stylesheet) {
1201 	char date_time[MAX_DATETIME_LENGTH];
1202 	time_t current_time;
1203 	time_t expire_time;
1204 
1205 	if(mode == CREATE_HTML) {
1206 		printf("Cache-Control: no-store\r\n");
1207 		printf("Pragma: no-cache\r\n");
1208 
1209 		time(&current_time);
1210 		get_time_string(&current_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
1211 		printf("Last-Modified: %s\r\n", date_time);
1212 
1213 		expire_time = (time_t)0;
1214 		get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
1215 		printf("Expires: %s\r\n", date_time);
1216 
1217 		printf("Content-type: text/html; charset=utf-8\r\n\r\n");
1218 
1219 		if(embedded == TRUE)
1220 			return;
1221 
1222 		printf("<html>\n");
1223 		printf("<head>\n");
1224 		printf("<link rel=\"shortcut icon\" href=\"%sfavicon.ico\" type=\"image/ico\">\n", url_images_path);
1225 		printf("<title>\n");
1226 		printf("Nagios Trends\n");
1227 		printf("</title>\n");
1228 
1229 		if(use_stylesheet == TRUE) {
1230 			printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, COMMON_CSS);
1231 			printf("<LINK REL='stylesheet' TYPE='text/css' HREF='%s%s'>\n", url_stylesheets_path, TRENDS_CSS);
1232 			}
1233 
1234 		/* write JavaScript code for popup window */
1235 		if(display_type != DISPLAY_NO_TRENDS)
1236 			write_popup_code();
1237 
1238 		printf("</head>\n");
1239 
1240 		printf("<BODY CLASS='trends'>\n");
1241 
1242 		/* include user SSI header */
1243 #ifdef LEGACY_GRAPHICAL_CGIS
1244 		include_ssi_files(TRENDS_CGI, SSI_HEADER);
1245 #else
1246 		include_ssi_files(LEGACY_TRENDS_CGI, SSI_HEADER);
1247 #endif
1248 
1249 		printf("<div id=\"popup\" style=\"position:absolute; z-index:1; visibility: hidden\"></div>\n");
1250 		}
1251 
1252 	else {
1253 		printf("Cache-Control: no-store\r\n");
1254 		printf("Pragma: no-cache\r\n");
1255 
1256 		time(&current_time);
1257 		get_time_string(&current_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
1258 		printf("Last-Modified: %s\r\n", date_time);
1259 
1260 		expire_time = (time_t)0L;
1261 		get_time_string(&expire_time, date_time, sizeof(date_time), HTTP_DATE_TIME);
1262 		printf("Expires: %s\r\n", date_time);
1263 
1264 		printf("Content-Type: image/png\r\n\r\n");
1265 		}
1266 
1267 	return;
1268 	}
1269 
1270 
1271 
document_footer(void)1272 void document_footer(void) {
1273 
1274 	if(embedded == TRUE)
1275 		return;
1276 
1277 	if(mode == CREATE_HTML) {
1278 
1279 		/* include user SSI footer */
1280 #ifdef LEGACY_GRAPHICAL_CGIS
1281 		include_ssi_files(TRENDS_CGI, SSI_FOOTER);
1282 #else
1283 		include_ssi_files(LEGACY_TRENDS_CGI, SSI_FOOTER);
1284 #endif
1285 
1286 		printf("</body>\n");
1287 		printf("</html>\n");
1288 		}
1289 
1290 	return;
1291 	}
1292 
1293 
1294 
process_cgivars(void)1295 int process_cgivars(void) {
1296 	char **variables;
1297 	int error = FALSE;
1298 	int x;
1299 
1300 	variables = getcgivars();
1301 
1302 	for(x = 0; variables[x]; x++) {
1303 
1304 		/* do some basic length checking on the variable identifier to prevent buffer overflows */
1305 		if(strlen(variables[x]) >= MAX_INPUT_BUFFER - 1) {
1306 			continue;
1307 			}
1308 
1309 		/* we found the host argument */
1310 		else if(!strcmp(variables[x], "host")) {
1311 			x++;
1312 			if(variables[x] == NULL) {
1313 				error = TRUE;
1314 				break;
1315 				}
1316 
1317 			if((host_name = (char *)strdup(variables[x])) == NULL)
1318 				host_name = "";
1319 			strip_html_brackets(host_name);
1320 
1321 			display_type = DISPLAY_HOST_TRENDS;
1322 			}
1323 
1324 		/* we found the node width argument */
1325 		else if(!strcmp(variables[x], "service")) {
1326 			x++;
1327 			if(variables[x] == NULL) {
1328 				error = TRUE;
1329 				break;
1330 				}
1331 
1332 			if((svc_description = (char *)strdup(variables[x])) == NULL)
1333 				svc_description = "";
1334 			strip_html_brackets(svc_description);
1335 
1336 			display_type = DISPLAY_SERVICE_TRENDS;
1337 			}
1338 
1339 		/* we found first time argument */
1340 		else if(!strcmp(variables[x], "t1")) {
1341 			x++;
1342 			if(variables[x] == NULL) {
1343 				error = TRUE;
1344 				break;
1345 				}
1346 
1347 			t1 = (time_t)strtoul(variables[x], NULL, 10);
1348 			timeperiod_type = TIMEPERIOD_CUSTOM;
1349 			}
1350 
1351 		/* we found first time argument */
1352 		else if(!strcmp(variables[x], "t2")) {
1353 			x++;
1354 			if(variables[x] == NULL) {
1355 				error = TRUE;
1356 				break;
1357 				}
1358 
1359 			t2 = (time_t)strtoul(variables[x], NULL, 10);
1360 			timeperiod_type = TIMEPERIOD_CUSTOM;
1361 			}
1362 
1363 		/* we found the image creation option */
1364 		else if(!strcmp(variables[x], "createimage")) {
1365 			mode = CREATE_IMAGE;
1366 			}
1367 
1368 		/* we found the assume initial states option */
1369 		else if(!strcmp(variables[x], "assumeinitialstates")) {
1370 			x++;
1371 			if(variables[x] == NULL) {
1372 				error = TRUE;
1373 				break;
1374 				}
1375 
1376 			if(!strcmp(variables[x], "yes"))
1377 				assume_initial_states = TRUE;
1378 			else
1379 				assume_initial_states = FALSE;
1380 			}
1381 
1382 		/* we found the initial assumed host state option */
1383 		else if(!strcmp(variables[x], "initialassumedhoststate")) {
1384 			x++;
1385 			if(variables[x] == NULL) {
1386 				error = TRUE;
1387 				break;
1388 				}
1389 
1390 			initial_assumed_host_state = atoi(variables[x]);
1391 			}
1392 
1393 		/* we found the initial assumed service state option */
1394 		else if(!strcmp(variables[x], "initialassumedservicestate")) {
1395 			x++;
1396 			if(variables[x] == NULL) {
1397 				error = TRUE;
1398 				break;
1399 				}
1400 
1401 			initial_assumed_service_state = atoi(variables[x]);
1402 			}
1403 
1404 		/* we found the assume state during program not running option */
1405 		else if(!strcmp(variables[x], "assumestatesduringnotrunning")) {
1406 			x++;
1407 			if(variables[x] == NULL) {
1408 				error = TRUE;
1409 				break;
1410 				}
1411 
1412 			if(!strcmp(variables[x], "yes"))
1413 				assume_states_during_notrunning = TRUE;
1414 			else
1415 				assume_states_during_notrunning = FALSE;
1416 			}
1417 
1418 		/* we found the assume state retention option */
1419 		else if(!strcmp(variables[x], "assumestateretention")) {
1420 			x++;
1421 			if(variables[x] == NULL) {
1422 				error = TRUE;
1423 				break;
1424 				}
1425 
1426 			if(!strcmp(variables[x], "yes"))
1427 				assume_state_retention = TRUE;
1428 			else
1429 				assume_state_retention = FALSE;
1430 			}
1431 
1432 		/* we found the include soft states option */
1433 		else if(!strcmp(variables[x], "includesoftstates")) {
1434 			x++;
1435 			if(variables[x] == NULL) {
1436 				error = TRUE;
1437 				break;
1438 				}
1439 
1440 			if(!strcmp(variables[x], "yes"))
1441 				include_soft_states = TRUE;
1442 			else
1443 				include_soft_states = FALSE;
1444 			}
1445 
1446 		/* we found the zoom factor argument */
1447 		else if(!strcmp(variables[x], "zoom")) {
1448 			x++;
1449 			if(variables[x] == NULL) {
1450 				error = TRUE;
1451 				break;
1452 				}
1453 
1454 			zoom_factor = atoi(variables[x]);
1455 			if(zoom_factor == 0)
1456 				zoom_factor = 1;
1457 			}
1458 
1459 		/* we found the backtrack archives argument */
1460 		else if(!strcmp(variables[x], "backtrack")) {
1461 			x++;
1462 			if(variables[x] == NULL) {
1463 				error = TRUE;
1464 				break;
1465 				}
1466 
1467 			backtrack_archives = atoi(variables[x]);
1468 			if(backtrack_archives < 0)
1469 				backtrack_archives = 0;
1470 			if(backtrack_archives > MAX_ARCHIVE_BACKTRACKS)
1471 				backtrack_archives = MAX_ARCHIVE_BACKTRACKS;
1472 			}
1473 
1474 		/* we found the standard timeperiod argument */
1475 		else if(!strcmp(variables[x], "timeperiod")) {
1476 			x++;
1477 			if(variables[x] == NULL) {
1478 				error = TRUE;
1479 				break;
1480 				}
1481 
1482 			if(!strcmp(variables[x], "today"))
1483 				timeperiod_type = TIMEPERIOD_TODAY;
1484 			else if(!strcmp(variables[x], "yesterday"))
1485 				timeperiod_type = TIMEPERIOD_YESTERDAY;
1486 			else if(!strcmp(variables[x], "thisweek"))
1487 				timeperiod_type = TIMEPERIOD_THISWEEK;
1488 			else if(!strcmp(variables[x], "lastweek"))
1489 				timeperiod_type = TIMEPERIOD_LASTWEEK;
1490 			else if(!strcmp(variables[x], "thismonth"))
1491 				timeperiod_type = TIMEPERIOD_THISMONTH;
1492 			else if(!strcmp(variables[x], "lastmonth"))
1493 				timeperiod_type = TIMEPERIOD_LASTMONTH;
1494 			else if(!strcmp(variables[x], "thisquarter"))
1495 				timeperiod_type = TIMEPERIOD_THISQUARTER;
1496 			else if(!strcmp(variables[x], "lastquarter"))
1497 				timeperiod_type = TIMEPERIOD_LASTQUARTER;
1498 			else if(!strcmp(variables[x], "thisyear"))
1499 				timeperiod_type = TIMEPERIOD_THISYEAR;
1500 			else if(!strcmp(variables[x], "lastyear"))
1501 				timeperiod_type = TIMEPERIOD_LASTYEAR;
1502 			else if(!strcmp(variables[x], "nextproblem"))
1503 				timeperiod_type = TIMEPERIOD_NEXTPROBLEM;
1504 			else if(!strcmp(variables[x], "last24hours"))
1505 				timeperiod_type = TIMEPERIOD_LAST24HOURS;
1506 			else if(!strcmp(variables[x], "last7days"))
1507 				timeperiod_type = TIMEPERIOD_LAST7DAYS;
1508 			else if(!strcmp(variables[x], "last31days"))
1509 				timeperiod_type = TIMEPERIOD_LAST31DAYS;
1510 			else if(!strcmp(variables[x], "custom"))
1511 				timeperiod_type = TIMEPERIOD_CUSTOM;
1512 			else
1513 				continue;
1514 
1515 			convert_timeperiod_to_times(timeperiod_type);
1516 			}
1517 
1518 		/* we found time argument */
1519 		else if(!strcmp(variables[x], "smon")) {
1520 			x++;
1521 			if(variables[x] == NULL) {
1522 				error = TRUE;
1523 				break;
1524 				}
1525 
1526 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1527 				continue;
1528 
1529 			start_month = atoi(variables[x]);
1530 			timeperiod_type = TIMEPERIOD_CUSTOM;
1531 			compute_time_from_parts = TRUE;
1532 			}
1533 
1534 		/* we found time argument */
1535 		else if(!strcmp(variables[x], "sday")) {
1536 			x++;
1537 			if(variables[x] == NULL) {
1538 				error = TRUE;
1539 				break;
1540 				}
1541 
1542 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1543 				continue;
1544 
1545 			start_day = atoi(variables[x]);
1546 			timeperiod_type = TIMEPERIOD_CUSTOM;
1547 			compute_time_from_parts = TRUE;
1548 			}
1549 
1550 		/* we found time argument */
1551 		else if(!strcmp(variables[x], "syear")) {
1552 			x++;
1553 			if(variables[x] == NULL) {
1554 				error = TRUE;
1555 				break;
1556 				}
1557 
1558 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1559 				continue;
1560 
1561 			start_year = atoi(variables[x]);
1562 			timeperiod_type = TIMEPERIOD_CUSTOM;
1563 			compute_time_from_parts = TRUE;
1564 			}
1565 
1566 		/* we found time argument */
1567 		else if(!strcmp(variables[x], "smin")) {
1568 			x++;
1569 			if(variables[x] == NULL) {
1570 				error = TRUE;
1571 				break;
1572 				}
1573 
1574 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1575 				continue;
1576 
1577 			start_minute = atoi(variables[x]);
1578 			timeperiod_type = TIMEPERIOD_CUSTOM;
1579 			compute_time_from_parts = TRUE;
1580 			}
1581 
1582 		/* we found time argument */
1583 		else if(!strcmp(variables[x], "ssec")) {
1584 			x++;
1585 			if(variables[x] == NULL) {
1586 				error = TRUE;
1587 				break;
1588 				}
1589 
1590 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1591 				continue;
1592 
1593 			start_second = atoi(variables[x]);
1594 			timeperiod_type = TIMEPERIOD_CUSTOM;
1595 			compute_time_from_parts = TRUE;
1596 			}
1597 
1598 		/* we found time argument */
1599 		else if(!strcmp(variables[x], "shour")) {
1600 			x++;
1601 			if(variables[x] == NULL) {
1602 				error = TRUE;
1603 				break;
1604 				}
1605 
1606 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1607 				continue;
1608 
1609 			start_hour = atoi(variables[x]);
1610 			timeperiod_type = TIMEPERIOD_CUSTOM;
1611 			compute_time_from_parts = TRUE;
1612 			}
1613 
1614 
1615 		/* we found time argument */
1616 		else if(!strcmp(variables[x], "emon")) {
1617 			x++;
1618 			if(variables[x] == NULL) {
1619 				error = TRUE;
1620 				break;
1621 				}
1622 
1623 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1624 				continue;
1625 
1626 			end_month = atoi(variables[x]);
1627 			timeperiod_type = TIMEPERIOD_CUSTOM;
1628 			compute_time_from_parts = TRUE;
1629 			}
1630 
1631 		/* we found time argument */
1632 		else if(!strcmp(variables[x], "eday")) {
1633 			x++;
1634 			if(variables[x] == NULL) {
1635 				error = TRUE;
1636 				break;
1637 				}
1638 
1639 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1640 				continue;
1641 
1642 			end_day = atoi(variables[x]);
1643 			timeperiod_type = TIMEPERIOD_CUSTOM;
1644 			compute_time_from_parts = TRUE;
1645 			}
1646 
1647 		/* we found time argument */
1648 		else if(!strcmp(variables[x], "eyear")) {
1649 			x++;
1650 			if(variables[x] == NULL) {
1651 				error = TRUE;
1652 				break;
1653 				}
1654 
1655 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1656 				continue;
1657 
1658 			end_year = atoi(variables[x]);
1659 			timeperiod_type = TIMEPERIOD_CUSTOM;
1660 			compute_time_from_parts = TRUE;
1661 			}
1662 
1663 		/* we found time argument */
1664 		else if(!strcmp(variables[x], "emin")) {
1665 			x++;
1666 			if(variables[x] == NULL) {
1667 				error = TRUE;
1668 				break;
1669 				}
1670 
1671 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1672 				continue;
1673 
1674 			end_minute = atoi(variables[x]);
1675 			timeperiod_type = TIMEPERIOD_CUSTOM;
1676 			compute_time_from_parts = TRUE;
1677 			}
1678 
1679 		/* we found time argument */
1680 		else if(!strcmp(variables[x], "esec")) {
1681 			x++;
1682 			if(variables[x] == NULL) {
1683 				error = TRUE;
1684 				break;
1685 				}
1686 
1687 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1688 				continue;
1689 
1690 			end_second = atoi(variables[x]);
1691 			timeperiod_type = TIMEPERIOD_CUSTOM;
1692 			compute_time_from_parts = TRUE;
1693 			}
1694 
1695 		/* we found time argument */
1696 		else if(!strcmp(variables[x], "ehour")) {
1697 			x++;
1698 			if(variables[x] == NULL) {
1699 				error = TRUE;
1700 				break;
1701 				}
1702 
1703 			if(timeperiod_type != TIMEPERIOD_CUSTOM)
1704 				continue;
1705 
1706 			end_hour = atoi(variables[x]);
1707 			timeperiod_type = TIMEPERIOD_CUSTOM;
1708 			compute_time_from_parts = TRUE;
1709 			}
1710 
1711 		/* we found the embed option */
1712 		else if(!strcmp(variables[x], "embedded"))
1713 			embedded = TRUE;
1714 
1715 		/* we found the noheader option */
1716 		else if(!strcmp(variables[x], "noheader"))
1717 			display_header = FALSE;
1718 
1719 		/* we found the nopopups option */
1720 		else if(!strcmp(variables[x], "nopopups"))
1721 			display_popups = FALSE;
1722 
1723 		/* we found the nomap option */
1724 		else if(!strcmp(variables[x], "nomap")) {
1725 			display_popups = FALSE;
1726 			use_map = FALSE;
1727 			}
1728 
1729 		/* we found the input option */
1730 		else if(!strcmp(variables[x], "input")) {
1731 			x++;
1732 			if(variables[x] == NULL) {
1733 				error = TRUE;
1734 				break;
1735 				}
1736 
1737 			if(!strcmp(variables[x], "gethost"))
1738 				input_type = GET_INPUT_HOST_TARGET;
1739 			else if(!strcmp(variables[x], "getservice"))
1740 				input_type = GET_INPUT_SERVICE_TARGET;
1741 			else if(!strcmp(variables[x], "getoptions"))
1742 				input_type = GET_INPUT_OPTIONS;
1743 			else
1744 				input_type = GET_INPUT_TARGET_TYPE;
1745 			}
1746 
1747 		/* we found the small image option */
1748 		else if(!strcmp(variables[x], "smallimage"))
1749 			small_image = TRUE;
1750 
1751 		}
1752 
1753 	/* free memory allocated to the CGI variables */
1754 	free_cgivars(variables);
1755 
1756 	return error;
1757 	}
1758 
1759 
1760 
1761 /* top level routine for graphic all trend data */
graph_all_trend_data(void)1762 void graph_all_trend_data(void) {
1763 	archived_state *temp_as;
1764 	archived_state *last_as;
1765 	time_t a;
1766 	time_t b;
1767 	time_t current_time;
1768 	int current_state = AS_NO_DATA;
1769 	int have_some_real_data = FALSE;
1770 	hoststatus *hststatus = NULL;
1771 	servicestatus *svcstatus = NULL;
1772 	unsigned long wobble = 300;
1773 	time_t initial_assumed_time;
1774 	int initial_assumed_state = AS_SVC_OK;
1775 	int error = FALSE;
1776 
1777 
1778 	time(&current_time);
1779 
1780 	/* if left hand of graph is after current time, we can't do anything at all.... */
1781 	if(t1 > current_time)
1782 		return;
1783 
1784 	/* find current state for host or service */
1785 	if(display_type == DISPLAY_HOST_TRENDS)
1786 		hststatus = find_hoststatus(host_name);
1787 	else
1788 		svcstatus = find_servicestatus(host_name, svc_description);
1789 
1790 
1791 	/************************************/
1792 	/* INSERT CURRENT STATE (IF WE CAN) */
1793 	/************************************/
1794 
1795 	/* if current time DOES NOT fall within graph bounds, so we can't do anything as far as assuming current state */
1796 	/* the "wobble" value is necessary because when the CGI is called to do the PNG generation, t2 will actually be less that current_time by a bit */
1797 
1798 	/* if we don't have any data, assume current state (if possible) */
1799 	if(as_list == NULL && current_time > t1 && current_time < (time_t)(t2 + wobble)) {
1800 
1801 		/* we don't have any historical information, but the current time falls within the reporting period, so use */
1802 		/* the current status of the host/service as the starting data */
1803 		if(display_type == DISPLAY_HOST_TRENDS) {
1804 			if(hststatus != NULL) {
1805 
1806 				if(hststatus->status == SD_HOST_DOWN)
1807 					last_known_state = AS_HOST_DOWN;
1808 				else if(hststatus->status == SD_HOST_UNREACHABLE)
1809 					last_known_state = AS_HOST_UNREACHABLE;
1810 				else
1811 					last_known_state = AS_HOST_UP;
1812 
1813 				/* add a dummy archived state item, so something can get graphed */
1814 				add_archived_state(last_known_state, AS_HARD_STATE, t1, "Current Host State Assumed (Faked Log Entry)");
1815 				}
1816 			}
1817 		else {
1818 			if(svcstatus != NULL) {
1819 
1820 				if(svcstatus->status == SERVICE_OK)
1821 					last_known_state = AS_SVC_OK;
1822 				else if(svcstatus->status == SERVICE_WARNING)
1823 					last_known_state = AS_SVC_WARNING;
1824 				else if(svcstatus->status == SERVICE_CRITICAL)
1825 					last_known_state = AS_SVC_CRITICAL;
1826 				else if(svcstatus->status == SERVICE_UNKNOWN)
1827 					last_known_state = AS_SVC_UNKNOWN;
1828 
1829 				/* add a dummy archived state item, so something can get graphed */
1830 				add_archived_state(last_known_state, AS_HARD_STATE, t1, "Current Service State Assumed (Faked Log Entry)");
1831 				}
1832 			}
1833 		}
1834 
1835 
1836 	/******************************************/
1837 	/* INSERT FIRST ASSUMED STATE (IF WE CAN) */
1838 	/******************************************/
1839 
1840 	if((display_type == DISPLAY_HOST_TRENDS && initial_assumed_host_state != AS_NO_DATA) || (display_type == DISPLAY_SERVICE_TRENDS && initial_assumed_service_state != AS_NO_DATA)) {
1841 
1842 		/* see if its okay to assume initial state for this subject */
1843 		error = FALSE;
1844 		if(display_type == DISPLAY_SERVICE_TRENDS) {
1845 			if(initial_assumed_service_state != AS_SVC_OK && initial_assumed_service_state != AS_SVC_WARNING && initial_assumed_service_state != AS_SVC_UNKNOWN && initial_assumed_service_state != AS_SVC_CRITICAL && initial_assumed_service_state != AS_CURRENT_STATE)
1846 				error = TRUE;
1847 			else
1848 				initial_assumed_state = initial_assumed_service_state;
1849 			if(initial_assumed_service_state == AS_CURRENT_STATE && svcstatus == NULL)
1850 				error = TRUE;
1851 			}
1852 		else {
1853 			if(initial_assumed_host_state != AS_HOST_UP && initial_assumed_host_state != AS_HOST_DOWN && initial_assumed_host_state != AS_HOST_UNREACHABLE && initial_assumed_host_state != AS_CURRENT_STATE)
1854 				error = TRUE;
1855 			else
1856 				initial_assumed_state = initial_assumed_host_state;
1857 			if(initial_assumed_host_state == AS_CURRENT_STATE && hststatus == NULL)
1858 				error = TRUE;
1859 			}
1860 
1861 		/* get the current state if applicable */
1862 		if(((display_type == DISPLAY_HOST_TRENDS && initial_assumed_host_state == AS_CURRENT_STATE) || (display_type == DISPLAY_SERVICE_TRENDS && initial_assumed_service_state == AS_CURRENT_STATE)) && error == FALSE) {
1863 			if(display_type == DISPLAY_HOST_TRENDS) {
1864 				switch(hststatus->status) {
1865 					case SD_HOST_DOWN:
1866 						initial_assumed_state = AS_HOST_DOWN;
1867 						break;
1868 					case SD_HOST_UNREACHABLE:
1869 						initial_assumed_state = AS_HOST_UNREACHABLE;
1870 						break;
1871 					case SD_HOST_UP:
1872 						initial_assumed_state = AS_HOST_UP;
1873 						break;
1874 					default:
1875 						error = TRUE;
1876 						break;
1877 					}
1878 				}
1879 			else {
1880 				switch(svcstatus->status) {
1881 					case SERVICE_OK:
1882 						initial_assumed_state = AS_SVC_OK;
1883 						break;
1884 					case SERVICE_WARNING:
1885 						initial_assumed_state = AS_SVC_WARNING;
1886 						break;
1887 					case SERVICE_UNKNOWN:
1888 						initial_assumed_state = AS_SVC_UNKNOWN;
1889 						break;
1890 					case SERVICE_CRITICAL:
1891 						initial_assumed_state = AS_SVC_CRITICAL;
1892 						break;
1893 					default:
1894 						error = TRUE;
1895 						break;
1896 					}
1897 				}
1898 			}
1899 
1900 		if(error == FALSE) {
1901 
1902 			/* add this assumed state entry before any entries in the list and <= t1 */
1903 			if(as_list == NULL)
1904 				initial_assumed_time = t1;
1905 			else if(as_list->time_stamp > t1)
1906 				initial_assumed_time = t1;
1907 			else
1908 				initial_assumed_time = as_list->time_stamp - 1;
1909 
1910 			if(display_type == DISPLAY_HOST_TRENDS)
1911 				add_archived_state(initial_assumed_state, AS_HARD_STATE, initial_assumed_time, "First Host State Assumed (Faked Log Entry)");
1912 			else
1913 				add_archived_state(initial_assumed_state, AS_HARD_STATE, initial_assumed_time, "First Service State Assumed (Faked Log Entry)");
1914 			}
1915 		}
1916 
1917 
1918 
1919 
1920 	/**************************************/
1921 	/* BAIL OUT IF WE DON'T HAVE ANYTHING */
1922 	/**************************************/
1923 
1924 	have_some_real_data = FALSE;
1925 	for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
1926 		if(temp_as->entry_type != AS_NO_DATA && temp_as->entry_type != AS_PROGRAM_START && temp_as->entry_type != AS_PROGRAM_END) {
1927 			have_some_real_data = TRUE;
1928 			break;
1929 			}
1930 		}
1931 	if(have_some_real_data == FALSE)
1932 		return;
1933 
1934 
1935 
1936 
1937 	/* if we're creating the HTML, start map code... */
1938 	if(mode == CREATE_HTML)
1939 		printf("<MAP name='trendsmap'>\n");
1940 
1941 	last_as = NULL;
1942 	earliest_time = t2;
1943 	latest_time = t1;
1944 
1945 
1946 
1947 #ifdef DEBUG
1948 	printf("--- BEGINNING/MIDDLE SECTION ---<BR>\n");
1949 #endif
1950 
1951 	/**********************************/
1952 	/*    BEGINNING/MIDDLE SECTION    */
1953 	/**********************************/
1954 
1955 	for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
1956 
1957 		/* keep this as last known state if this is the first entry or if it occurs before the starting point of the graph */
1958 		if((temp_as->time_stamp <= t1 || temp_as == as_list) && (temp_as->entry_type != AS_NO_DATA && temp_as->entry_type != AS_PROGRAM_END && temp_as->entry_type != AS_PROGRAM_START)) {
1959 			last_known_state = temp_as->entry_type;
1960 #ifdef DEBUG
1961 			printf("SETTING LAST KNOWN STATE=%d<br>\n", last_known_state);
1962 #endif
1963 			}
1964 
1965 		/* skip this entry if it occurs before the starting point of the graph */
1966 		if(temp_as->time_stamp <= t1) {
1967 #ifdef DEBUG
1968 			printf("SKIPPING PRE-EVENT: %d @ %lu<br>\n", temp_as->entry_type, temp_as->time_stamp);
1969 #endif
1970 			last_as = temp_as;
1971 			continue;
1972 			}
1973 
1974 		/* graph this span if we're not on the first item */
1975 		if(last_as != NULL) {
1976 
1977 			a = last_as->time_stamp;
1978 			b = temp_as->time_stamp;
1979 
1980 			/* we've already passed the last time displayed in the graph */
1981 			if(a > t2)
1982 				break;
1983 
1984 			/* only graph this data if its on the graph */
1985 			else if(b > t1) {
1986 
1987 				/* clip last time if it exceeds graph limits */
1988 				if(b > t2)
1989 					b = t2;
1990 
1991 				/* clip first time if it precedes graph limits */
1992 				if(a < t1)
1993 					a = t1;
1994 
1995 				/* save this time if its the earliest we've graphed */
1996 				if(a < earliest_time) {
1997 					earliest_time = a;
1998 					earliest_state = last_as->entry_type;
1999 					}
2000 
2001 				/* save this time if its the latest we've graphed */
2002 				if(b > latest_time) {
2003 					latest_time = b;
2004 					latest_state = last_as->entry_type;
2005 					}
2006 
2007 				/* compute availability times for this chunk */
2008 				graph_trend_data(last_as->entry_type, temp_as->entry_type, last_as->time_stamp, a, b, last_as->state_info);
2009 
2010 				/* return if we've reached the end of the graph limits */
2011 				if(b >= t2) {
2012 					last_as = temp_as;
2013 					break;
2014 					}
2015 				}
2016 			}
2017 
2018 
2019 		/* keep track of the last item */
2020 		last_as = temp_as;
2021 		}
2022 
2023 
2024 #ifdef DEBUG
2025 	printf("--- END SECTION ---<BR>\n");
2026 #endif
2027 
2028 	/**********************************/
2029 	/*           END SECTION          */
2030 	/**********************************/
2031 
2032 	if(last_as != NULL) {
2033 
2034 		/* don't process an entry that is beyond the limits of the graph */
2035 		if(last_as->time_stamp < t2) {
2036 
2037 			time(&current_time);
2038 			b = current_time;
2039 			if(b > t2)
2040 				b = t2;
2041 
2042 			a = last_as->time_stamp;
2043 			if(a < t1)
2044 				a = t1;
2045 
2046 			/* fake the current state (it doesn't really matter for graphing) */
2047 			if(display_type == DISPLAY_HOST_TRENDS)
2048 				current_state = AS_HOST_UP;
2049 			else
2050 				current_state = AS_SVC_OK;
2051 
2052 			/* compute availability times for last state */
2053 			graph_trend_data(last_as->entry_type, current_state, a, a, b, last_as->state_info);
2054 			}
2055 		}
2056 
2057 
2058 
2059 	/* if we're creating the HTML, close the map code */
2060 	if(mode == CREATE_HTML)
2061 		printf("</MAP>\n");
2062 
2063 	return;
2064 	}
2065 
2066 
2067 
2068 /* graphs trend data */
graph_trend_data(int first_state,int last_state,time_t real_start_time,time_t start_time,time_t end_time,char * state_info)2069 void graph_trend_data(int first_state, int last_state, time_t real_start_time, time_t start_time, time_t end_time, char *state_info) {
2070 	int start_state;
2071 	int start_pixel = 0;
2072 	int end_pixel = 0;
2073 	int color_to_use = 0;
2074 	int height = 0;
2075 	double start_pixel_ratio;
2076 	double end_pixel_ratio;
2077 	char temp_buffer[MAX_INPUT_BUFFER];
2078 	char state_string[MAX_INPUT_BUFFER];
2079 	char end_timestring[MAX_INPUT_BUFFER];
2080 	char start_timestring[MAX_INPUT_BUFFER];
2081 	time_t center_time;
2082 	time_t next_start_time;
2083 	time_t next_end_time;
2084 	int days = 0;
2085 	int hours = 0;
2086 	int minutes = 0;
2087 	int seconds = 0;
2088 
2089 	/* can't graph if we don't have data... */
2090 	if(first_state == AS_NO_DATA || last_state == AS_NO_DATA)
2091 		return;
2092 	if(first_state == AS_PROGRAM_START && (last_state == AS_PROGRAM_END || last_state == AS_PROGRAM_START)) {
2093 		if(assume_initial_states == FALSE)
2094 			return;
2095 		}
2096 	if(first_state == AS_PROGRAM_END) {
2097 		if(assume_states_during_notrunning == TRUE)
2098 			first_state = last_known_state;
2099 		else
2100 			return;
2101 		}
2102 
2103 	/* special case if first entry was program start */
2104 	if(first_state == AS_PROGRAM_START) {
2105 #ifdef DEBUG
2106 		printf("First state=program start!\n");
2107 #endif
2108 		if(assume_initial_states == TRUE) {
2109 #ifdef DEBUG
2110 			printf("\tWe are assuming initial states...\n");
2111 #endif
2112 			if(assume_state_retention == TRUE) {
2113 				start_state = last_known_state;
2114 #ifdef DEBUG
2115 				printf("\tWe are assuming state retention (%d)...\n", start_state);
2116 #endif
2117 				}
2118 			else {
2119 #ifdef DEBUG
2120 				printf("\tWe are NOT assuming state retention...\n");
2121 #endif
2122 				if(display_type == DISPLAY_HOST_TRENDS)
2123 					start_state = AS_HOST_UP;
2124 				else
2125 					start_state = AS_SVC_OK;
2126 				}
2127 			}
2128 		else {
2129 #ifdef DEBUG
2130 			printf("We ARE NOT assuming initial states!\n");
2131 #endif
2132 			return;
2133 			}
2134 		}
2135 	else {
2136 		start_state = first_state;
2137 		last_known_state = first_state;
2138 		}
2139 
2140 #ifdef DEBUG
2141 	printf("Graphing state %d\n", start_state);
2142 	printf("\tfrom %s", ctime(&start_time));
2143 	printf("\tto %s", ctime(&end_time));
2144 #endif
2145 
2146 	if(start_time < t1)
2147 		start_time = t1;
2148 	if(end_time > t2)
2149 		end_time = t2;
2150 	if(end_time < t1 || start_time > t2)
2151 		return;
2152 
2153 	/* calculate the first and last pixels to use */
2154 	if(start_time == t1)
2155 		start_pixel = 0;
2156 	else {
2157 		start_pixel_ratio = ((double)(start_time - t1)) / ((double)(t2 - t1));
2158 		start_pixel = (int)(start_pixel_ratio * (drawing_width - 1));
2159 		}
2160 	if(end_time == t1)
2161 		end_pixel = 0;
2162 	else {
2163 		end_pixel_ratio = ((double)(end_time - t1)) / ((double)(t2 - t1));
2164 		end_pixel = (int)(end_pixel_ratio * (drawing_width - 1));
2165 		}
2166 
2167 #ifdef DEBUG
2168 	printf("\tPixel %d to %d\n\n", start_pixel, end_pixel);
2169 #endif
2170 
2171 
2172 	/* we're creating the image, so draw... */
2173 	if(mode == CREATE_IMAGE) {
2174 
2175 		/* figure out the color to use for drawing */
2176 		switch(start_state) {
2177 			case AS_HOST_UP:
2178 				color_to_use = color_green;
2179 				height = 60;
2180 				break;
2181 			case AS_HOST_DOWN:
2182 				color_to_use = color_red;
2183 				height = 40;
2184 				break;
2185 			case AS_HOST_UNREACHABLE:
2186 				color_to_use = color_darkred;
2187 				height = 20;
2188 				break;
2189 			case AS_SVC_OK:
2190 				color_to_use = color_green;
2191 				height = 80;
2192 				break;
2193 			case AS_SVC_WARNING:
2194 				color_to_use = color_yellow;
2195 				height = 60;
2196 				break;
2197 			case AS_SVC_UNKNOWN:
2198 				color_to_use = color_orange;
2199 				height = 40;
2200 				break;
2201 			case AS_SVC_CRITICAL:
2202 				color_to_use = color_red;
2203 				height = 20;
2204 				break;
2205 			default:
2206 				color_to_use = color_black;
2207 				height = 0;
2208 				break;
2209 			}
2210 
2211 		/* draw a rectangle */
2212 		if(start_state != AS_NO_DATA)
2213 			gdImageFilledRectangle(trends_image, start_pixel + drawing_x_offset, drawing_height - height + drawing_y_offset, end_pixel + drawing_x_offset, drawing_height + drawing_y_offset, color_to_use);
2214 		}
2215 
2216 	/* else we're creating the HTML, so write map area code... */
2217 	else {
2218 
2219 
2220 		/* figure out the the state string to use */
2221 		switch(start_state) {
2222 			case AS_HOST_UP:
2223 				strcpy(state_string, "UP");
2224 				height = 60;
2225 				break;
2226 			case AS_HOST_DOWN:
2227 				strcpy(state_string, "DOWN");
2228 				height = 40;
2229 				break;
2230 			case AS_HOST_UNREACHABLE:
2231 				strcpy(state_string, "UNREACHABLE");
2232 				height = 20;
2233 				break;
2234 			case AS_SVC_OK:
2235 				strcpy(state_string, "OK");
2236 				height = 80;
2237 				break;
2238 			case AS_SVC_WARNING:
2239 				strcpy(state_string, "WARNING");
2240 				height = 60;
2241 				break;
2242 			case AS_SVC_UNKNOWN:
2243 				strcpy(state_string, "UNKNOWN");
2244 				height = 40;
2245 				break;
2246 			case AS_SVC_CRITICAL:
2247 				strcpy(state_string, "CRITICAL");
2248 				height = 20;
2249 				break;
2250 			default:
2251 				strcpy(state_string, "?");
2252 				height = 5;
2253 				break;
2254 			}
2255 
2256 		/* get the center of this time range */
2257 		center_time = start_time + ((end_time - start_time) / 2);
2258 
2259 		/* determine next start and end time range with zoom factor */
2260 		if(zoom_factor > 0) {
2261 			next_start_time = center_time - (((t2 - t1) / 2) / zoom_factor);
2262 			next_end_time = center_time + (((t2 - t1) / 2) / zoom_factor);
2263 			}
2264 		else {
2265 			next_start_time = center_time + (((t2 - t1) / 2) * zoom_factor);
2266 			next_end_time = center_time - (((t2 - t1) / 2) * zoom_factor);
2267 			}
2268 
2269 		printf("<AREA shape='rect' ");
2270 
2271 		printf("coords='%d,%d,%d,%d' ", drawing_x_offset + start_pixel, drawing_y_offset + (drawing_height - height), drawing_x_offset + end_pixel, drawing_y_offset + drawing_height);
2272 
2273 #ifdef LEGACY_GRAPHICAL_CGIS
2274 		printf("href='%s?t1=%llu&t2=%llu&host=%s", TRENDS_CGI, (unsigned long long)next_start_time, (unsigned long long)next_end_time, url_encode(host_name));
2275 #else
2276 		printf("href='%s?t1=%llu&t2=%llu&host=%s", LEGACY_TRENDS_CGI, (unsigned long long)next_start_time, (unsigned long long)next_end_time, url_encode(host_name));
2277 #endif
2278 		if(display_type == DISPLAY_SERVICE_TRENDS)
2279 			printf("&service=%s", url_encode(svc_description));
2280 		printf("&assumeinitialstates=%s", (assume_initial_states == TRUE) ? "yes" : "no");
2281 		printf("&initialassumedhoststate=%d", initial_assumed_host_state);
2282 		printf("&initialassumedservicestate=%d", initial_assumed_service_state);
2283 		printf("&assumestateretention=%s", (assume_state_retention == TRUE) ? "yes" : "no");
2284 		printf("&assumestatesduringnotrunning=%s", (assume_states_during_notrunning == TRUE) ? "yes" : "no");
2285 		printf("&includesoftstates=%s", (include_soft_states == TRUE) ? "yes" : "no");
2286 		if(backtrack_archives > 0)
2287 			printf("&backtrack=%d", backtrack_archives);
2288 		printf("&zoom=%d", zoom_factor);
2289 
2290 		printf("' ");
2291 
2292 		/* display popup text */
2293 		if(display_popups == TRUE) {
2294 
2295 			snprintf(start_timestring, sizeof(start_timestring) - 1, "%s", ctime(&real_start_time));
2296 			start_timestring[sizeof(start_timestring) - 1] = '\x0';
2297 			start_timestring[strlen(start_timestring) - 1] = '\x0';
2298 
2299 			snprintf(end_timestring, sizeof(end_timestring) - 1, "%s", ctime(&end_time));
2300 			end_timestring[sizeof(end_timestring) - 1] = '\x0';
2301 			end_timestring[strlen(end_timestring) - 1] = '\x0';
2302 
2303 			/* calculate total time in this state */
2304 			get_time_breakdown((time_t)(end_time - start_time), &days, &hours, &minutes, &seconds);
2305 
2306 			/* sanitize plugin output */
2307 			sanitize_plugin_output(state_info);
2308 
2309 			printf("onMouseOver='showPopup(\"");
2310 			snprintf(temp_buffer, sizeof(temp_buffer) - 1, "<B><U>%s</U></B><BR><B>Time Range</B>: <I>%s</I> to <I>%s</I><BR><B>Duration</B>: <I>%dd %dh %dm %ds</I><BR><B>State Info</B>: <I>%s</I>", state_string, start_timestring, end_timestring, days, hours, minutes, seconds, (state_info == NULL) ? "N/A" : state_info);
2311 			temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
2312 			printf("%s", temp_buffer);
2313 			printf("\",event)' onMouseOut='hidePopup()'");
2314 			}
2315 
2316 		printf(">\n");
2317 
2318 		}
2319 
2320 
2321 	/* calculate time in this state */
2322 	switch(start_state) {
2323 		case AS_HOST_UP:
2324 			time_up += (unsigned long)(end_time - start_time);
2325 			break;
2326 		case AS_HOST_DOWN:
2327 			time_down += (unsigned long)(end_time - start_time);
2328 			break;
2329 		case AS_HOST_UNREACHABLE:
2330 			time_unreachable += (unsigned long)(end_time - start_time);
2331 			break;
2332 		case AS_SVC_OK:
2333 			time_ok += (unsigned long)(end_time - start_time);
2334 			break;
2335 		case AS_SVC_WARNING:
2336 			time_warning += (unsigned long)(end_time - start_time);
2337 			break;
2338 		case AS_SVC_UNKNOWN:
2339 			time_unknown += (unsigned long)(end_time - start_time);
2340 			break;
2341 		case AS_SVC_CRITICAL:
2342 			time_critical += (unsigned long)(end_time - start_time);
2343 			break;
2344 		default:
2345 			break;
2346 		}
2347 
2348 	return;
2349 	}
2350 
2351 
2352 
2353 /* convert current host state to archived state value */
convert_host_state_to_archived_state(int current_status)2354 int convert_host_state_to_archived_state(int current_status) {
2355 
2356 	if(current_status == SD_HOST_UP)
2357 		return AS_HOST_UP;
2358 	if(current_status == SD_HOST_DOWN)
2359 		return AS_HOST_DOWN;
2360 	if(current_status == SD_HOST_UNREACHABLE)
2361 		return AS_HOST_UNREACHABLE;
2362 
2363 	return AS_NO_DATA;
2364 	}
2365 
2366 
2367 /* convert current service state to archived state value */
convert_service_state_to_archived_state(int current_status)2368 int convert_service_state_to_archived_state(int current_status) {
2369 
2370 	if(current_status == SERVICE_OK)
2371 		return AS_SVC_OK;
2372 	if(current_status == SERVICE_UNKNOWN)
2373 		return AS_SVC_UNKNOWN;
2374 	if(current_status == SERVICE_WARNING)
2375 		return AS_SVC_WARNING;
2376 	if(current_status == SERVICE_CRITICAL)
2377 		return AS_SVC_CRITICAL;
2378 
2379 	return AS_NO_DATA;
2380 	}
2381 
2382 
2383 
2384 /* adds an archived state entry */
add_archived_state(int entry_type,int state_type,time_t time_stamp,char * state_info)2385 void add_archived_state(int entry_type, int state_type, time_t time_stamp, char *state_info) {
2386 	archived_state *last_as = NULL;
2387 	archived_state *temp_as = NULL;
2388 	archived_state *new_as = NULL;
2389 
2390 #ifdef DEBUG
2391 	printf("Added state %d @ %s", state_type, ctime(&time_stamp));
2392 #endif
2393 
2394 	/* allocate memory for the new entry */
2395 	new_as = (archived_state *)malloc(sizeof(archived_state));
2396 	if(new_as == NULL)
2397 		return;
2398 
2399 	/* allocate memory fo the state info */
2400 	if(state_info != NULL) {
2401 		new_as->state_info = (char *)malloc(strlen(state_info) + 1);
2402 		if(new_as->state_info != NULL)
2403 			strcpy(new_as->state_info, state_info);
2404 		}
2405 	else new_as->state_info = NULL;
2406 
2407 	new_as->entry_type = entry_type;
2408 	new_as->processed_state = entry_type;
2409 	new_as->state_type = state_type;
2410 	new_as->time_stamp = time_stamp;
2411 
2412 	/* add the new entry to the list in memory, sorted by time */
2413 	last_as = as_list;
2414 	for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
2415 		if(new_as->time_stamp < temp_as->time_stamp) {
2416 			new_as->next = temp_as;
2417 			if(temp_as == as_list)
2418 				as_list = new_as;
2419 			else
2420 				last_as->next = new_as;
2421 			break;
2422 			}
2423 		else
2424 			last_as = temp_as;
2425 		}
2426 	if(as_list == NULL) {
2427 		new_as->next = NULL;
2428 		as_list = new_as;
2429 		}
2430 	else if(temp_as == NULL) {
2431 		new_as->next = NULL;
2432 		last_as->next = new_as;
2433 		}
2434 
2435 	return;
2436 	}
2437 
2438 
2439 /* frees memory allocated to the archived state list */
free_archived_state_list(void)2440 void free_archived_state_list(void) {
2441 	archived_state *this_as = NULL;
2442 	archived_state *next_as = NULL;
2443 
2444 	for(this_as = as_list; this_as != NULL;) {
2445 		next_as = this_as->next;
2446 		if(this_as->state_info != NULL)
2447 			free(this_as->state_info);
2448 		free(this_as);
2449 		this_as = next_as;
2450 		}
2451 
2452 	as_list = NULL;
2453 
2454 	return;
2455 	}
2456 
2457 
2458 /* reads log files for archived state data */
read_archived_state_data(void)2459 void read_archived_state_data(void) {
2460 	char filename[MAX_FILENAME_LENGTH];
2461 	int newest_archive = 0;
2462 	int oldest_archive = 0;
2463 	int current_archive;
2464 
2465 #ifdef DEBUG
2466 	printf("Determining archives to use...\n");
2467 #endif
2468 
2469 	/* determine earliest archive to use */
2470 	oldest_archive = determine_archive_to_use_from_time(t1);
2471 	if(log_rotation_method != LOG_ROTATION_NONE)
2472 		oldest_archive += backtrack_archives;
2473 
2474 	/* determine most recent archive to use */
2475 	newest_archive = determine_archive_to_use_from_time(t2);
2476 
2477 	if(oldest_archive < newest_archive)
2478 		oldest_archive = newest_archive;
2479 
2480 #ifdef DEBUG
2481 	printf("Oldest archive: %d\n", oldest_archive);
2482 	printf("Newest archive: %d\n", newest_archive);
2483 #endif
2484 
2485 	/* read in all the necessary archived logs */
2486 	for(current_archive = newest_archive; current_archive <= oldest_archive; current_archive++) {
2487 
2488 		/* get the name of the log file that contains this archive */
2489 		get_log_archive_to_use(current_archive, filename, sizeof(filename) - 1);
2490 
2491 #ifdef DEBUG
2492 		printf("\tCurrent archive: %d (%s)\n", current_archive, filename);
2493 #endif
2494 
2495 		/* scan the log file for archived state data */
2496 		scan_log_file_for_archived_state_data(filename);
2497 		}
2498 
2499 	return;
2500 	}
2501 
2502 
2503 
2504 /* grabs archives state data from a log file */
scan_log_file_for_archived_state_data(char * filename)2505 void scan_log_file_for_archived_state_data(char *filename) {
2506 	char *input = NULL;
2507 	char *input2 = NULL;
2508 	char entry_host_name[MAX_INPUT_BUFFER];
2509 	char entry_svc_description[MAX_INPUT_BUFFER];
2510 	char *plugin_output = NULL;
2511 	char *temp_buffer = NULL;
2512 	time_t time_stamp;
2513 	mmapfile *thefile = NULL;
2514 	int state_type = 0;
2515 
2516 	/* print something so browser doesn't time out */
2517 	if(mode == CREATE_HTML) {
2518 		printf(" ");
2519 		fflush(NULL);
2520 		}
2521 
2522 	if((thefile = mmap_fopen(filename)) == NULL) {
2523 #ifdef DEBUG
2524 		printf("Could not open file '%s' for reading.\n", filename);
2525 #endif
2526 		return;
2527 		}
2528 
2529 #ifdef DEBUG
2530 	printf("Scanning log file '%s' for archived state data...\n", filename);
2531 #endif
2532 
2533 	while(1) {
2534 
2535 		/* free memory */
2536 		free(input);
2537 		free(input2);
2538 		input = NULL;
2539 		input2 = NULL;
2540 
2541 		/* read the next line */
2542 		if((input = mmap_fgets(thefile)) == NULL)
2543 			break;
2544 
2545 		strip(input);
2546 
2547 		if((input2 = strdup(input)) == NULL)
2548 			continue;
2549 
2550 		temp_buffer = my_strtok(input2, "]");
2551 		time_stamp = (temp_buffer == NULL) ? (time_t)0 : (time_t)strtoul(temp_buffer + 1, NULL, 10);
2552 
2553 		/* program starts/restarts */
2554 		if(strstr(input, " starting..."))
2555 			add_archived_state(AS_PROGRAM_START, AS_NO_DATA, time_stamp, "Program start");
2556 		if(strstr(input, " restarting..."))
2557 			add_archived_state(AS_PROGRAM_START, AS_NO_DATA, time_stamp, "Program restart");
2558 
2559 		/* program stops */
2560 		if(strstr(input, " shutting down..."))
2561 			add_archived_state(AS_PROGRAM_END, AS_NO_DATA, time_stamp, "Normal program termination");
2562 		if(strstr(input, "Bailing out"))
2563 			add_archived_state(AS_PROGRAM_END, AS_NO_DATA, time_stamp, "Abnormal program termination");
2564 
2565 		if(display_type == DISPLAY_HOST_TRENDS) {
2566 			if(strstr(input, "HOST ALERT:") || strstr(input, "INITIAL HOST STATE:") || strstr(input, "CURRENT HOST STATE:")) {
2567 
2568 				free(input2);
2569 				if((input2 = strdup(input)) == NULL)
2570 					continue;
2571 
2572 				/* get host name */
2573 				temp_buffer = my_strtok(input2, "]");
2574 				temp_buffer = my_strtok(NULL, ":");
2575 				temp_buffer = my_strtok(NULL, ";");
2576 				strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name));
2577 				entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
2578 
2579 				if(strcmp(host_name, entry_host_name))
2580 					continue;
2581 
2582 				/* state types */
2583 				if(strstr(input, ";SOFT;")) {
2584 					if(include_soft_states == FALSE)
2585 						continue;
2586 					state_type = AS_SOFT_STATE;
2587 					}
2588 				if(strstr(input, ";HARD;"))
2589 					state_type = AS_HARD_STATE;
2590 
2591 				/* get the plugin output */
2592 				temp_buffer = my_strtok(NULL, ";");
2593 				temp_buffer = my_strtok(NULL, ";");
2594 				temp_buffer = my_strtok(NULL, ";");
2595 				plugin_output = my_strtok(NULL, "\n");
2596 
2597 				if(strstr(input, ";DOWN;"))
2598 					add_archived_state(AS_HOST_DOWN, state_type, time_stamp, plugin_output);
2599 				else if(strstr(input, ";UNREACHABLE;"))
2600 					add_archived_state(AS_HOST_UNREACHABLE, state_type, time_stamp, plugin_output);
2601 				else if(strstr(input, ";RECOVERY") || strstr(input, ";UP;"))
2602 					add_archived_state(AS_HOST_UP, state_type, time_stamp, plugin_output);
2603 				else
2604 					add_archived_state(AS_NO_DATA, AS_NO_DATA, time_stamp, plugin_output);
2605 				}
2606 			}
2607 		if(display_type == DISPLAY_SERVICE_TRENDS) {
2608 			if(strstr(input, "SERVICE ALERT:") || strstr(input, "INITIAL SERVICE STATE:") || strstr(input, "CURRENT SERVICE STATE:")) {
2609 
2610 				free(input2);
2611 				if((input2 = strdup(input)) == NULL)
2612 					continue;
2613 
2614 				/* get host name */
2615 				temp_buffer = my_strtok(input2, "]");
2616 				temp_buffer = my_strtok(NULL, ":");
2617 				temp_buffer = my_strtok(NULL, ";");
2618 				strncpy(entry_host_name, (temp_buffer == NULL) ? "" : temp_buffer + 1, sizeof(entry_host_name));
2619 				entry_host_name[sizeof(entry_host_name) - 1] = '\x0';
2620 
2621 				if(strcmp(host_name, entry_host_name))
2622 					continue;
2623 
2624 				/* get service description */
2625 				temp_buffer = my_strtok(NULL, ";");
2626 				strncpy(entry_svc_description, (temp_buffer == NULL) ? "" : temp_buffer, sizeof(entry_svc_description));
2627 				entry_svc_description[sizeof(entry_svc_description) - 1] = '\x0';
2628 
2629 				if(strcmp(svc_description, entry_svc_description))
2630 					continue;
2631 
2632 				/* state types */
2633 				if(strstr(input, ";SOFT;")) {
2634 					if(include_soft_states == FALSE)
2635 						continue;
2636 					state_type = AS_SOFT_STATE;
2637 					}
2638 				if(strstr(input, ";HARD;"))
2639 					state_type = AS_HARD_STATE;
2640 
2641 				/* get the plugin output */
2642 				temp_buffer = my_strtok(NULL, ";");
2643 				temp_buffer = my_strtok(NULL, ";");
2644 				temp_buffer = my_strtok(NULL, ";");
2645 				plugin_output = my_strtok(NULL, "\n");
2646 
2647 				if(strstr(input, ";CRITICAL;"))
2648 					add_archived_state(AS_SVC_CRITICAL, state_type, time_stamp, plugin_output);
2649 				else if(strstr(input, ";WARNING;"))
2650 					add_archived_state(AS_SVC_WARNING, state_type, time_stamp, plugin_output);
2651 				else if(strstr(input, ";UNKNOWN;"))
2652 					add_archived_state(AS_SVC_UNKNOWN, state_type, time_stamp, plugin_output);
2653 				else if(strstr(input, ";RECOVERY;") || strstr(input, ";OK;"))
2654 					add_archived_state(AS_SVC_OK, state_type, time_stamp, plugin_output);
2655 				else
2656 					add_archived_state(AS_NO_DATA, AS_NO_DATA, time_stamp, plugin_output);
2657 
2658 				}
2659 			}
2660 
2661 		}
2662 
2663 	/* free memory and close the file */
2664 	free(input);
2665 	free(input2);
2666 	mmap_fclose(thefile);
2667 
2668 	return;
2669 	}
2670 
2671 
2672 
2673 /* write JavaScript code and layer for popup window */
write_popup_code(void)2674 void write_popup_code(void) {
2675 	char *border_color = "#000000";
2676 	char *background_color = "#ffffcc";
2677 	int border = 1;
2678 	int padding = 3;
2679 	int x_offset = 3;
2680 	int y_offset = 3;
2681 
2682 	printf("<SCRIPT LANGUAGE='JavaScript'>\n");
2683 	printf("<!--\n");
2684 	printf("// JavaScript popup based on code originally found at http://www.helpmaster.com/htmlhelp/javascript/popjbpopup.htm\n");
2685 	printf("function showPopup(text, eventObj){\n");
2686 	printf("if(!document.all && document.getElementById)\n");
2687 	printf("{ document.all=document.getElementsByTagName(\"*\")}\n");
2688 	printf("ieLayer = 'document.all[\\'popup\\']';\n");
2689 	printf("nnLayer = 'document.layers[\\'popup\\']';\n");
2690 	printf("moLayer = 'document.getElementById(\\'popup\\')';\n");
2691 
2692 	printf("if(!(document.all||document.layers||document.documentElement)) return;\n");
2693 
2694 	printf("if(document.all) { document.popup=eval(ieLayer); }\n");
2695 	printf("else {\n");
2696 	printf("  if (document.documentElement) document.popup=eval(moLayer);\n");
2697 	printf("  else document.popup=eval(nnLayer);\n");
2698 	printf("}\n");
2699 
2700 	printf("var table = \"\";\n");
2701 
2702 	printf("if (document.all||document.documentElement){\n");
2703 	printf("table += \"<table bgcolor='%s' border=%d cellpadding=%d cellspacing=0>\";\n", background_color, border, padding);
2704 	printf("table += \"<tr><td>\";\n");
2705 	printf("table += \"<table cellspacing=0 cellpadding=%d>\";\n", padding);
2706 	printf("table += \"<tr><td bgcolor='%s' class='popupText'>\" + text + \"</td></tr>\";\n", background_color);
2707 	printf("table += \"</table></td></tr></table>\"\n");
2708 	printf("document.popup.innerHTML = table;\n");
2709 	printf("document.popup.style.left = (document.all ? eventObj.x : eventObj.layerX) + %d;\n", x_offset);
2710 	printf("document.popup.style.top  = (document.all ? eventObj.y : eventObj.layerY) + %d;\n", y_offset);
2711 	printf("document.popup.style.visibility = \"visible\";\n");
2712 	printf("} \n");
2713 
2714 
2715 	printf("else{\n");
2716 	printf("table += \"<table cellpadding=%d border=%d cellspacing=0 bordercolor='%s'>\";\n", padding, border, border_color);
2717 	printf("table += \"<tr><td bgcolor='%s' class='popupText'>\" + text + \"</td></tr></table>\";\n", background_color);
2718 	printf("document.popup.document.open();\n");
2719 	printf("document.popup.document.write(table);\n");
2720 	printf("document.popup.document.close();\n");
2721 
2722 	/* set x coordinate */
2723 	printf("document.popup.left = eventObj.layerX + %d;\n", x_offset);
2724 
2725 	/* make sure we don't overlap the right side of the screen */
2726 	printf("if(document.popup.left + document.popup.document.width + %d > window.innerWidth) document.popup.left = window.innerWidth - document.popup.document.width - %d - 16;\n", x_offset, x_offset);
2727 
2728 	/* set y coordinate */
2729 	printf("document.popup.top  = eventObj.layerY + %d;\n", y_offset);
2730 
2731 	/* make sure we don't overlap the bottom edge of the screen */
2732 	printf("if(document.popup.top + document.popup.document.height + %d > window.innerHeight) document.popup.top = window.innerHeight - document.popup.document.height - %d - 16;\n", y_offset, y_offset);
2733 
2734 	/* make the popup visible */
2735 	printf("document.popup.visibility = \"visible\";\n");
2736 	printf("}\n");
2737 	printf("}\n");
2738 
2739 	printf("function hidePopup(){ \n");
2740 	printf("if (!(document.all || document.layers || document.documentElement)) return;\n");
2741 	printf("if (document.popup == null){ }\n");
2742 	printf("else if (document.all||document.documentElement) document.popup.style.visibility = \"hidden\";\n");
2743 	printf("else document.popup.visibility = \"hidden\";\n");
2744 	printf("document.popup = null;\n");
2745 	printf("}\n");
2746 	printf("//-->\n");
2747 
2748 	printf("</SCRIPT>\n");
2749 
2750 	return;
2751 	}
2752 
2753 
2754 
2755 
2756 /* write timestamps */
draw_timestamps(void)2757 void draw_timestamps(void) {
2758 	int last_timestamp = 0;
2759 	archived_state *temp_as;
2760 	double start_pixel_ratio;
2761 	int start_pixel;
2762 
2763 	if(mode != CREATE_IMAGE)
2764 		return;
2765 
2766 	/* draw first timestamp */
2767 	draw_timestamp(0, t1);
2768 	last_timestamp = 0;
2769 
2770 	for(temp_as = as_list; temp_as != NULL; temp_as = temp_as->next) {
2771 
2772 		if(temp_as->time_stamp < t1 || temp_as->time_stamp > t2)
2773 			continue;
2774 
2775 		start_pixel_ratio = ((double)(temp_as->time_stamp - t1)) / ((double)(t2 - t1));
2776 		start_pixel = (int)(start_pixel_ratio * (drawing_width - 1));
2777 
2778 		/* draw start timestamp if possible */
2779 		if((start_pixel > last_timestamp + MIN_TIMESTAMP_SPACING) && (start_pixel < drawing_width - 1 - MIN_TIMESTAMP_SPACING)) {
2780 			draw_timestamp(start_pixel, temp_as->time_stamp);
2781 			last_timestamp = start_pixel;
2782 			}
2783 		}
2784 
2785 	/* draw last timestamp */
2786 	draw_timestamp(drawing_width - 1, t2);
2787 
2788 	return;
2789 	}
2790 
2791 
2792 /* write timestamp below graph */
draw_timestamp(int ts_pixel,time_t ts_time)2793 void draw_timestamp(int ts_pixel, time_t ts_time) {
2794 	char temp_buffer[MAX_INPUT_BUFFER];
2795 	int string_height;
2796 	int string_width;
2797 
2798 	snprintf(temp_buffer, sizeof(temp_buffer) - 1, "%s", ctime(&ts_time));
2799 	temp_buffer[sizeof(temp_buffer) - 1] = '\x0';
2800 	temp_buffer[strlen(temp_buffer) - 1] = '\x0';
2801 
2802 	string_height = gdFontSmall->h;
2803 	string_width = gdFontSmall->w * strlen(temp_buffer);
2804 
2805 	if(small_image == FALSE)
2806 		gdImageStringUp(trends_image, gdFontSmall, ts_pixel + drawing_x_offset - (string_height / 2), drawing_y_offset + drawing_height + string_width + 5, (unsigned char *)temp_buffer, color_black);
2807 
2808 	/* draw a dashed vertical line at this point */
2809 	if(ts_pixel > 0 && ts_pixel < (drawing_width - 1))
2810 		draw_dashed_line(ts_pixel + drawing_x_offset, drawing_y_offset, ts_pixel + drawing_x_offset, drawing_y_offset + drawing_height, color_black);
2811 
2812 	return;
2813 	}
2814 
2815 
2816 
2817 /* draw total state times */
draw_time_breakdowns(void)2818 void draw_time_breakdowns(void) {
2819 	char temp_buffer[MAX_INPUT_BUFFER];
2820 	unsigned long total_time = 0L;
2821 	unsigned long total_state_time;
2822 	unsigned long time_indeterminate = 0L;
2823 
2824 	if(mode == CREATE_HTML)
2825 		return;
2826 
2827 	if(small_image == TRUE)
2828 		return;
2829 
2830 	total_time = (unsigned long)(t2 - t1);
2831 
2832 	if(display_type == DISPLAY_HOST_TRENDS)
2833 		total_state_time = time_up + time_down + time_unreachable;
2834 	else
2835 		total_state_time = time_ok + time_warning + time_unknown + time_critical;
2836 
2837 	if(total_state_time >= total_time)
2838 		time_indeterminate = 0L;
2839 	else
2840 		time_indeterminate = total_time - total_state_time;
2841 
2842 
2843 	if(display_type == DISPLAY_HOST_TRENDS) {
2844 
2845 		get_time_breakdown_string(total_time, time_up, "Up", &temp_buffer[0], sizeof(temp_buffer));
2846 		gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 5, (unsigned char *)temp_buffer, color_darkgreen);
2847 		gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 2), drawing_y_offset + 5, (unsigned char *)"Up", color_darkgreen);
2848 
2849 		get_time_breakdown_string(total_time, time_down, "Down", &temp_buffer[0], sizeof(temp_buffer));
2850 		gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 25, (unsigned char *)temp_buffer, color_red);
2851 		gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 4), drawing_y_offset + 25, (unsigned char *)"Down", color_red);
2852 
2853 		get_time_breakdown_string(total_time, time_unreachable, "Unreachable", &temp_buffer[0], sizeof(temp_buffer));
2854 		gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 45, (unsigned char *)temp_buffer, color_darkred);
2855 		gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 11), drawing_y_offset + 45, (unsigned char *)"Unreachable", color_darkred);
2856 
2857 		get_time_breakdown_string(total_time, time_indeterminate, "Indeterminate", &temp_buffer[0], sizeof(temp_buffer));
2858 		gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 65, (unsigned char *)temp_buffer, color_black);
2859 		gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 13), drawing_y_offset + 65, (unsigned char *)"Indeterminate", color_black);
2860 		}
2861 	else {
2862 		get_time_breakdown_string(total_time, time_ok, "Ok", &temp_buffer[0], sizeof(temp_buffer));
2863 		gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 5, (unsigned char *)temp_buffer, color_darkgreen);
2864 		gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 2), drawing_y_offset + 5, (unsigned char *)"Ok", color_darkgreen);
2865 
2866 		get_time_breakdown_string(total_time, time_warning, "Warning", &temp_buffer[0], sizeof(temp_buffer));
2867 		gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 25, (unsigned char *)temp_buffer, color_yellow);
2868 		gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 7), drawing_y_offset + 25, (unsigned char *)"Warning", color_yellow);
2869 
2870 		get_time_breakdown_string(total_time, time_unknown, "Unknown", &temp_buffer[0], sizeof(temp_buffer));
2871 		gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 45, (unsigned char *)temp_buffer, color_orange);
2872 		gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 7), drawing_y_offset + 45, (unsigned char *)"Unknown", color_orange);
2873 
2874 		get_time_breakdown_string(total_time, time_critical, "Critical", &temp_buffer[0], sizeof(temp_buffer));
2875 		gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 65, (unsigned char *)temp_buffer, color_red);
2876 		gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 8), drawing_y_offset + 65, (unsigned char *)"Critical", color_red);
2877 
2878 		get_time_breakdown_string(total_time, time_indeterminate, "Indeterminate", &temp_buffer[0], sizeof(temp_buffer));
2879 		gdImageString(trends_image, gdFontSmall, drawing_x_offset + drawing_width + 20, drawing_y_offset + 85, (unsigned char *)temp_buffer, color_black);
2880 		gdImageString(trends_image, gdFontSmall, drawing_x_offset - 10 - (gdFontSmall->w * 13), drawing_y_offset + 85, (unsigned char *)"Indeterminate", color_black);
2881 		}
2882 
2883 	return;
2884 	}
2885 
2886 
get_time_breakdown_string(unsigned long total_time,unsigned long state_time,char * state_string,char * buffer,int buffer_length)2887 void get_time_breakdown_string(unsigned long total_time, unsigned long state_time, char *state_string, char *buffer, int buffer_length) {
2888 	int days;
2889 	int hours;
2890 	int minutes;
2891 	int seconds;
2892 	double percent_time;
2893 
2894 	get_time_breakdown(state_time, &days, &hours, &minutes, &seconds);
2895 	if(total_time == 0L)
2896 		percent_time = 0.0;
2897 	else
2898 		percent_time = ((double)state_time / total_time) * 100.0;
2899 	snprintf(buffer, buffer_length - 1, "%-13s: (%.3f%%) %dd %dh %dm %ds", state_string, percent_time, days, hours, minutes, seconds);
2900 	buffer[buffer_length - 1] = '\x0';
2901 
2902 	return;
2903 	}
2904 
2905 
convert_timeperiod_to_times(int type)2906 void convert_timeperiod_to_times(int type) {
2907 	time_t current_time;
2908 	struct tm *t;
2909 
2910 	/* get the current time */
2911 	time(&current_time);
2912 
2913 	t = localtime(&current_time);
2914 
2915 	t->tm_sec = 0;
2916 	t->tm_min = 0;
2917 	t->tm_hour = 0;
2918 	t->tm_isdst = -1;
2919 
2920 	switch(type) {
2921 		case TIMEPERIOD_LAST24HOURS:
2922 			t1 = current_time - (60 * 60 * 24);
2923 			t2 = current_time;
2924 			break;
2925 		case TIMEPERIOD_TODAY:
2926 			t1 = mktime(t);
2927 			t2 = current_time;
2928 			break;
2929 		case TIMEPERIOD_YESTERDAY:
2930 			t1 = (time_t)(mktime(t) - (60 * 60 * 24));
2931 			t2 = (time_t)mktime(t);
2932 			break;
2933 		case TIMEPERIOD_THISWEEK:
2934 			t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday));
2935 			t2 = current_time;
2936 			break;
2937 		case TIMEPERIOD_LASTWEEK:
2938 			t1 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday) - (60 * 60 * 24 * 7));
2939 			t2 = (time_t)(mktime(t) - (60 * 60 * 24 * t->tm_wday));
2940 			break;
2941 		case TIMEPERIOD_THISMONTH:
2942 			t->tm_mday = 1;
2943 			t1 = mktime(t);
2944 			t2 = current_time;
2945 			break;
2946 		case TIMEPERIOD_LASTMONTH:
2947 			t->tm_mday = 1;
2948 			t2 = mktime(t);
2949 			if(t->tm_mon == 0) {
2950 				t->tm_mon = 11;
2951 				t->tm_year--;
2952 				}
2953 			else
2954 				t->tm_mon--;
2955 			t1 = mktime(t);
2956 			break;
2957 		case TIMEPERIOD_THISQUARTER:
2958 			break;
2959 		case TIMEPERIOD_LASTQUARTER:
2960 			break;
2961 		case TIMEPERIOD_THISYEAR:
2962 			t->tm_mon = 0;
2963 			t->tm_mday = 1;
2964 			t1 = mktime(t);
2965 			t2 = current_time;
2966 			break;
2967 		case TIMEPERIOD_LASTYEAR:
2968 			t->tm_mon = 0;
2969 			t->tm_mday = 1;
2970 			t2 = mktime(t);
2971 			t->tm_year--;
2972 			t1 = mktime(t);
2973 			break;
2974 		case TIMEPERIOD_NEXTPROBLEM:
2975 			/* Time period will be defined later */
2976 			break;
2977 		case TIMEPERIOD_LAST7DAYS:
2978 			t2 = current_time;
2979 			t1 = current_time - (7 * 24 * 60 * 60);
2980 			break;
2981 		case TIMEPERIOD_LAST31DAYS:
2982 			t2 = current_time;
2983 			t1 = current_time - (31 * 24 * 60 * 60);
2984 			break;
2985 		default:
2986 			break;
2987 		}
2988 
2989 	return;
2990 	}
2991 
2992 
compute_report_times(void)2993 void compute_report_times(void) {
2994 	time_t current_time;
2995 	struct tm *st;
2996 	struct tm *et;
2997 
2998 	/* get the current time */
2999 	time(&current_time);
3000 
3001 	st = localtime(&current_time);
3002 
3003 	st->tm_sec = start_second;
3004 	st->tm_min = start_minute;
3005 	st->tm_hour = start_hour;
3006 	st->tm_mday = start_day;
3007 	st->tm_mon = start_month - 1;
3008 	st->tm_year = start_year - 1900;
3009 	st->tm_isdst = -1;
3010 
3011 	t1 = mktime(st);
3012 
3013 	et = localtime(&current_time);
3014 
3015 	et->tm_sec = end_second;
3016 	et->tm_min = end_minute;
3017 	et->tm_hour = end_hour;
3018 	et->tm_mday = end_day;
3019 	et->tm_mon = end_month - 1;
3020 	et->tm_year = end_year - 1900;
3021 	et->tm_isdst = -1;
3022 
3023 	t2 = mktime(et);
3024 	}
3025 
3026 
3027 
3028 /* draws a dashed line */
draw_dashed_line(int x1,int y1,int x2,int y2,int color)3029 void draw_dashed_line(int x1, int y1, int x2, int y2, int color) {
3030 	int styleDashed[12];
3031 
3032 	styleDashed[0] = color;
3033 	styleDashed[1] = color;
3034 	styleDashed[2] = gdTransparent;
3035 	styleDashed[3] = gdTransparent;
3036 	styleDashed[4] = color;
3037 	styleDashed[5] = color;
3038 	styleDashed[6] = gdTransparent;
3039 	styleDashed[7] = gdTransparent;
3040 	styleDashed[8] = color;
3041 	styleDashed[9] = color;
3042 	styleDashed[10] = gdTransparent;
3043 	styleDashed[11] = gdTransparent;
3044 
3045 	/* sets current style to a dashed line */
3046 	gdImageSetStyle(trends_image, styleDashed, 12);
3047 
3048 	/* draws a line (dashed) */
3049 	gdImageLine(trends_image, x1, y1, x2, y2, gdStyled);
3050 
3051 	return;
3052 	}
3053 
3054 
3055 /* draws horizontal grid lines */
draw_horizontal_grid_lines(void)3056 void draw_horizontal_grid_lines(void) {
3057 
3058 	if(mode == CREATE_HTML)
3059 		return;
3060 
3061 	if(small_image == TRUE)
3062 		return;
3063 
3064 	draw_dashed_line(drawing_x_offset, drawing_y_offset + 10, drawing_x_offset + drawing_width, drawing_y_offset + 10, color_black);
3065 	draw_dashed_line(drawing_x_offset, drawing_y_offset + 30, drawing_x_offset + drawing_width, drawing_y_offset + 30, color_black);
3066 	draw_dashed_line(drawing_x_offset, drawing_y_offset + 50, drawing_x_offset + drawing_width, drawing_y_offset + 50, color_black);
3067 	if(display_type == DISPLAY_SERVICE_TRENDS)
3068 		draw_dashed_line(drawing_x_offset, drawing_y_offset + 70, drawing_x_offset + drawing_width, drawing_y_offset + 70, color_black);
3069 
3070 	return;
3071 	}
3072