예제 #1
0
파일: column.c 프로젝트: asriadi/wireshark
/* Returns the longer string of the column title or the hard-coded width of
 * its contents for building the packet list layout. */
const gchar *
get_column_width_string(const gint format, const gint col)
{
    if(strlen(get_column_longest_string(format)) >
       strlen(get_column_title(col)))
        return get_column_longest_string(format);
    else
        return get_column_title(col);
}
예제 #2
0
파일: column.c 프로젝트: flaub/HotFuzz
void
build_column_format_array(column_info *cinfo, const gint num_cols, const gboolean reset_fences)
{
  int i;

  /* Build the column format array */
  col_setup(cinfo, num_cols);

  for (i = 0; i < cinfo->num_cols; i++) {
    cinfo->col_fmt[i] = get_column_format(i);
    cinfo->col_title[i] = g_strdup(get_column_title(i));

    if (cinfo->col_fmt[i] == COL_CUSTOM) {
      cinfo->col_custom_field[i] = g_strdup(get_column_custom_field(i));
      if(!dfilter_compile(cinfo->col_custom_field[i], &cinfo->col_custom_dfilter[i])) {
        /* XXX: Should we issue a warning? */
        g_free(cinfo->col_custom_field[i]);
        cinfo->col_custom_field[i] = NULL;
        cinfo->col_custom_dfilter[i] = NULL;
      }
    } else {
      cinfo->col_custom_field[i] = NULL;
      cinfo->col_custom_dfilter[i] = NULL;
    }

    cinfo->fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) * NUM_COL_FMTS);
    get_column_format_matches(cinfo->fmt_matx[i], cinfo->col_fmt[i]);
    cinfo->col_data[i] = NULL;

    if (cinfo->col_fmt[i] == COL_INFO)
      cinfo->col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
    else
      cinfo->col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);

    if(reset_fences)
      cinfo->col_fence[i] = 0;

    cinfo->col_expr.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
    cinfo->col_expr.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
  }

  cinfo->col_expr.col_expr[i] = NULL;
  cinfo->col_expr.col_expr_val[i] = NULL;

  for (i = 0; i < cinfo->num_cols; i++) {
    int j;

    for (j = 0; j < NUM_COL_FMTS; j++) {
      if (!cinfo->fmt_matx[i][j])
          continue;

      if (cinfo->col_first[j] == -1)
        cinfo->col_first[j] = i;

      cinfo->col_last[j] = i;
    }
  }
}
예제 #3
0
QVariant PacketListModel::headerData(int section, Qt::Orientation orientation,
                               int role) const
{
    if (!cap_file_) return QVariant();

    if (orientation == Qt::Horizontal && section < prefs.num_cols) {
        switch (role) {
        case Qt::DisplayRole:
            return get_column_title(section);
        default:
            break;
        }
    }

    return QVariant();
}
예제 #4
0
PacketDialog::PacketDialog(QWidget &parent, CaptureFile &cf, frame_data *fdata) :
    WiresharkDialog(parent, cf),
    ui(new Ui::PacketDialog),
    packet_data_(NULL)
{
    ui->setupUi(this);
    ui->hintLabel->setSmallText();

    // XXX Use recent settings instead
    resize(parent.width() * 4 / 5, parent.height() * 4 / 5);

    setWindowSubtitle(tr("Packet %1").arg(fdata->num));

    phdr_ = cap_file_.capFile()->phdr;
    packet_data_ = (guint8 *) g_memdup(ws_buffer_start_ptr(&(cap_file_.capFile()->buf)), fdata->cap_len);

    if (!cf_read_record(cap_file_.capFile(), fdata)) reject();
    /* proto tree, visible. We need a proto tree if there's custom columns */
    epan_dissect_init(&edt_, cap_file_.capFile()->epan, TRUE, TRUE);
    col_custom_prime_edt(&edt_, &(cap_file_.capFile()->cinfo));

    epan_dissect_run(&edt_, cap_file_.capFile()->cd_t, &phdr_,
                     frame_tvbuff_new(fdata, packet_data_),
                     fdata, &(cap_file_.capFile()->cinfo));
    epan_dissect_fill_in_columns(&edt_, TRUE, TRUE);

    proto_tree_ = new ProtoTree(ui->packetSplitter);
    proto_tree_->fillProtocolTree(edt_.tree);
    proto_tree_->expandAll();

    byte_view_tab_ = new ByteViewTab(ui->packetSplitter);
    byte_view_tab_->setCaptureFile(cap_file_.capFile());
    byte_view_tab_->clear();

    GSList *src_le;
    for (src_le = edt_.pi.data_src; src_le != NULL; src_le = src_le->next) {
        struct data_source *source;
        char* source_name;
        source = (struct data_source *)src_le->data;
        source_name = get_data_source_name(source);
        byte_view_tab_->addTab(source_name, get_data_source_tvb(source), edt_.tree, proto_tree_,
                               cap_file_.capFile()->current_frame->flags.encoding);
        wmem_free(NULL, source_name);
    }
    byte_view_tab_->setCurrentIndex(0);

    ui->packetSplitter->setStretchFactor(0, 5);
    ui->packetSplitter->setStretchFactor(1, 1);

    QStringList col_parts;
    for (int i = 0; i < cap_file_.capFile()->cinfo.num_cols; ++i) {
        // ElidedLabel doesn't support rich text / HTML
        col_parts << QString("%1: %2")
                     .arg(get_column_title(i))
                     .arg(cap_file_.capFile()->cinfo.col_data[i]);
    }
    col_info_ = col_parts.join(" " UTF8_MIDDLE_DOT " ");
    setHintText();

    connect(this, SIGNAL(monospaceFontChanged(QFont)),
            proto_tree_, SLOT(setMonospaceFont(QFont)));
    connect(this, SIGNAL(monospaceFontChanged(QFont)),
            byte_view_tab_, SLOT(setMonospaceFont(QFont)));

    connect(proto_tree_, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
            byte_view_tab_, SLOT(protoTreeItemChanged(QTreeWidgetItem*)));
    connect(byte_view_tab_, SIGNAL(byteFieldHovered(QString&)),
            this, SLOT(setHintText(QString&)));
}
예제 #5
0
int
main(int argc, char *argv[])
{
  char                *init_progfile_dir_error;
  int                  opt, i;
  extern char         *optarg;
  gboolean             arg_error = FALSE;

#ifdef _WIN32
  WSADATA		wsaData;
#endif	/* _WIN32 */

  char                *gpf_path, *pf_path;
  char                *gdp_path, *dp_path;
  int                  gpf_open_errno, gpf_read_errno;
  int                  pf_open_errno, pf_read_errno;
  int                  gdp_open_errno, gdp_read_errno;
  int                  dp_open_errno, dp_read_errno;
  int                  err;
  gchar               *pipe_name = NULL;
  gchar               *rfilters[64];
  e_prefs             *prefs;
  char                 badopt;
  GLogLevelFlags       log_flags;
  GPtrArray           *disp_fields = g_ptr_array_new();
  guint                fc;
  gboolean             skip_pcap_header = FALSE;

  #define OPTSTRING_INIT "d:F:hlnN:o:r:R:sS:t:v"

  static const char    optstring[] = OPTSTRING_INIT;

  /*
   * Get credential information for later use.
   */
  get_credential_info();

  /*
   * Clear the filters arrays
   */
  memset(rfilters, 0, sizeof(rfilters));
  memset(rfcodes, 0, sizeof(rfcodes));
  n_rfilters = 0;
  n_rfcodes = 0;

  /*
   * Initialize our string format
   */
  string_fmts = g_ptr_array_new();

  /*
   * Attempt to get the pathname of the executable file.
   */
  init_progfile_dir_error = init_progfile_dir(argv[0], main);
  if (init_progfile_dir_error != NULL) {
    fprintf(stderr, "rawshark: Can't get pathname of rawshark program: %s.\n",
            init_progfile_dir_error);
  }

  /*
   * Get credential information for later use.
   */
  get_credential_info();

  /* nothing more than the standard GLib handler, but without a warning */
  log_flags =
		    G_LOG_LEVEL_WARNING |
		    G_LOG_LEVEL_MESSAGE |
		    G_LOG_LEVEL_INFO |
		    G_LOG_LEVEL_DEBUG;

  g_log_set_handler(NULL,
		    log_flags,
		    log_func_ignore, NULL /* user_data */);
  g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
		    log_flags,
		    log_func_ignore, NULL /* user_data */);

  timestamp_set_type(TS_RELATIVE);
  timestamp_set_precision(TS_PREC_AUTO);

  /* Register all dissectors; we must do this before checking for the
     "-G" flag, as the "-G" flag dumps information registered by the
     dissectors, and we must do it before we read the preferences, in
     case any dissectors register preferences. */
  epan_init(register_all_protocols, register_all_protocol_handoffs, NULL, NULL,
            failure_message, open_failure_message, read_failure_message,
            write_failure_message);

  /* Now register the preferences for any non-dissector modules.
     We must do that before we read the preferences as well. */
  prefs_register_modules();

  /* Set the C-language locale to the native environment. */
  setlocale(LC_ALL, "");

  prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
                     &pf_open_errno, &pf_read_errno, &pf_path);
  if (gpf_path != NULL) {
    if (gpf_open_errno != 0) {
      cmdarg_err("Can't open global preferences file \"%s\": %s.",
              pf_path, strerror(gpf_open_errno));
    }
    if (gpf_read_errno != 0) {
      cmdarg_err("I/O error reading global preferences file \"%s\": %s.",
              pf_path, strerror(gpf_read_errno));
    }
  }
  if (pf_path != NULL) {
    if (pf_open_errno != 0) {
      cmdarg_err("Can't open your preferences file \"%s\": %s.", pf_path,
              strerror(pf_open_errno));
    }
    if (pf_read_errno != 0) {
      cmdarg_err("I/O error reading your preferences file \"%s\": %s.",
              pf_path, strerror(pf_read_errno));
    }
    g_free(pf_path);
    pf_path = NULL;
  }

  /* Set the name resolution code's flags from the preferences. */
  g_resolv_flags = prefs->name_resolve;

  /* Read the disabled protocols file. */
  read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
                            &dp_path, &dp_open_errno, &dp_read_errno);
  if (gdp_path != NULL) {
    if (gdp_open_errno != 0) {
      cmdarg_err("Could not open global disabled protocols file\n\"%s\": %s.",
                 gdp_path, strerror(gdp_open_errno));
    }
    if (gdp_read_errno != 0) {
      cmdarg_err("I/O error reading global disabled protocols file\n\"%s\": %s.",
                 gdp_path, strerror(gdp_read_errno));
    }
    g_free(gdp_path);
  }
  if (dp_path != NULL) {
    if (dp_open_errno != 0) {
      cmdarg_err(
        "Could not open your disabled protocols file\n\"%s\": %s.", dp_path,
        strerror(dp_open_errno));
    }
    if (dp_read_errno != 0) {
      cmdarg_err(
        "I/O error reading your disabled protocols file\n\"%s\": %s.", dp_path,
        strerror(dp_read_errno));
    }
    g_free(dp_path);
  }

