/* render help dialog */ void load_help_popup (WINDOW * main_win) { int c, quit = 1; size_t i, n; int y, x, h = HELP_WIN_HEIGHT, w = HELP_WIN_WIDTH; int w2 = w - 2; n = ARRAY_SIZE (help_main); getmaxyx (stdscr, y, x); WINDOW *win = newwin (h, w, (y - h) / 2, (x - w) / 2); keypad (win, TRUE); wborder (win, '|', '|', '-', '-', '+', '+', '+', '+'); /* create a new instance of GMenu and make it selectable */ GMenu *menu = new_gmenu (win, HELP_MENU_HEIGHT, HELP_MENU_WIDTH, HELP_MENU_Y, HELP_MENU_X); menu->size = n; /* add items to GMenu */ menu->items = (GItem *) xcalloc (n, sizeof (GItem)); for (i = 0; i < n; ++i) { menu->items[i].name = alloc_string (help_main[i]); menu->items[i].checked = 0; } post_gmenu (menu); draw_header (win, "GoAccess Quick Help", 1, 1, w2, 1); mvwprintw (win, 2, 2, "[UP/DOWN] to scroll - [q] to quit"); wrefresh (win); while (quit) { c = wgetch (stdscr); switch (c) { case KEY_DOWN: gmenu_driver (menu, REQ_DOWN); draw_header (win, "", 2, 3, HELP_MENU_WIDTH, 0); break; case KEY_UP: gmenu_driver (menu, REQ_UP); draw_header (win, "", 2, 3, HELP_MENU_WIDTH, 0); break; case KEY_RESIZE: case 'q': quit = 0; break; } wrefresh (win); } /* clean stuff up */ for (i = 0; i < n; ++i) free (menu->items[i].name); free (menu->items); free (menu); touchwin (main_win); close_win (win); wrefresh (main_win); }
/* render an actual menu item */ static void draw_menu_item (GMenu * menu, char *s, int x, int y, int w, int color, int checked) { char check, *lbl = NULL; if (menu->selectable) { check = checked ? 'x' : ' '; lbl = xmalloc (snprintf (NULL, 0, "[%c] %s", check, s) + 1); sprintf (lbl, "[%c] %s", check, s); draw_header (menu->win, lbl, "%s", y, x, w, color, 0); free (lbl); } else { draw_header (menu->win, s, "%s", y, x, w, color, 0); } }
/* render all windows */ static void render_screens (void) { GColors *color = get_color (COLOR_DEFAULT); int row, col, chg = 0; getmaxyx (stdscr, row, col); term_size (main_win); generate_time (); chg = logger->processed - logger->offset; draw_header (stdscr, "", "%s", row - 1, 0, col, color_default); wattron (stdscr, color->attr | COLOR_PAIR (color->pair->idx)); mvaddstr (row - 1, 1, "[F1]Help [Enter] Exp. Panel"); mvprintw (row - 1, 30, "%d - %s", chg, asctime (now_tm)); mvaddstr (row - 1, col - 21, "[Q]uit GoAccess"); mvprintw (row - 1, col - 5, "%s", GO_VERSION); wattroff (stdscr, color->attr | COLOR_PAIR (color->pair->idx)); refresh (); /* call general stats header */ display_general (header_win, conf.ifile, logger); wrefresh (header_win); /* display active label based on current module */ update_active_module (header_win, gscroll.current); display_content (main_win, logger, dash, &gscroll); }
/* render dashboard hits */ static void render_visitors (GDashModule * data, GDashRender render, int *x) { WINDOW *win = render.win; GModule module = data->module; const GDashStyle *style = module_style; char *visitors; int y = render.y, w = render.w, idx = render.idx, sel = render.sel; int len = data->visitors_len; if (data->module == HOSTS && data->data[idx].is_subitem) goto out; /* selected state */ if (sel) { visitors = int_to_str (data->data[idx].metrics->visitors); draw_header (win, visitors, "%*s", y, *x, w, HIGHLIGHT, len); free (visitors); } /* regular state */ else { wattron (win, A_BOLD | COLOR_PAIR (style[module].color_visitors)); mvwprintw (win, y, *x, "%*d", len, data->data[idx].metrics->visitors); wattroff (win, A_BOLD | COLOR_PAIR (style[module].color_visitors)); } out: *x += len + DASH_SPACE; }
/* render dashboard bandwidth */ static void render_bandwidth (GDashModule * data, GDashRender render, int *x) { WINDOW *win = render.win; GModule module = data->module; const GDashStyle *style = module_style; int y = render.y, w = render.w, idx = render.idx, sel = render.sel; char *bw = data->data[idx].metrics->bw.sbw; if (data->module == HOSTS && data->data[idx].is_subitem) goto out; if (style[module].color_bw == -1) return; /* selected state */ if (sel) { draw_header (win, bw, "%11s", y, *x, w, HIGHLIGHT, 0); } /* regular state */ else { wattron (win, A_BOLD | COLOR_PAIR (style[module].color_bw)); mvwprintw (win, y, *x, "%11s", bw); wattroff (win, A_BOLD | COLOR_PAIR (style[module].color_bw)); } out: *x += DASH_BW_LEN + DASH_SPACE; }
/* render dashboard request protocol */ static void render_protocol (GDashModule * data, GDashRender render, int *x) { WINDOW *win = render.win; GModule module = data->module; const GDashStyle *style = module_style; int y = render.y, w = render.w, idx = render.idx, sel = render.sel; char *protocol = data->data[idx].metrics->protocol; if (style[module].color_protocol == -1) return; if (protocol == NULL || *protocol == '\0') return; /* selected state */ if (sel) { draw_header (win, protocol, "%s", y, *x, w, HIGHLIGHT, 0); } /* regular state */ else { wattron (win, A_BOLD | COLOR_PAIR (style[module].color_protocol)); mvwprintw (win, y, *x, "%s", protocol); wattroff (win, A_BOLD | COLOR_PAIR (style[module].color_protocol)); } *x += REQ_PROTO_LEN - 1 + DASH_SPACE; }
/* render all windows */ static void render_screens (void) { int row, col, chg = 0; getmaxyx (stdscr, row, col); term_size (main_win); generate_time (); chg = logger->process - logger->offset; draw_header (stdscr, "", "%s", row - 1, 0, col, 0, 0); wattron (stdscr, COLOR_PAIR (COL_WHITE)); mvaddstr (row - 1, 1, "[F1]Help [O]pen detail view"); mvprintw (row - 1, 30, "%d - %s", chg, asctime (now_tm)); mvaddstr (row - 1, col - 21, "[Q]uit GoAccess"); mvprintw (row - 1, col - 5, "%s", GO_VERSION); wattroff (stdscr, COLOR_PAIR (COL_WHITE)); refresh (); /* call general stats header */ display_general (header_win, conf.ifile, logger); wrefresh (header_win); /* display active label based on current module */ update_active_module (header_win, gscroll.current); display_content (main_win, logger, dash, &gscroll); }
static void draw_page_text (GtkPrintOperation * op, GtkPrintContext * cnt, gint page, gpointer data) { cairo_t *cr; PangoLayout *layout; gint i, line; cr = gtk_print_context_get_cairo_context (cnt); /* create header */ if (options.print_data.headers) draw_header (cnt, page + 1, npages); /* add text */ layout = gtk_print_context_create_pango_layout (cnt); pango_layout_set_font_description (layout, fdesc); cairo_move_to (cr, 0, HEADER_HEIGHT + HEADER_GAP); line = page * nlines; for (i = 0; i < nlines; i++) { if (text[line + i] == NULL) break; pango_layout_set_text (layout, text[line + i], -1); pango_cairo_show_layout (cr, layout); cairo_rel_move_to (cr, 0, FONTSIZE); } g_object_unref (layout); }
// creates a new MandelPod window void new_mandel_window(void) { // get the graphics context mandel_gc = pz_get_gc(1); // create the main window mandel_wid = pz_new_window (0, 21, screen_info.cols, screen_info.rows - (HEADER_TOPLINE+1), draw_header, handle_event); #ifdef MANDELPOD_STATUS // create the status window status_wid = pz_new_window (22, 4, 12, 12, draw_idle_status, handle_event); #endif // get screen info GrGetWindowInfo(mandel_wid, &wi); // select the event types GrSelectEvents (mandel_wid, GR_EVENT_MASK_EXPOSURE | GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_KEY_UP | GR_EVENT_MASK_TIMER); // display the window GrMapWindow (mandel_wid); #ifdef MANDELPOD_STATUS GrMapWindow (status_wid); #endif // create the timer for the busy status animation mandel_timer_id = GrCreateTimer (mandel_wid, 250); // start main app init_values(); create_status(); draw_header(); calculate_mandel(); }
// Creates a new tunnel "app" window void new_tunnel_window(void) { tunnel_gc = pz_get_gc(1); /* Get the graphics context */ /* Open the window: */ tunnel_wid = pz_new_window (0, 21, screen_info.cols, screen_info.rows - (HEADER_TOPLINE+1), draw_header, handle_event); GrGetWindowInfo(tunnel_wid, &wi); /* Get screen info */ /* Select the types of events you need for your window: */ GrSelectEvents (tunnel_wid, GR_EVENT_MASK_TIMER|GR_EVENT_MASK_EXPOSURE|GR_EVENT_MASK_KEY_DOWN|GR_EVENT_MASK_KEY_UP); // set up pixmap temp_pixmap = GrNewPixmap(screen_info.cols, (screen_info.rows - (HEADER_TOPLINE + 1)), NULL); /* Display the window: */ GrMapWindow (tunnel_wid); draw_header(); readHighScore(); reset(); }
static void reset_board() { int index; for(index = 0; index < 9; index++) board[index] = '-'; difficulty = 6; gameRunning = 1; currSquare = 0; draw_header(); /* Clear the window */ GrClearWindow (tictactoe_wid, GR_FALSE); GrSetGCUseBackground(tictactoe_gc, GR_TRUE); GrSetGCBackground(tictactoe_gc, WHITE); GrSetGCForeground(tictactoe_gc, BLACK); GrLine(tictactoe_wid, tictactoe_gc, wi.width * .90, (wi.height / 2.) - (wi.height / 2. * .33), wi.width - wi.width * .90, (wi.height / 2.) - (wi.height / 2. * .33)); GrLine(tictactoe_wid, tictactoe_gc, wi.width * .90, (wi.height / 2.) + (wi.height / 2. * .33), wi.width - wi.width * .90, (wi.height / 2.) + (wi.height / 2. * .33)); GrLine(tictactoe_wid, tictactoe_gc, (wi.width / 2.) - (wi.width / 2. * .33), wi.height * .90, (wi.width / 2.) - (wi.width / 2. * .33), wi.height - wi.height * .90); GrLine(tictactoe_wid, tictactoe_gc, (wi.width / 2.) + (wi.width / 2. * .33), wi.height * .90, (wi.width / 2.) + (wi.width / 2. * .33), wi.height - wi.height * .90); currSquare = 0; drawXO(currSquare, GRAY, 'x'); }
/* Render the help dialog. */ static void load_confdlg_error (WINDOW * parent_win, char **errors, int nerrors) { int c, quit = 1, i = 0; int y, x, h = ERR_WIN_HEIGHT, w = ERR_WIN_WIDTH; WINDOW *win; GMenu *menu; getmaxyx (stdscr, y, x); win = newwin (h, w, (y - h) / 2, (x - w) / 2); keypad (win, TRUE); wborder (win, '|', '|', '-', '-', '+', '+', '+', '+'); /* create a new instance of GMenu and make it selectable */ menu = new_gmenu (win, ERR_MENU_HEIGHT, ERR_MENU_WIDTH, ERR_MENU_Y, ERR_MENU_X); menu->size = nerrors; /* add items to GMenu */ menu->items = (GItem *) xcalloc (nerrors, sizeof (GItem)); for (i = 0; i < nerrors; ++i) { menu->items[i].name = alloc_string (errors[i]); menu->items[i].checked = 0; free (errors[i]); } free (errors); post_gmenu (menu); draw_header (win, ERR_HEADER, " %s", 1, 1, w - 2, color_error); mvwprintw (win, 2, 2, "[UP/DOWN] to scroll - [q] to quit"); wrefresh (win); while (quit) { c = wgetch (stdscr); switch (c) { case KEY_DOWN: gmenu_driver (menu, REQ_DOWN); break; case KEY_UP: gmenu_driver (menu, REQ_UP); break; case KEY_RESIZE: case 'q': quit = 0; break; } wrefresh (win); } /* clean stuff up */ for (i = 0; i < nerrors; ++i) free (menu->items[i].name); free (menu->items); free (menu); touchwin (parent_win); close_win (win); wrefresh (parent_win); }
/* Print out (terminal dashboard) the overall statistics header. */ static void render_overall_header (WINDOW * win, GHolder * h) { char *hd = get_overall_header (h); int col = getmaxx (stdscr); draw_header (win, hd, " %s", 0, 0, col, color_panel_header); free (hd); }
static void disabled_panel_msg (GModule module) { const char *lbl = module_to_label (module); int row, col; getmaxyx (stdscr, row, col); draw_header (stdscr, lbl, "'%s' panel is disabled", row - 1, 0, col, WHITE_RED, 0); }
/* render dashboard data */ static void render_data (GDashModule * data, GDashRender render, int *x) { WINDOW *win = render.win; GModule module = data->module; const GDashStyle *style = module_style; int y = render.y, w = render.w, idx = render.idx, sel = render.sel; char buf[DATE_LEN]; char *value, *padded_data; value = substring (data->data[idx].metrics->data, 0, w - *x); if (module == VISITORS) { /* verify we have a valid date conversion */ if (convert_date (buf, value, "%Y%m%d", "%d/%b/%Y", DATE_LEN) != 0) { LOG_DEBUG (("invalid date: %s", value)); xstrncpy (buf, "---", 4); } } if (sel) { if (data->module == HOSTS && data->data[idx].is_subitem) { padded_data = left_pad_str (value, *x); draw_header (win, padded_data, "%s", y, 0, w, HIGHLIGHT, 0); free (padded_data); } else { draw_header (win, module == VISITORS ? buf : value, "%s", y, *x, w, HIGHLIGHT, 0); } } else { wattron (win, COLOR_PAIR (style[module].color_data)); mvwprintw (win, y, *x, "%s", module == VISITORS ? buf : value); wattroff (win, COLOR_PAIR (style[module].color_data)); } *x += module == VISITORS ? DATE_LEN - 1 : data->data_len; *x += DASH_SPACE; free (value); }
/* render processing spinner */ static void ui_spinner (void *ptr_data) { GSpinner *sp = (GSpinner *) ptr_data; GColors *color = NULL; static char const spin_chars[] = "/-\\|"; char buf[SPIN_LBL]; int i = 0; long long tdiff = 0, psec = 0; time_t begin; if (sp->curses) color = (*sp->color) (); time (&begin); while (1) { pthread_mutex_lock (&sp->mutex); if (sp->state == SPN_END) break; setlocale (LC_NUMERIC, ""); if (conf.no_progress) { snprintf (buf, sizeof buf, SPIN_FMT, sp->label); } else { tdiff = (long long) (time (NULL) - begin); psec = tdiff >= 1 ? *(sp->processed) / tdiff : 0; snprintf (buf, sizeof buf, SPIN_FMTM, sp->label, *(sp->processed), psec); } setlocale (LC_NUMERIC, "POSIX"); if (sp->curses) { /* CURSES */ draw_header (sp->win, buf, " %s", sp->y, sp->x, sp->w, sp->color); /* caret */ wattron (sp->win, COLOR_PAIR (color->pair->idx)); mvwaddch (sp->win, sp->y, sp->spin_x, spin_chars[i++ & 3]); wattroff (sp->win, COLOR_PAIR (color->pair->idx)); wrefresh (sp->win); } else if (!conf.no_progress) { /* STDOUT */ fprintf (stderr, "%s\r", buf); } pthread_mutex_unlock (&sp->mutex); usleep (100000); } sp = NULL; free (sp); }
static void draw_formats (WINDOW * win, int w2) { char *date_format = NULL, *log_format = NULL, *time_format = NULL; draw_header (win, "Log Format Configuration", " %s", 1, 1, w2, color_panel_header); mvwprintw (win, 2, 2, "[SPACE] to toggle - [ENTER] to proceed - [q]uit"); /* set log format from config file if available */ draw_header (win, "Log Format - [c] to add/edit format", " %s", 11, 1, w2, color_panel_header); if ((log_format = get_input_log_format ())) { mvwprintw (win, 12, 2, "%.*s", CONF_MENU_W, log_format); free (log_format); } /* set log format from config file if available */ draw_header (win, "Date Format - [d] to add/edit format", " %s", 14, 1, w2, color_panel_header); if ((date_format = get_input_date_format ())) { mvwprintw (win, 15, 2, "%.*s", CONF_MENU_W, date_format); free (date_format); } /* set log format from config file if available */ draw_header (win, "Time Format - [t] to add/edit format", " %s", 17, 1, w2, color_panel_header); if ((time_format = get_input_time_format ())) { mvwprintw (win, 18, 2, "%.*s", CONF_MENU_W, time_format); free (time_format); } }
/* compile the regular expression and see if it's valid */ static int regexp_init (regex_t * regex, const char *pattern) { int y, x, rc; char buf[REGEX_ERROR]; getmaxyx (stdscr, y, x); rc = regcomp (regex, pattern, REG_EXTENDED | (find_t.icase ? REG_ICASE : 0)); /* something went wrong */ if (rc != 0) { regerror (rc, regex, buf, sizeof (buf)); draw_header (stdscr, buf, "%s", y - 1, 0, x, WHITE_RED, 0); refresh (); return 1; } return 0; }
/* render module's total */ static void render_total_label (WINDOW * win, GDashModule * data, int y, int color) { char *s; int win_h, win_w, total, ht_size; total = data->holder_size; ht_size = data->ht_size; s = xmalloc (snprintf (NULL, 0, "Total: %d/%d", total, ht_size) + 1); getmaxyx (win, win_h, win_w); (void) win_h; sprintf (s, "Total: %d/%d", total, ht_size); draw_header (win, s, "%s", y, win_w - strlen (s) - 2, win_w, color, 0); free (s); }
/* render processing spinner */ static void ui_spinner (void *ptr_data) { GSpinner *sp = (GSpinner *) ptr_data; static char const spin_chars[] = "/-\\|"; char buf[SPIN_LBL]; long long tdiff = 0, psec = 0; int i = 0; time_t begin; time (&begin); while (1) { pthread_mutex_lock (&sp->mutex); if (sp->state == SPN_END) break; tdiff = (long long) (time (NULL) - begin); psec = tdiff >= 1 ? *(sp->process) / tdiff : 0; snprintf (buf, sizeof buf, SPIN_FMT, sp->label, *(sp->process), psec); /* CURSES */ if (sp->curses) { /* label + metrics */ draw_header (sp->win, buf, " %s", sp->y, sp->x, sp->w, sp->color); /* caret */ wattron (sp->win, COLOR_PAIR (sp->color)); mvwaddch (sp->win, sp->y, sp->spin_x, spin_chars[i++ & 3]); wattroff (sp->win, COLOR_PAIR (sp->color)); wrefresh (sp->win); } /* STDOUT */ else { fprintf (stderr, "%s\r", buf); } pthread_mutex_unlock (&sp->mutex); usleep (100000); } sp = NULL; free (sp); }
/* render dashboard percent */ static void render_percent (GDashModule * data, GDashRender render, int *x) { WINDOW *win = render.win; GModule module = data->module; const GDashStyle *style = module_style; char *percent; int y = render.y, w = render.w, idx = render.idx, sel = render.sel; int len = data->perc_len + 3; if (data->module == HOSTS && data->data[idx].is_subitem) goto out; if (style[module].color_percent == -1) return; /* selected state */ if (sel) { percent = float_to_str (data->data[idx].metrics->percent); draw_header (win, percent, "%*s%%", y, *x, w, HIGHLIGHT, len); free (percent); } /* regular state */ else { wattron (win, A_BOLD | COLOR_PAIR (style[module].color_percent)); if (data->max_hits == data->data[idx].metrics->hits) wattron (win, A_BOLD | COLOR_PAIR (COL_YELLOW)); if (style[module].color_percent == COL_BLACK) wattron (win, A_BOLD | COLOR_PAIR (style[module].color_percent)); mvwprintw (win, y, *x, "%*.2f%%", len, data->data[idx].metrics->percent); if (style[module].color_percent == COL_BLACK) wattroff (win, A_BOLD | COLOR_PAIR (style[module].color_percent)); if (data->max_hits == data->data[idx].metrics->hits) wattroff (win, A_BOLD | COLOR_PAIR (COL_YELLOW)); wattroff (win, A_BOLD | COLOR_PAIR (style[module].color_percent)); } out: *x += len + 1 + DASH_SPACE; }
/* render dashboard bars (graph) */ static void render_bars (GDashModule * data, GDashRender render, int *x) { WINDOW *win = render.win; GModule module = data->module; const GDashStyle *style = module_style; char *bar; int y = render.y, w = render.w, idx = render.idx, sel = render.sel; if (style[module].color_bars == -1) return; bar = get_bars (data->data[idx].metrics->hits, data->max_hits, *x); if (sel) draw_header (win, bar, "%s", y, *x, w, HIGHLIGHT, 0); else mvwprintw (win, y, *x, "%s", bar); free (bar); }
static void draw_page_image (GtkPrintOperation * op, GtkPrintContext * cnt, gint page, gpointer data) { cairo_t *cr; GdkPixbuf *pb, *spb; guint iw, ih; gdouble pw, ph; gdouble factor; cr = gtk_print_context_get_cairo_context (cnt); pw = gtk_print_context_get_width (cnt); ph = gtk_print_context_get_height (cnt); if (options.print_data.headers) ph -= HEADER_HEIGHT + HEADER_GAP; /* create header */ if (options.print_data.headers) draw_header (cnt, 1, 1); /* scale image to page size */ pb = gdk_pixbuf_new_from_file (options.common_data.uri, NULL); iw = gdk_pixbuf_get_width (pb); ih = gdk_pixbuf_get_height (pb); if (pw < iw || ph < ih) { factor = MIN (pw / iw, ph / ih); factor = (factor > 1.0) ? 1.0 : factor; spb = gdk_pixbuf_scale_simple (pb, iw * factor, ih * factor, GDK_INTERP_HYPER); } else spb = g_object_ref (pb); g_object_unref (pb); /* add image to surface */ gdk_cairo_set_source_pixbuf (cr, spb, 0.0, HEADER_HEIGHT + HEADER_GAP); cairo_paint (cr); g_object_unref (spb); }
void display_general (WINDOW * win, char *ifile, GLog * logger) { GColors *(*colorlbl) (void) = color_overall_lbls; GColors *(*colorpth) (void) = color_overall_path; GColors *(*colorval) (void) = color_overall_vals; int col = getmaxx (stdscr); size_t n, i; /* *INDENT-OFF* */ Field fields[] = { {T_REQUESTS , get_str_processed_reqs (logger) , colorlbl , colorval , 0}, {T_UNIQUE_VIS , get_str_visitors () , colorlbl , colorval , 0}, {T_UNIQUE_FIL , get_str_reqs () , colorlbl , colorval , 0}, {T_REFERRER , get_str_ref_reqs () , colorlbl , colorval , 0}, {T_VALID , get_str_valid_reqs (logger) , colorlbl , colorval , 0}, {T_GEN_TIME , get_str_proctime () , colorlbl , colorval , 0}, {T_STATIC_FIL , get_str_static_reqs () , colorlbl , colorval , 0}, {T_LOG , get_str_filesize (logger, ifile) , colorlbl , colorval , 0}, {T_FAILED , get_str_failed_reqs (logger) , colorlbl , colorval , 0}, {T_EXCLUDE_IP , get_str_excluded_ips (logger) , colorlbl , colorval , 0}, {T_UNIQUE404 , get_str_notfound_reqs () , colorlbl , colorval , 0}, {T_BW , get_str_bandwidth (logger) , colorlbl , colorval , 0}, {T_LOG_PATH , get_str_logfile (logger, ifile) , colorlbl , colorpth , 1} }; /* *INDENT-ON* */ werase (win); draw_header (win, T_DASH " - " T_HEAD, " %s", 0, 0, col, color_panel_header); n = ARRAY_SIZE (fields); render_overall_statistics (win, fields, n); for (i = 0; i < n; i++) { free (fields[i].value); } }
static void render_header (WINDOW * win, GDashModule * data, GModule cur_module, int *y) { char ind; char *hd; int k, w, h, color; getmaxyx (win, h, w); (void) h; k = data->module + 1; ind = cur_module == data->module ? '>' : ' '; color = cur_module == data->module && conf.hl_header ? YELLOW_BLACK : HIGHLIGHT; hd = xmalloc (snprintf (NULL, 0, "%c %d - %s", ind, k, data->head) + 1); sprintf (hd, "%c %d - %s", ind, k, data->head); draw_header (win, hd, " %s", (*y), 0, w, color, 0); free (hd); render_total_label (win, data, (*y), color); data->pos_y = (*y); (*y)++; }
/* render config log date/format dialog */ int verify_format (GLog * logger, GSpinner * spinner) { GMenu *menu; WINDOW *win; char *cstm_log, *cstm_date; int c, quit = 1; int invalid = 1; int y, x, h = CONF_WIN_H, w = CONF_WIN_W; int w2 = w - 2; size_t i, n, sel; /* conf dialog menu options */ const char *choices[] = { "Common Log Format (CLF)", "Common Log Format (CLF) with Virtual Host", "NCSA Combined Log Format", "NCSA Combined Log Format with Virtual Host", "W3C", "CloudFront (Download Distribution)" }; n = ARRAY_SIZE (choices); getmaxyx (stdscr, y, x); win = newwin (h, w, (y - h) / 2, (x - w) / 2); keypad (win, TRUE); wborder (win, '|', '|', '-', '-', '+', '+', '+', '+'); /* create a new instance of GMenu and make it selectable */ menu = new_gmenu (win, CONF_MENU_H, CONF_MENU_W, CONF_MENU_Y, CONF_MENU_X); menu->size = n; menu->selectable = 1; /* add items to GMenu */ menu->items = (GItem *) xcalloc (n, sizeof (GItem)); for (i = 0; i < n; ++i) { menu->items[i].name = alloc_string (choices[i]); sel = get_selected_format_idx (); menu->items[i].checked = sel == i ? 1 : 0; } post_gmenu (menu); draw_header (win, "Log Format Configuration", " %s", 1, 1, w2, 1, 0); mvwprintw (win, 2, 2, "[SPACE] to toggle - [ENTER] to proceed"); /* set log format from goaccessrc if available */ draw_header (win, "Log Format - [c] to add/edit format", " %s", 11, 1, w2, 1, 0); if (conf.log_format) { log_format = escape_str (conf.log_format); mvwprintw (win, 12, 2, "%.*s", CONF_MENU_W, log_format); if (conf.log_format) free (conf.log_format); } /* set date format from goaccessrc if available */ draw_header (win, "Date Format - [d] to add/edit format", " %s", 14, 1, w2, 1, 0); if (conf.date_format) { date_format = escape_str (conf.date_format); mvwprintw (win, 15, 2, "%.*s", CONF_MENU_W, date_format); if (conf.date_format) free (conf.date_format); } wrefresh (win); while (quit) { c = wgetch (stdscr); switch (c) { case KEY_DOWN: gmenu_driver (menu, REQ_DOWN); draw_header (win, "", "%s", 3, 2, CONF_MENU_W, 0, 0); break; case KEY_UP: gmenu_driver (menu, REQ_UP); draw_header (win, "", "%s", 3, 2, CONF_MENU_W, 0, 0); break; case 32: /* space */ gmenu_driver (menu, REQ_SEL); if (date_format) free (date_format); if (log_format) free (log_format); for (i = 0; i < n; ++i) { if (menu->items[i].checked != 1) continue; date_format = get_selected_date_str (i); log_format = get_selected_format_str (i); draw_header (win, date_format, " %s", 15, 1, CONF_MENU_W, 0, 0); draw_header (win, log_format, " %s", 12, 1, CONF_MENU_W, 0, 0); break; } break; case 99: /* c */ /* clear top status bar */ draw_header (win, "", "%s", 3, 2, CONF_MENU_W, 0, 0); wmove (win, 12, 2); /* get input string */ cstm_log = input_string (win, 12, 2, 70, log_format, 0, 0); if (cstm_log != NULL && *cstm_log != '\0') { if (log_format) free (log_format); log_format = alloc_string (cstm_log); free (cstm_log); } /* did not set an input string */ else { if (cstm_log) free (cstm_log); if (log_format) { free (log_format); log_format = NULL; } } break; case 100: /* d */ /* clear top status bar */ draw_header (win, "", "%s", 3, 2, CONF_MENU_W, 0, 0); wmove (win, 15, 0); /* get input string */ cstm_date = input_string (win, 15, 2, 14, date_format, 0, 0); if (cstm_date != NULL && *cstm_date != '\0') { if (date_format) free (date_format); date_format = alloc_string (cstm_date); free (cstm_date); } /* did not set an input string */ else { if (cstm_date) free (cstm_date); if (date_format) { free (date_format); date_format = NULL; } } break; case 274: /* F10 */ case 0x0a: case 0x0d: case KEY_ENTER: /* display status bar error messages */ if (date_format == NULL) draw_header (win, "Select a date format.", "%s", 3, 2, CONF_MENU_W, WHITE_RED, 0); if (log_format == NULL) draw_header (win, "Select a log format.", "%s", 3, 2, CONF_MENU_W, WHITE_RED, 0); if (date_format && log_format) { conf.date_format = unescape_str (date_format); conf.log_format = unescape_str (log_format); /* test log against selected settings */ if (test_format (logger)) { invalid = 1; draw_header (win, "No valid hits.", "%s", 3, 2, CONF_MENU_W, WHITE_RED, 0); free (conf.log_format); free (conf.date_format); } /* valid data, reset logger & start parsing */ else { reset_struct (logger); /* start spinner thread */ spinner->win = win; spinner->y = 3; spinner->x = 2; spinner->spin_x = CONF_MENU_W; spinner->w = CONF_MENU_W; spinner->color = BLACK_CYAN; ui_spinner_create (spinner); invalid = 0; quit = 0; } } break; case KEY_RESIZE: case 'q': quit = 0; break; } pthread_mutex_lock (&spinner->mutex); wrefresh (win); pthread_mutex_unlock (&spinner->mutex); } /* clean stuff up */ for (i = 0; i < n; ++i) free (menu->items[i].name); free (menu->items); free (menu); return invalid ? 1 : 0; }
/* render a list of agents if available */ void load_agent_list (WINDOW * main_win, char *addr) { char buf[256]; char *ptr_value; GAgents *agents = NULL; GMenu *menu; int c, quit = 1, delims = 0; int i, n = 0, alloc = 0; int y, x, list_h, list_w, menu_w, menu_h; void *value_ptr = NULL; WINDOW *win; if (!conf.list_agents) return; getmaxyx (stdscr, y, x); list_h = y / 2; /* list window - height */ list_w = x - 4; /* list window - width */ menu_h = list_h - AGENTS_MENU_Y - 1; /* menu window - height */ menu_w = list_w - AGENTS_MENU_X - AGENTS_MENU_X; /* menu window - width */ #ifdef HAVE_LIBTOKYOCABINET value_ptr = tc_db_get_str (ht_hosts_agents, addr); #else value_ptr = g_hash_table_lookup (ht_hosts_agents, addr); #endif if (value_ptr != NULL) { ptr_value = (char *) value_ptr; delims = count_matches (ptr_value, '|'); n = ((strlen (ptr_value) + menu_w - 1) / menu_w) + delims + 1; agents = new_gagents (n); alloc = split_agent_str (ptr_value, agents, menu_w); #ifdef HAVE_LIBTOKYOCABINET free (value_ptr); #endif } win = newwin (list_h, list_w, (y - list_h) / 2, (x - list_w) / 2); keypad (win, TRUE); wborder (win, '|', '|', '-', '-', '+', '+', '+', '+'); /* create a new instance of GMenu and make it selectable */ menu = new_gmenu (win, menu_h, menu_w, AGENTS_MENU_Y, AGENTS_MENU_X); /* add items to GMenu */ menu->items = (GItem *) xcalloc (alloc, sizeof (GItem)); for (i = 0; i < alloc; ++i) { menu->items[i].name = alloc_string (agents[i].agents); menu->items[i].checked = 0; menu->size++; } post_gmenu (menu); snprintf (buf, sizeof buf, "User Agents for %s", addr); draw_header (win, buf, " %s", 1, 1, list_w - 2, 1, 0); mvwprintw (win, 2, 2, "[UP/DOWN] to scroll - [q] to close window"); wrefresh (win); while (quit) { c = wgetch (stdscr); switch (c) { case KEY_DOWN: gmenu_driver (menu, REQ_DOWN); draw_header (win, "", "%s", 3, 2, CONF_MENU_W, 0, 0); break; case KEY_UP: gmenu_driver (menu, REQ_UP); draw_header (win, "", "%s", 3, 2, CONF_MENU_W, 0, 0); break; case KEY_RESIZE: case 'q': quit = 0; break; } wrefresh (win); } /* clean stuff up */ for (i = 0; i < alloc; ++i) free (menu->items[i].name); free (menu->items); free (menu); for (i = 0; i < alloc; ++i) free (agents[i].agents); if (agents) free (agents); touchwin (main_win); close_win (win); wrefresh (main_win); }
/* implement basic frame work to build a field input */ char * input_string (WINDOW * win, int pos_y, int pos_x, size_t max_width, const char *str, int enable_case, int *toggle_case) { char *s = xmalloc (max_width + 1), *tmp; size_t pos = 0, x = 0, quit = 1, c; /* window dimensions */ size_t size_x = 0, size_y = 0, i; getmaxyx (win, size_y, size_x); size_x -= 4; /* are we setting a default string */ if (str) { size_t len = MIN (max_width, strlen (str)); memcpy (s, str, len); s[len] = '\0'; x = pos = 0; /* is the default str length greater than input field? */ if (strlen (s) > size_x) { tmp = xstrdup (&s[0]); tmp[size_x] = '\0'; mvwprintw (win, pos_y, pos_x, "%s", tmp); free (tmp); } else mvwprintw (win, pos_y, pos_x, "%s", s); } else s[0] = '\0'; if (enable_case) draw_header (win, "[x] case sensitive", " %s", size_y - 2, 1, size_x - 2, 2, 0); wmove (win, pos_y, pos_x + x); wrefresh (win); curs_set (1); while (quit) { c = wgetch (stdscr); switch (c) { case 1: /* ^a */ case 262: /* HOME */ pos = x = 0; break; case 5: case 360: /* END of line */ if (strlen (s) > size_x) { x = size_x; pos = strlen (s) - size_x; } else { pos = 0; x = strlen (s); } break; case 7: /* ^g */ case 27: /* ESC */ pos = x = 0; if (str && *str == '\0') s[0] = '\0'; quit = 0; break; case 9: /* TAB */ if (!enable_case) break; *toggle_case = *toggle_case == 0 ? 1 : 0; if (*toggle_case) draw_header (win, "[ ] case sensitive", " %s", size_y - 2, 1, size_x - 2, 2, 0); else if (!*toggle_case) draw_header (win, "[x] case sensitive", " %s", size_y - 2, 1, size_x - 2, 2, 0); break; case 21: /* ^u */ s[0] = '\0'; pos = x = 0; break; case 8: /* xterm-256color */ case 127: case KEY_BACKSPACE: if (pos + x > 0) { memmove (&s[(pos + x) - 1], &s[pos + x], (max_width - (pos + x)) + 1); if (pos <= 0) x--; else pos--; } break; case KEY_LEFT: if (x > 0) x--; else if (pos > 0) pos--; break; case KEY_RIGHT: if ((x + pos) < strlen (s)) { if (x < size_x) x++; else pos++; } break; case 0x0a: case 0x0d: case KEY_ENTER: quit = 0; break; default: if (strlen (s) == max_width) break; if (!isprint (c)) break; if (strlen (s) == pos) { s[pos + x] = c; s[pos + x + 1] = '\0'; waddch (win, c); } else { memmove (&s[pos + x + 1], &s[pos + x], strlen (&s[pos + x]) + 1); s[pos + x] = c; } if ((x + pos) < max_width) { if (x < size_x) x++; else pos++; } } tmp = xstrdup (&s[pos > 0 ? pos : 0]); tmp[MIN (strlen (tmp), size_x)] = '\0'; for (i = strlen (tmp); i < size_x; i++) mvwprintw (win, pos_y, pos_x + i, "%s", " "); mvwprintw (win, pos_y, pos_x, "%s", tmp); free (tmp); wmove (win, pos_y, pos_x + x); wrefresh (win); } curs_set (0); return s; }
/* render general statistics */ void display_general (WINDOW * win, char *ifile, GLog * logger) { char *bw, *size, *log_file; char *failed, *not_found, *process, *ref, *req; char *static_files, *now, *visitors, *exclude_ip; int x_field = 2, x_value = 0; size_t n, i, j, max_field = 0, max_value = 0, mod_val, y; typedef struct Field_ { const char *field; char *value; /* char due to log, bw, log_file */ int color; } Field; Field fields[] = { {T_REQUESTS, NULL, COL_CYAN}, {T_UNIQUE_VIS, NULL, COL_CYAN}, {T_REFERRER, NULL, COL_CYAN}, {T_LOG, NULL, COL_CYAN}, {T_F_REQUESTS, NULL, COL_CYAN}, {T_UNIQUE_FIL, NULL, COL_CYAN}, {T_UNIQUE404, NULL, COL_CYAN}, {T_BW, NULL, COL_CYAN}, {T_GEN_TIME, NULL, COL_CYAN}, {T_EXCLUDE_IP, NULL, COL_CYAN}, {T_STATIC_FIL, NULL, COL_CYAN}, {T_LOG_PATH, NULL, COL_YELLOW} }; werase (win); draw_header (win, T_HEAD, " %s", 0, 0, getmaxx (stdscr), 1, 0); if (!logger->piping && ifile != NULL) { size = filesize_str (file_size (ifile)); log_file = alloc_string (ifile); } else { size = alloc_string ("N/A"); log_file = alloc_string ("STDIN"); } bw = filesize_str ((float) logger->resp_size); /* *INDENT-OFF* */ failed = int_to_str (logger->invalid); not_found = int_to_str (get_ht_size (ht_not_found_requests)); process = int_to_str (logger->process); ref = int_to_str (get_ht_size (ht_referrers)); req = int_to_str (get_ht_size(ht_requests)); static_files = int_to_str (get_ht_size(ht_requests_static)); now = int_to_str (((long long) end_proc - start_proc)); visitors = int_to_str (get_ht_size(ht_unique_visitors)); exclude_ip = int_to_str (logger->exclude_ip); fields[0].value = process; fields[1].value = visitors; fields[2].value = ref; fields[3].value = size; fields[4].value = failed; fields[5].value = req; fields[6].value = not_found; fields[7].value = bw; fields[8].value = now; fields[9].value = exclude_ip; fields[10].value = static_files; fields[11].value = log_file; n = ARRAY_SIZE (fields); /* *INDENT-ON* */ for (i = 0, y = 2; i < n; i++) { mod_val = i % 4; if (i > 0 && mod_val == 0) { max_field = 0; max_value = 0; x_field = 2; x_value = 2; y++; } x_field += max_field; mvwprintw (win, y, x_field, "%s", fields[i].field); max_field = 0; for (j = 0; j < n; j++) { size_t len = strlen (fields[j].field); if (j % 4 == mod_val && len > max_field) max_field = len; } max_value = 0; for (j = 0; j < n; j++) { size_t len = strlen (fields[j].value); if (j % 4 == mod_val && len > max_value) max_value = len; } x_value = max_field + x_field + 1; max_field += max_value + 2; wattron (win, A_BOLD | COLOR_PAIR (fields[i].color)); mvwprintw (win, y, x_value, "%s", fields[i].value); wattroff (win, A_BOLD | COLOR_PAIR (fields[i].color)); } for (i = 0; i < n; i++) { free (fields[i].value); } }
/* render sort dialog */ void load_sort_win (WINDOW * main_win, GModule module, GSort * sort) { GMenu *menu; int c, quit = 1; int i = 0, k, n = 0; int opts[SORT_MAX_OPTS]; int y, x, h = SORT_WIN_H, w = SORT_WIN_W; int w2 = w - 2; WINDOW *win; getmaxyx (stdscr, y, x); /* determine amount of sort choices */ for (i = 0, k = 0; NULL != sort_choices[module][i]; i++) { const char *name = sort_choices[module][i]; if (strcmp ("Time Served", name) == 0 && !conf.serve_usecs) continue; else if (strcmp ("Bandwidth", name) == 0 && !conf.bandwidth) continue; else if (strcmp ("Protocol", name) == 0 && !conf.append_protocol) continue; else if (strcmp ("Method", name) == 0 && !conf.append_method) continue; opts[k++] = i; n++; } win = newwin (h, w, (y - h) / 2, (x - w) / 2); keypad (win, TRUE); wborder (win, '|', '|', '-', '-', '+', '+', '+', '+'); /* create a new instance of GMenu and make it selectable */ menu = new_gmenu (win, SORT_MENU_H, SORT_MENU_W, SORT_MENU_Y, SORT_MENU_X); menu->size = n; menu->selectable = 1; /* add items to GMenu */ menu->items = (GItem *) xcalloc (n, sizeof (GItem)); /* set checked option and set index */ for (i = 0; i < n; ++i) { menu->items[i].name = alloc_string (sort_choices[module][opts[i]]); if (sort->field == SORT_BY_HITS && strcmp ("Hits", menu->items[i].name) == 0) { menu->items[i].checked = 1; menu->idx = i; } else if (sort->field == SORT_BY_DATA && strcmp ("Data", menu->items[i].name) == 0) { menu->items[i].checked = 1; menu->idx = i; } else if (sort->field == SORT_BY_BW && strcmp ("Bandwidth", menu->items[i].name) == 0) { menu->items[i].checked = 1; menu->idx = i; } else if (sort->field == SORT_BY_USEC && strcmp ("Time Served", menu->items[i].name) == 0) { menu->items[i].checked = 1; menu->idx = i; } else if (sort->field == SORT_BY_PROT && strcmp ("Protocol", menu->items[i].name) == 0) { menu->items[i].checked = 1; menu->idx = i; } else if (sort->field == SORT_BY_MTHD && strcmp ("Method", menu->items[i].name) == 0) { menu->items[i].checked = 1; menu->idx = i; } } post_gmenu (menu); draw_header (win, "Sort active module by", " %s", 1, 1, w2, 1, 0); mvwprintw (win, 2, 2, "[ENTER] to select field - [TAB] sort"); if (sort->sort == SORT_ASC) draw_header (win, "[x] ASC [ ] DESC", " %s", SORT_WIN_H - 2, 1, SORT_WIN_W - 2, 2, 0); else draw_header (win, "[ ] ASC [x] DESC", " %s", SORT_WIN_H - 2, 1, SORT_WIN_W - 2, 2, 0); wrefresh (win); while (quit) { c = wgetch (stdscr); switch (c) { case KEY_DOWN: gmenu_driver (menu, REQ_DOWN); draw_header (win, "", "%s", 3, 2, SORT_MENU_W, 0, 0); break; case KEY_UP: gmenu_driver (menu, REQ_UP); draw_header (win, "", "%s", 3, 2, SORT_MENU_W, 0, 0); break; case 9: /* TAB */ /* ascending */ if (sort->sort == SORT_ASC) { sort->sort = SORT_DESC; draw_header (win, "[ ] ASC [x] DESC", " %s", SORT_WIN_H - 2, 1, SORT_WIN_W - 2, 2, 0); } /* descending */ else { sort->sort = SORT_ASC; draw_header (win, "[x] ASC [ ] DESC", " %s", SORT_WIN_H - 2, 1, SORT_WIN_W - 2, 2, 0); } break; case 32: case 0x0a: case 0x0d: case KEY_ENTER: gmenu_driver (menu, REQ_SEL); for (i = 0; i < n; ++i) { if (menu->items[i].checked != 1) continue; if (strcmp ("Hits", menu->items[i].name) == 0) sort->field = SORT_BY_HITS; else if (strcmp ("Data", menu->items[i].name) == 0) sort->field = SORT_BY_DATA; else if (strcmp ("Bandwidth", menu->items[i].name) == 0) sort->field = SORT_BY_BW; else if (strcmp ("Time Served", menu->items[i].name) == 0) sort->field = SORT_BY_USEC; else if (strcmp ("Protocol", menu->items[i].name) == 0) sort->field = SORT_BY_PROT; else if (strcmp ("Method", menu->items[i].name) == 0) sort->field = SORT_BY_MTHD; quit = 0; break; } break; case KEY_RESIZE: case 'q': quit = 0; break; } wrefresh (win); } /* clean stuff up */ for (i = 0; i < n; ++i) free (menu->items[i].name); free (menu->items); free (menu); touchwin (main_win); close_win (win); wrefresh (main_win); }