#ifdef _WIN32
  /* Load Wpcap, if possible */
  load_wpcap();
#endif

  init_cap_file(&cfile);

  /* Assemble the compile-time version information string */
  comp_info_str = g_string_new("Compiled ");
  get_compiled_version_info(comp_info_str, get_epan_compiled_version_info);

  /* Assemble the run-time version information string */
  runtime_info_str = g_string_new("Running ");
  get_runtime_version_info(runtime_info_str, NULL);

  /* Print format defaults to this. */
  print_format = PR_FMT_TEXT;

  /* Initialize our encapsulation type */
  encap = WTAP_ENCAP_UNKNOWN;

  /* Now get our args */
  /* XXX - We should probably have an option to dump libpcap link types */
  while ((opt = getopt(argc, argv, optstring)) != -1) {
    switch (opt) {
      case 'd':        /* Payload type */
        if (!set_link_type(optarg)) {
          cmdarg_err("Invalid link type or protocol \"%s\"", optarg);
          exit(1);
        }
        break;
      case 'F':        /* Read field to display */
        g_ptr_array_add(disp_fields, g_strdup(optarg));
        break;
      case 'h':        /* Print help and exit */
        print_usage(TRUE);
        exit(0);
        break;
      case 'l':        /* "Line-buffer" standard output */
        /* This isn't line-buffering, strictly speaking, it's just
           flushing the standard output after the information for
           each packet is printed; however, that should be good
           enough for all the purposes to which "-l" is put (and
           is probably actually better for "-V", as it does fewer
           writes).

           See the comment in "process_packet()" for an explanation of
           why we do that, and why we don't just use "setvbuf()" to
           make the standard output line-buffered (short version: in
           Windows, "line-buffered" is the same as "fully-buffered",
           and the output buffer is only flushed when it fills up). */
        line_buffered = TRUE;
        break;
      case 'n':        /* No name resolution */
        g_resolv_flags = RESOLV_NONE;
        break;
      case 'N':        /* Select what types of addresses/port #s to resolve */
        if (g_resolv_flags == RESOLV_ALL)
          g_resolv_flags = RESOLV_NONE;
        badopt = string_to_name_resolve(optarg, &g_resolv_flags);
        if (badopt != '\0') {
          cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
                     badopt);
          exit(1);
        }
        break;
      case 'o':        /* Override preference from command line */
        switch (prefs_set_pref(optarg)) {

        case PREFS_SET_OK:
          break;

        case PREFS_SET_SYNTAX_ERR:
          cmdarg_err("Invalid -o flag \"%s\"", optarg);
          exit(1);
          break;

        case PREFS_SET_NO_SUCH_PREF:
        case PREFS_SET_OBSOLETE:
          cmdarg_err("-o flag \"%s\" specifies unknown preference", optarg);
          exit(1);
          break;
        }
        break;
      case 'r':        /* Read capture file xxx */
        pipe_name = g_strdup(optarg);
        break;
      case 'R':        /* Read file filter */
        if(n_rfilters < (int) sizeof(rfilters) / (int) sizeof(rfilters[0])) {
          rfilters[n_rfilters++] = optarg;
        }
        else {
          cmdarg_err("Too many display filters");
          exit(1);
        }
        break;
      case 's':        /* Skip PCAP header */
        skip_pcap_header = TRUE;
        break;
      case 'S':        /* Print string representations */
        if (!parse_field_string_format(optarg)) {
          cmdarg_err("Invalid field string format");
          exit(1);
        }
        break;
      case 't':        /* Time stamp type */
        if (strcmp(optarg, "r") == 0)
          timestamp_set_type(TS_RELATIVE);
        else if (strcmp(optarg, "a") == 0)
          timestamp_set_type(TS_ABSOLUTE);
        else if (strcmp(optarg, "ad") == 0)
          timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
        else if (strcmp(optarg, "d") == 0)
          timestamp_set_type(TS_DELTA);
        else if (strcmp(optarg, "dd") == 0)
          timestamp_set_type(TS_DELTA_DIS);
        else if (strcmp(optarg, "e") == 0)
          timestamp_set_type(TS_EPOCH);
        else {
          cmdarg_err("Invalid time stamp type \"%s\"",
            optarg);
          cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
          cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
          exit(1);
        }
        break;
      case 'v':        /* Show version and exit */
        printf("Rawshark " VERSION "%s\n"
               "\n"
               "%s"
               "\n"
               "%s"
               "\n"
               "%s",
               wireshark_svnversion, get_copyright_info(), comp_info_str->str,
               runtime_info_str->str);
        exit(0);
        break;

      default:
      case '?':        /* Bad flag - print usage message */
        print_usage(TRUE);
        exit(1);
        break;
    }
  }

  /* Notify all registered modules that have had any of their preferences
     changed either from one of the preferences file or from the command
     line that their preferences have changed.
     Initialize preferences before display filters, otherwise modules
     like MATE won't work. */
  prefs_apply_all();

  /* Initialize our display fields */
  for (fc = 0; fc < disp_fields->len; fc++) {
	protocolinfo_init(g_ptr_array_index(disp_fields, fc));
  }
  g_ptr_array_free(disp_fields, TRUE);
  printf("\n");
  fflush(stdout);

  /* If no capture filter or read filter has been specified, and there are
     still command-line arguments, treat them as the tokens of a capture
     filter (if no "-r" flag was specified) or a read filter (if a "-r"
     flag was specified. */
  if (optind < argc) {
    if (pipe_name != NULL) {
      if (n_rfilters != 0) {
        cmdarg_err("Read filters were specified both with \"-R\" "
            "and with additional command-line arguments");
        exit(1);
      }
      rfilters[n_rfilters] = get_args_as_string(argc, argv, optind);
    }
  }

  /* Make sure we got a dissector handle for our payload. */
  if (encap == WTAP_ENCAP_UNKNOWN) {
    cmdarg_err("No valid payload dissector specified.");
    exit(1);
  }

  if (arg_error) {
    print_usage(FALSE);
    exit(1);
  }


#ifdef _WIN32
  /* Start windows sockets */
  WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
#endif /* _WIN32 */

  /* At this point MATE will have registered its field array so we can
     have a tap filter with one of MATE's late-registered fields as part
     of the filter.  We can now process all the "-z" arguments. */
  start_requested_stats();

  /* disabled protocols as per configuration file */
  if (gdp_path == NULL && dp_path == NULL) {
    set_disabled_protos_list();
  }

  /* Build the column format array */
  col_setup(&cfile.cinfo, prefs->num_cols);
  for (i = 0; i < cfile.cinfo.num_cols; i++) {
    cfile.cinfo.col_fmt[i] = get_column_format(i);
    cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
    cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
      NUM_COL_FMTS);
    get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
    cfile.cinfo.col_data[i] = NULL;
    if (cfile.cinfo.col_fmt[i] == COL_INFO)
      cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
    else
      cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
    cfile.cinfo.col_fence[i] = 0;
    cfile.cinfo.col_expr.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
    cfile.cinfo.col_expr.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
  }

  for (i = 0; i < cfile.cinfo.num_cols; i++) {
      int j;

      for (j = 0; j < NUM_COL_FMTS; j++) {
         if (!cfile.cinfo.fmt_matx[i][j])
             continue;

         if (cfile.cinfo.col_first[j] == -1)
             cfile.cinfo.col_first[j] = i;
         cfile.cinfo.col_last[j] = i;
      }
  }

  if (n_rfilters != 0) {
    for (i = 0; i < n_rfilters; i++) {
      if (!dfilter_compile(rfilters[i], &rfcodes[n_rfcodes])) {
        cmdarg_err("%s", dfilter_error_msg);
        epan_cleanup();
        exit(2);
      }
      n_rfcodes++;
    }
  }

  if (pipe_name) {
    /*
     * We're reading a pipe (or capture file).
     */

    /*
     * Immediately relinquish any special privileges we have; we must not
     * be allowed to read any capture files the user running Rawshark
     * can't open.
     */
    relinquish_special_privs_perm();

    if (raw_cf_open(&cfile, pipe_name) != CF_OK) {
      epan_cleanup();
      exit(2);
    }

    /* Do we need to PCAP header and magic? */
    if (skip_pcap_header) {
      guint bytes_left = sizeof(struct pcap_hdr) + sizeof(guint32);
      gchar buf[sizeof(struct pcap_hdr) + sizeof(guint32)];
      while (bytes_left > 0) {
          guint bytes = read(fd, buf, bytes_left);
          if (bytes <= 0) {
              cmdarg_err("Not enough bytes for pcap header.");
              exit(2);
          }
          bytes_left -= bytes;
      }
    }

    /* Set timestamp precision; there should arguably be a command-line
       option to let the user set this. */
#if 0
    switch(wtap_file_tsprecision(cfile.wth)) {
    case(WTAP_FILE_TSPREC_SEC):
      timestamp_set_precision(TS_PREC_AUTO_SEC);
      break;
    case(WTAP_FILE_TSPREC_DSEC):
      timestamp_set_precision(TS_PREC_AUTO_DSEC);
      break;
    case(WTAP_FILE_TSPREC_CSEC):
      timestamp_set_precision(TS_PREC_AUTO_CSEC);
      break;
    case(WTAP_FILE_TSPREC_MSEC):
      timestamp_set_precision(TS_PREC_AUTO_MSEC);
      break;
    case(WTAP_FILE_TSPREC_USEC):
      timestamp_set_precision(TS_PREC_AUTO_USEC);
      break;
    case(WTAP_FILE_TSPREC_NSEC):
      timestamp_set_precision(TS_PREC_AUTO_NSEC);
      break;
    default:
      g_assert_not_reached();
    }
#else
    timestamp_set_precision(TS_PREC_AUTO_USEC);
#endif

    /* Process the packets in the file */
    err = load_cap_file(&cfile);

    if (err != 0) {
      epan_cleanup();
      exit(2);
    }
  } else {
    /* If you want to capture live packets, use TShark. */
    cmdarg_err("Input file or pipe name not specified.");
    exit(2);
  }

  epan_cleanup();

  return 0;
}
예제 #6
0
PacketDialog::PacketDialog(QWidget &parent, CaptureFile &cf, frame_data *fdata) :
    WiresharkDialog(parent, cf),
    ui(new Ui::PacketDialog),
    phdr_(wtap_pkthdr()),
    packet_data_(NULL)
{
    ui->setupUi(this);
    loadGeometry(parent.width() * 4 / 5, parent.height() * 4 / 5);
    ui->hintLabel->setSmallText();

    setWindowSubtitle(tr("Packet %1").arg(fdata->num));

    if (!cf_read_record(cap_file_.capFile(), fdata)) {
        reject();
        return;
    }

    phdr_ = cap_file_.capFile()->phdr;
    packet_data_ = (guint8 *) g_memdup(ws_buffer_start_ptr(&(cap_file_.capFile()->buf)), fdata->cap_len);

    /* proto tree, visible. We need a proto tree if there's custom columns */
    epan_dissect_init(&edt_, cap_file_.capFile()->epan, TRUE, TRUE);
    col_custom_prime_edt(&edt_, &(cap_file_.capFile()->cinfo));

    epan_dissect_run(&edt_, cap_file_.capFile()->cd_t, &phdr_,
                     frame_tvbuff_new(&cap_file_.capFile()->provider, fdata, packet_data_),
                     fdata, &(cap_file_.capFile()->cinfo));
    epan_dissect_fill_in_columns(&edt_, TRUE, TRUE);

    proto_tree_ = new ProtoTree(ui->packetSplitter);
    proto_tree_->setRootNode(edt_.tree);

    byte_view_tab_ = new ByteViewTab(ui->packetSplitter);
    byte_view_tab_->setCaptureFile(cap_file_.capFile());
    byte_view_tab_->selectedFrameChanged(0);

    ui->packetSplitter->setStretchFactor(1, 0);

    QStringList col_parts;
    for (int i = 0; i < cap_file_.capFile()->cinfo.num_cols; ++i) {
        // ElidedLabel doesn't support rich text / HTML
        col_parts << QString("%1: %2")
                     .arg(get_column_title(i))
                     .arg(cap_file_.capFile()->cinfo.columns[i].col_data);
    }
    col_info_ = col_parts.join(" " UTF8_MIDDLE_DOT " ");

    ui->hintLabel->setText(col_info_);

    connect(wsApp, SIGNAL(zoomMonospaceFont(QFont)),
            proto_tree_, SLOT(setMonospaceFont(QFont)));

    connect(byte_view_tab_, SIGNAL(fieldSelected(FieldInformation *)),
            proto_tree_, SLOT(selectedFieldChanged(FieldInformation *)));
    connect(proto_tree_, SIGNAL(fieldSelected(FieldInformation *)),
            byte_view_tab_, SLOT(selectedFieldChanged(FieldInformation *)));

    connect(byte_view_tab_, SIGNAL(fieldHighlight(FieldInformation *)),
            this, SLOT(setHintText(FieldInformation *)));

}