2007-01-28 10:31:32 +00:00
|
|
|
/*
|
|
|
|
* uat.c
|
|
|
|
*
|
|
|
|
* User Accessible Tables
|
|
|
|
* Mantain an array of user accessible data strucures
|
|
|
|
*
|
2008-08-05 21:03:46 +00:00
|
|
|
* (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
|
2007-01-29 04:47:58 +00:00
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 2001 Gerald Combs
|
2007-10-16 15:43:18 +00:00
|
|
|
*
|
2007-01-29 04:47:58 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2007-10-16 15:43:18 +00:00
|
|
|
*
|
2007-01-29 04:47:58 +00:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2007-10-16 15:43:18 +00:00
|
|
|
*
|
2007-01-29 04:47:58 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2012-06-28 22:56:06 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2007-01-28 10:31:32 +00:00
|
|
|
*/
|
2012-09-20 01:48:30 +00:00
|
|
|
#include "config.h"
|
2007-01-28 10:31:32 +00:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#include <glib.h>
|
2008-09-03 19:14:52 +00:00
|
|
|
|
|
|
|
#include <wsutil/file_util.h>
|
|
|
|
#include <wsutil/str_util.h>
|
2013-07-15 02:48:26 +00:00
|
|
|
#include <wsutil/report_err.h>
|
2008-09-03 19:14:52 +00:00
|
|
|
|
2013-11-17 02:55:14 +00:00
|
|
|
#include <wsutil/filesystem.h>
|
2007-02-03 14:25:02 +00:00
|
|
|
#include <epan/packet.h>
|
2007-04-03 19:08:00 +00:00
|
|
|
#include <epan/range.h>
|
2007-01-28 10:31:32 +00:00
|
|
|
|
|
|
|
#include "uat-int.h"
|
|
|
|
|
|
|
|
static GPtrArray* all_uats = NULL;
|
|
|
|
|
|
|
|
void uat_init(void) {
|
2011-09-21 18:55:03 +00:00
|
|
|
all_uats = g_ptr_array_new();
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
2007-02-03 14:25:02 +00:00
|
|
|
uat_t* uat_new(const char* name,
|
2011-09-21 18:55:03 +00:00
|
|
|
size_t size,
|
|
|
|
const char* filename,
|
|
|
|
gboolean from_profile,
|
2014-01-30 17:43:52 +00:00
|
|
|
void* data_ptr,
|
2011-09-21 18:55:03 +00:00
|
|
|
guint* numitems_ptr,
|
UATs could be put into "categories". The categories were defined only
implicitly by the #define name and string they were defined to; not all
UATs neatly fit into any of the categories, so some of them were put
into categories that weren't obviously correct for them, and one - the
display filter macro UAT - wasn't put into any category at all (which
caused crashes when editing them, as the GUI code that handled UAT
changes from a dialog assumed the category field was non-null).
The category was, in practice, used only to decide, in the
aforementioned GUI code, whether the packet summary pane needed to be
updated or not. It also offered no option of "don't update the packet
summary pane *and* don't redissect anything", which is what would be
appropriate for the display filter macro UAT.
Replace the category with a set of fields indicating what the UAT
affects; we currently offer "dissection", which applies to most UATs
(any UAT in libwireshark presumably affects dissection at a minimum) and
"the set of named fields that exist". Changing any UAT that affects
dissection requires a redissection; changing any UAT that affects the
set of named fields that exist requires a redissection *and* rebuilding
the packet summary pane.
Perhaps we also need "filtering", so that if you change a display filter
macro, we re-filter, in case the display is currently filtered with a
display filter that uses a macro that changed.
svn path=/trunk/; revision=43603
2012-07-08 01:00:46 +00:00
|
|
|
guint flags,
|
2011-09-21 18:55:03 +00:00
|
|
|
const char* help,
|
|
|
|
uat_copy_cb_t copy_cb,
|
|
|
|
uat_update_cb_t update_cb,
|
|
|
|
uat_free_cb_t free_cb,
|
|
|
|
uat_post_update_cb_t post_update_cb,
|
|
|
|
uat_field_t* flds_array) {
|
|
|
|
/* Create new uat */
|
2013-03-18 20:44:36 +00:00
|
|
|
uat_t* uat = (uat_t *)g_malloc(sizeof(uat_t));
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
|
|
|
|
|
|
|
/* Add to global array of uats */
|
|
|
|
if (!all_uats)
|
|
|
|
all_uats = g_ptr_array_new();
|
|
|
|
|
|
|
|
g_ptr_array_add(all_uats,uat);
|
|
|
|
|
|
|
|
/* Check params */
|
|
|
|
g_assert(name && size && filename && data_ptr && numitems_ptr);
|
|
|
|
|
|
|
|
/* Set uat values from inputs */
|
|
|
|
uat->name = g_strdup(name);
|
|
|
|
uat->record_size = size;
|
|
|
|
uat->filename = g_strdup(filename);
|
|
|
|
uat->from_profile = from_profile;
|
2014-01-30 17:43:52 +00:00
|
|
|
/* Callers of uat_new() pass in (void*) for data_ptr, because
|
|
|
|
* that is the "universal" pointer type that can be cast to
|
|
|
|
* anything. However, for our purposes, we want a (void**).
|
|
|
|
* So, we cast (void*) data_ptr to (void**) here. That keeps
|
|
|
|
* gcc -fstrict-aliasing from complaining. */
|
|
|
|
uat->user_ptr = (void**) data_ptr;
|
2011-09-21 18:55:03 +00:00
|
|
|
uat->nrows_p = numitems_ptr;
|
|
|
|
uat->copy_cb = copy_cb;
|
|
|
|
uat->update_cb = update_cb;
|
|
|
|
uat->free_cb = free_cb;
|
|
|
|
uat->post_update_cb = post_update_cb;
|
|
|
|
uat->fields = flds_array;
|
|
|
|
uat->user_data = g_array_new(FALSE,FALSE,(guint)uat->record_size);
|
2013-04-22 02:10:49 +00:00
|
|
|
uat->raw_data = g_array_new(FALSE,FALSE,(guint)uat->record_size);
|
|
|
|
uat->valid_data = g_array_new(FALSE,FALSE,sizeof(gboolean));
|
2011-09-21 18:55:03 +00:00
|
|
|
uat->changed = FALSE;
|
|
|
|
uat->loaded = FALSE;
|
2011-10-09 09:55:14 +00:00
|
|
|
uat->from_global = FALSE;
|
2011-09-21 18:55:03 +00:00
|
|
|
uat->rep = NULL;
|
|
|
|
uat->free_rep = NULL;
|
|
|
|
uat->help = help;
|
UATs could be put into "categories". The categories were defined only
implicitly by the #define name and string they were defined to; not all
UATs neatly fit into any of the categories, so some of them were put
into categories that weren't obviously correct for them, and one - the
display filter macro UAT - wasn't put into any category at all (which
caused crashes when editing them, as the GUI code that handled UAT
changes from a dialog assumed the category field was non-null).
The category was, in practice, used only to decide, in the
aforementioned GUI code, whether the packet summary pane needed to be
updated or not. It also offered no option of "don't update the packet
summary pane *and* don't redissect anything", which is what would be
appropriate for the display filter macro UAT.
Replace the category with a set of fields indicating what the UAT
affects; we currently offer "dissection", which applies to most UATs
(any UAT in libwireshark presumably affects dissection at a minimum) and
"the set of named fields that exist". Changing any UAT that affects
dissection requires a redissection; changing any UAT that affects the
set of named fields that exist requires a redissection *and* rebuilding
the packet summary pane.
Perhaps we also need "filtering", so that if you change a display filter
macro, we re-filter, in case the display is currently filtered with a
display filter that uses a macro that changed.
svn path=/trunk/; revision=43603
2012-07-08 01:00:46 +00:00
|
|
|
uat->flags = flags;
|
2011-09-21 18:55:03 +00:00
|
|
|
|
|
|
|
for (i=0;flds_array[i].title;i++) {
|
2013-03-18 20:44:36 +00:00
|
|
|
fld_data_t* f = (fld_data_t *)g_malloc(sizeof(fld_data_t));
|
2011-09-21 18:55:03 +00:00
|
|
|
|
|
|
|
f->colnum = i+1;
|
|
|
|
f->rep = NULL;
|
|
|
|
f->free_rep = NULL;
|
|
|
|
|
|
|
|
flds_array[i].priv = f;
|
|
|
|
}
|
|
|
|
|
|
|
|
uat->ncols = i;
|
|
|
|
|
2014-01-30 17:43:52 +00:00
|
|
|
*((void**)data_ptr) = NULL;
|
2011-09-21 18:55:03 +00:00
|
|
|
*numitems_ptr = 0;
|
|
|
|
|
|
|
|
return uat;
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
void* uat_add_record(uat_t* uat, const void* data, gboolean valid_rec) {
|
2011-09-21 18:55:03 +00:00
|
|
|
void* rec;
|
2013-04-22 02:10:49 +00:00
|
|
|
gboolean* valid;
|
2007-02-03 14:25:02 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
/* Save a copy of the raw (possibly that may contain invalid field values) data */
|
|
|
|
g_array_append_vals (uat->raw_data, data, 1);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
rec = uat->raw_data->data + (uat->record_size * (uat->raw_data->len-1));
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
if (uat->copy_cb) {
|
|
|
|
uat->copy_cb(rec, data, (unsigned int) uat->record_size);
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
if (valid_rec) {
|
|
|
|
/* Add a "known good" record to the list to be used by the dissector */
|
|
|
|
g_array_append_vals (uat->user_data, data, 1);
|
|
|
|
|
|
|
|
rec = uat->user_data->data + (uat->record_size * (uat->user_data->len-1));
|
|
|
|
|
|
|
|
if (uat->copy_cb) {
|
|
|
|
uat->copy_cb(rec, data, (unsigned int) uat->record_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
UAT_UPDATE(uat);
|
|
|
|
} else {
|
|
|
|
rec = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_array_append_vals (uat->valid_data, &valid_rec, 1);
|
|
|
|
valid = (gboolean*)(uat->valid_data->data + (sizeof(gboolean) * (uat->valid_data->len-1)));
|
|
|
|
*valid = valid_rec;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
return rec;
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
2007-02-04 05:19:02 +00:00
|
|
|
void uat_swap(uat_t* uat, guint a, guint b) {
|
2011-09-21 18:55:03 +00:00
|
|
|
size_t s = uat->record_size;
|
2015-01-10 00:50:09 +00:00
|
|
|
void* tmp;
|
2013-04-22 02:10:49 +00:00
|
|
|
gboolean tmp_bool;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
g_assert( a < uat->raw_data->len && b < uat->raw_data->len );
|
2007-02-04 05:19:02 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
if (a == b) return;
|
2007-02-04 05:19:02 +00:00
|
|
|
|
2015-01-10 00:50:09 +00:00
|
|
|
tmp = g_malloc(s);
|
2011-09-21 18:55:03 +00:00
|
|
|
memcpy(tmp, UAT_INDEX_PTR(uat,a), s);
|
|
|
|
memcpy(UAT_INDEX_PTR(uat,a), UAT_INDEX_PTR(uat,b), s);
|
|
|
|
memcpy(UAT_INDEX_PTR(uat,b), tmp, s);
|
2015-01-10 00:50:09 +00:00
|
|
|
g_free(tmp);
|
2007-02-04 05:19:02 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
tmp_bool = *(gboolean*)(uat->valid_data->data + (sizeof(gboolean) * (a)));
|
|
|
|
*(gboolean*)(uat->valid_data->data + (sizeof(gboolean) * (a))) = *(gboolean*)(uat->valid_data->data + (sizeof(gboolean) * (b)));
|
|
|
|
*(gboolean*)(uat->valid_data->data + (sizeof(gboolean) * (b))) = tmp_bool;
|
|
|
|
|
|
|
|
|
2007-02-04 05:19:02 +00:00
|
|
|
}
|
|
|
|
|
2007-01-28 10:31:32 +00:00
|
|
|
void uat_remove_record_idx(uat_t* uat, guint idx) {
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
g_assert( idx < uat->raw_data->len );
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
if (uat->free_cb) {
|
|
|
|
uat->free_cb(UAT_INDEX_PTR(uat,idx));
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
g_array_remove_index(uat->raw_data, idx);
|
|
|
|
g_array_remove_index(uat->valid_data, idx);
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
2008-02-26 19:03:01 +00:00
|
|
|
/* The returned filename was g_malloc()'d so the caller must free it */
|
2007-01-28 10:31:32 +00:00
|
|
|
gchar* uat_get_actual_filename(uat_t* uat, gboolean for_writing) {
|
2011-10-09 09:55:14 +00:00
|
|
|
gchar *pers_fname = NULL;
|
2008-02-26 19:03:01 +00:00
|
|
|
|
2011-10-09 09:55:14 +00:00
|
|
|
if (! uat->from_global) {
|
2013-04-09 02:48:03 +00:00
|
|
|
pers_fname = get_persconffile_path(uat->filename, uat->from_profile);
|
2011-10-09 09:55:14 +00:00
|
|
|
}
|
2007-02-03 14:25:02 +00:00
|
|
|
|
2011-10-09 09:55:14 +00:00
|
|
|
if ((! for_writing ) && (! file_exists(pers_fname) )) {
|
2011-09-21 18:55:03 +00:00
|
|
|
gchar* data_fname = get_datafile_path(uat->filename);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-10-09 09:55:14 +00:00
|
|
|
if (file_exists(data_fname)) {
|
2011-09-21 18:55:03 +00:00
|
|
|
g_free(pers_fname);
|
|
|
|
return data_fname;
|
|
|
|
}
|
2008-02-26 19:03:01 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
g_free(data_fname);
|
|
|
|
g_free(pers_fname);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
return pers_fname;
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
2008-01-30 22:50:55 +00:00
|
|
|
uat_t* uat_get_table_by_name(const char* name) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
2008-01-30 22:50:55 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for (i=0; i < all_uats->len; i++) {
|
2013-03-18 20:44:36 +00:00
|
|
|
uat_t* u = (uat_t *)g_ptr_array_index(all_uats,i);
|
2011-09-21 18:55:03 +00:00
|
|
|
if ( g_str_equal(u->name,name) ) {
|
|
|
|
return (u);
|
|
|
|
}
|
|
|
|
}
|
2008-01-30 22:50:55 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
return NULL;
|
2008-01-30 22:50:55 +00:00
|
|
|
}
|
|
|
|
|
2007-02-03 14:25:02 +00:00
|
|
|
static void putfld(FILE* fp, void* rec, uat_field_t* f) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint fld_len;
|
|
|
|
const char* fld_ptr;
|
|
|
|
|
|
|
|
f->cb.tostr(rec,&fld_ptr,&fld_len,f->cbdata.tostr,f->fld_data);
|
|
|
|
|
|
|
|
switch(f->mode){
|
2013-12-10 15:33:07 +00:00
|
|
|
case PT_TXTMOD_NONE:
|
2011-09-21 18:55:03 +00:00
|
|
|
case PT_TXTMOD_ENUM:
|
|
|
|
case PT_TXTMOD_FILENAME:
|
|
|
|
case PT_TXTMOD_DIRECTORYNAME:
|
|
|
|
case PT_TXTMOD_STRING: {
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
putc('"',fp);
|
|
|
|
|
|
|
|
for(i=0;i<fld_len;i++) {
|
|
|
|
char c = fld_ptr[i];
|
|
|
|
|
2014-05-13 12:44:47 +00:00
|
|
|
if (c == '"' || c == '\\' || ! g_ascii_isprint((guchar)c) ) {
|
2011-09-21 18:55:03 +00:00
|
|
|
fprintf(fp,"\\x%.2x",c);
|
|
|
|
} else {
|
|
|
|
putc(c,fp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
putc('"',fp);
|
2015-01-10 00:50:09 +00:00
|
|
|
break;
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
|
|
|
case PT_TXTMOD_HEXBYTES: {
|
|
|
|
guint i;
|
|
|
|
|
|
|
|
for(i=0;i<fld_len;i++) {
|
2013-12-21 17:34:41 +00:00
|
|
|
fprintf(fp,"%.2x",((const guint8*)fld_ptr)[i]);
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
|
|
|
|
2015-01-10 00:50:09 +00:00
|
|
|
break;
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
2015-01-10 00:50:09 +00:00
|
|
|
|
|
|
|
g_free((char*)fld_ptr);
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
2015-01-10 00:50:09 +00:00
|
|
|
gboolean uat_save(uat_t* uat, char** error) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
|
|
|
gchar* fname = uat_get_actual_filename(uat,TRUE);
|
|
|
|
FILE* fp;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
if (! fname ) return FALSE;
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
fp = ws_fopen(fname,"w");
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2009-02-11 11:04:30 +00:00
|
|
|
if (!fp && errno == ENOENT) {
|
|
|
|
/* Parent directory does not exist, try creating first */
|
|
|
|
gchar *pf_dir_path = NULL;
|
|
|
|
if (create_persconffile_dir(&pf_dir_path) != 0) {
|
2015-01-10 00:50:09 +00:00
|
|
|
*error = g_strdup_printf("uat_save: error creating '%s'", pf_dir_path);
|
2009-02-11 11:04:30 +00:00
|
|
|
g_free (pf_dir_path);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
fp = ws_fopen(fname,"w");
|
|
|
|
}
|
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
if (!fp) {
|
2015-01-10 00:50:09 +00:00
|
|
|
*error = g_strdup_printf("uat_save: error opening '%s': %s",fname,g_strerror(errno));
|
2011-09-21 18:55:03 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
*error = NULL;
|
|
|
|
g_free (fname);
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
/* Ensure raw_data is synced with user_data and all "good" entries have been accounted for */
|
|
|
|
|
|
|
|
/* Start by clearing current user_data */
|
|
|
|
for ( i = 0 ; i < uat->user_data->len ; i++ ) {
|
|
|
|
if (uat->free_cb) {
|
|
|
|
uat->free_cb(UAT_USER_INDEX_PTR(uat,i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_array_set_size(uat->user_data,0);
|
|
|
|
|
|
|
|
*((uat)->user_ptr) = NULL;
|
|
|
|
*((uat)->nrows_p) = 0;
|
|
|
|
|
|
|
|
/* Now copy "good" raw_data entries to user_data */
|
|
|
|
for ( i = 0 ; i < uat->raw_data->len ; i++ ) {
|
|
|
|
void* rec = uat->raw_data->data + (uat->record_size * i);
|
|
|
|
gboolean* valid = (gboolean*)(uat->valid_data->data + sizeof(gboolean)*i);
|
|
|
|
if (*valid) {
|
|
|
|
g_array_append_vals(uat->user_data, rec, 1);
|
|
|
|
if (uat->copy_cb) {
|
|
|
|
uat->copy_cb(UAT_USER_INDEX_PTR(uat,i), rec, (unsigned int) uat->record_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
UAT_UPDATE(uat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
fprintf(fp,"# This file is automatically generated, DO NOT MODIFY.\n");
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for ( i = 0 ; i < uat->user_data->len ; i++ ) {
|
|
|
|
void* rec = uat->user_data->data + (uat->record_size * i);
|
|
|
|
uat_field_t* f;
|
|
|
|
guint j;
|
2007-02-03 14:25:02 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
f = uat->fields;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for( j=0 ; j < uat->ncols ; j++ ) {
|
|
|
|
putfld(fp, rec, &(f[j]));
|
|
|
|
fputs((j == uat->ncols - 1) ? "\n" : "," ,fp);
|
|
|
|
}
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
fclose(fp);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
uat->changed = FALSE;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
return TRUE;
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void uat_destroy(uat_t* uat) {
|
2011-09-21 18:55:03 +00:00
|
|
|
/* XXX still missing a destructor */
|
|
|
|
g_ptr_array_remove(all_uats,uat);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
|
|
|
|
2008-02-15 22:36:24 +00:00
|
|
|
uat_t *uat_find(gchar *name) {
|
|
|
|
guint i;
|
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for (i=0; i < all_uats->len; i++) {
|
2013-03-18 20:44:36 +00:00
|
|
|
uat_t* u = (uat_t *)g_ptr_array_index(all_uats,i);
|
2008-02-15 22:36:24 +00:00
|
|
|
|
|
|
|
if (strcmp(u->name, name) == 0 || strcmp(u->filename, name) == 0) {
|
|
|
|
return u;
|
|
|
|
}
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
2008-02-15 22:36:24 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-02-11 16:09:21 +00:00
|
|
|
void uat_clear(uat_t* uat) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
2007-02-11 16:09:21 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for ( i = 0 ; i < uat->user_data->len ; i++ ) {
|
2013-04-22 02:10:49 +00:00
|
|
|
if (uat->free_cb) {
|
|
|
|
uat->free_cb(UAT_USER_INDEX_PTR(uat,i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( i = 0 ; i < uat->raw_data->len ; i++ ) {
|
2011-09-21 18:55:03 +00:00
|
|
|
if (uat->free_cb) {
|
|
|
|
uat->free_cb(UAT_INDEX_PTR(uat,i));
|
|
|
|
}
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2013-04-22 02:10:49 +00:00
|
|
|
g_array_set_size(uat->raw_data,0);
|
2011-09-21 18:55:03 +00:00
|
|
|
g_array_set_size(uat->user_data,0);
|
2013-04-22 02:10:49 +00:00
|
|
|
g_array_set_size(uat->valid_data,0);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
*((uat)->user_ptr) = NULL;
|
|
|
|
*((uat)->nrows_p) = 0;
|
2007-02-11 16:09:21 +00:00
|
|
|
}
|
|
|
|
|
2008-01-19 01:18:35 +00:00
|
|
|
void uat_unload_all(void) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
2008-01-14 16:40:23 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for (i=0; i < all_uats->len; i++) {
|
2013-03-18 20:44:36 +00:00
|
|
|
uat_t* u = (uat_t *)g_ptr_array_index(all_uats,i);
|
2008-03-06 22:13:24 +00:00
|
|
|
/* Do not unload if not in profile */
|
|
|
|
if (u->from_profile) {
|
|
|
|
uat_clear(u);
|
|
|
|
u->loaded = FALSE;
|
|
|
|
}
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
2008-01-14 16:40:23 +00:00
|
|
|
}
|
|
|
|
|
2013-12-20 07:57:02 +00:00
|
|
|
#if 0
|
2013-12-20 06:30:13 +00:00
|
|
|
static void uat_cleanup(void) {
|
2011-09-21 18:55:03 +00:00
|
|
|
while( all_uats->len ) {
|
|
|
|
uat_destroy((uat_t*)all_uats->pdata);
|
|
|
|
}
|
2007-01-28 10:31:32 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
g_ptr_array_free(all_uats,TRUE);
|
2007-01-28 10:31:32 +00:00
|
|
|
}
|
2013-12-20 07:57:02 +00:00
|
|
|
#endif
|
2007-02-08 10:15:04 +00:00
|
|
|
|
|
|
|
void uat_foreach_table(uat_cb_t cb,void* user_data) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for (i=0; i < all_uats->len; i++)
|
|
|
|
cb(g_ptr_array_index(all_uats,i), user_data);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
|
|
|
}
|
2007-02-08 10:15:04 +00:00
|
|
|
|
|
|
|
|
2007-02-03 14:25:02 +00:00
|
|
|
void uat_load_all(void) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
2015-01-10 00:50:09 +00:00
|
|
|
gchar* err;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for (i=0; i < all_uats->len; i++) {
|
2013-03-18 20:44:36 +00:00
|
|
|
uat_t* u = (uat_t *)g_ptr_array_index(all_uats,i);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2015-01-13 21:00:59 +00:00
|
|
|
if (!u->loaded) {
|
|
|
|
err = NULL;
|
|
|
|
if (!uat_load(u, &err)) {
|
|
|
|
report_failure("Error loading table '%s': %s",u->name,err);
|
|
|
|
g_free(err);
|
|
|
|
}
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
|
|
|
}
|
2007-02-03 14:25:02 +00:00
|
|
|
}
|
|
|
|
|
2007-02-08 10:15:04 +00:00
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_str(void* u1 _U_, const char* strptr, guint len _U_, const void* u2 _U_, const void* u3 _U_, char** err) {
|
2011-09-21 18:55:03 +00:00
|
|
|
if (strptr == NULL) {
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup("NULL pointer");
|
2011-09-21 18:55:03 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
2007-02-03 14:25:02 +00:00
|
|
|
}
|
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_oid(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
2010-06-28 09:30:15 +00:00
|
|
|
unsigned int i;
|
2011-09-21 18:55:03 +00:00
|
|
|
*err = NULL;
|
|
|
|
|
|
|
|
if (strptr == NULL) {
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup("NULL pointer");
|
2011-09-21 18:55:03 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2010-06-28 09:30:15 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
for(i = 0; i < len; i++)
|
2014-10-17 23:10:53 +00:00
|
|
|
if(!(g_ascii_isdigit(strptr[i]) || strptr[i] == '.')) {
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup("Only digits [0-9] and \".\" allowed in an OID");
|
|
|
|
return FALSE;
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
2010-06-28 09:30:15 +00:00
|
|
|
|
2015-01-10 00:50:09 +00:00
|
|
|
if(strptr[len-1] == '.') {
|
|
|
|
*err = g_strdup("OIDs must not be terminated with a \".\"");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-06-28 09:30:15 +00:00
|
|
|
|
2015-01-10 00:50:09 +00:00
|
|
|
if(!((*strptr == '0' || *strptr == '1' || *strptr =='2') && (len > 1 && strptr[1] == '.'))) {
|
|
|
|
*err = g_strdup("OIDs must start with \"0.\" (ITU-T assigned), \"1.\" (ISO assigned) or \"2.\" (joint ISO/ITU-T assigned)");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2010-06-28 09:30:15 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
/* should also check that the second arc is in the range 0-39 */
|
2010-06-28 09:30:15 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
return *err == NULL;
|
2010-06-28 09:30:15 +00:00
|
|
|
}
|
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_proto(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
2011-09-21 18:55:03 +00:00
|
|
|
if (len) {
|
2015-01-10 00:50:09 +00:00
|
|
|
char* name = g_strndup(strptr,len);
|
2011-09-21 18:55:03 +00:00
|
|
|
ascii_strdown_inplace(name);
|
|
|
|
g_strchug(name);
|
|
|
|
|
|
|
|
if (find_dissector(name)) {
|
|
|
|
*err = NULL;
|
2015-01-10 00:50:09 +00:00
|
|
|
g_free(name);
|
2011-09-21 18:55:03 +00:00
|
|
|
return TRUE;
|
|
|
|
} else {
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup("dissector not found");
|
|
|
|
g_free(name);
|
2011-09-21 18:55:03 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2007-02-07 20:45:14 +00:00
|
|
|
}
|
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
static gboolean uat_fld_chk_num(int base, const char* strptr, guint len, char** err) {
|
2009-03-08 22:36:43 +00:00
|
|
|
if (len > 0) {
|
2015-01-10 00:50:09 +00:00
|
|
|
char* str = g_strndup(strptr,len);
|
2014-11-19 03:53:32 +00:00
|
|
|
char* strn;
|
|
|
|
long i;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
i = strtol(str,&strn,base);
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2014-11-19 03:53:32 +00:00
|
|
|
if (((i == G_MAXLONG || i == G_MINLONG) && errno == ERANGE)
|
|
|
|
|| (errno != 0 && i == 0)) {
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup(g_strerror(errno));
|
|
|
|
g_free(str);
|
2009-03-08 22:36:43 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2014-11-19 03:53:32 +00:00
|
|
|
if ((*strn != '\0') && (*strn != ' ')) {
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup("Invalid value");
|
|
|
|
g_free(str);
|
2014-11-19 03:53:32 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/* Allow only 32bit values */
|
|
|
|
if ((sizeof(long) > 4) && ((i < G_MININT) || (i > G_MAXINT))) {
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup("Value too large");
|
|
|
|
g_free(str);
|
2014-11-19 03:53:32 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2015-01-10 00:50:09 +00:00
|
|
|
|
|
|
|
g_free(str);
|
2009-03-08 22:36:43 +00:00
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
*err = NULL;
|
|
|
|
return TRUE;
|
2007-02-07 20:45:14 +00:00
|
|
|
}
|
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_num_dec(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
2014-11-19 03:53:32 +00:00
|
|
|
return uat_fld_chk_num(10, strptr, len, err);
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_num_hex(void* u1 _U_, const char* strptr, guint len, const void* u2 _U_, const void* u3 _U_, char** err) {
|
2014-11-19 03:53:32 +00:00
|
|
|
return uat_fld_chk_num(16, strptr, len, err);
|
2007-02-03 14:25:02 +00:00
|
|
|
}
|
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_enum(void* u1 _U_, const char* strptr, guint len, const void* v, const void* u3 _U_, char** err) {
|
2015-01-10 00:50:09 +00:00
|
|
|
char* str = g_strndup(strptr,len);
|
2011-09-21 18:55:03 +00:00
|
|
|
guint i;
|
2013-03-18 20:44:36 +00:00
|
|
|
const value_string* vs = (const value_string *)v;
|
2011-09-21 18:55:03 +00:00
|
|
|
|
|
|
|
for(i=0;vs[i].strptr;i++) {
|
|
|
|
if (g_str_equal(vs[i].strptr,str)) {
|
|
|
|
*err = NULL;
|
2015-01-10 00:50:09 +00:00
|
|
|
g_free(str);
|
2011-09-21 18:55:03 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup_printf("invalid value: %s",str);
|
|
|
|
g_free(str);
|
2011-09-21 18:55:03 +00:00
|
|
|
return FALSE;
|
2007-02-03 14:25:02 +00:00
|
|
|
}
|
|
|
|
|
2015-01-13 20:13:45 +00:00
|
|
|
gboolean uat_fld_chk_range(void* u1 _U_, const char* strptr, guint len, const void* v _U_, const void* u3, char** err) {
|
2015-01-10 00:50:09 +00:00
|
|
|
char* str = g_strndup(strptr,len);
|
2011-09-21 18:55:03 +00:00
|
|
|
range_t* r = NULL;
|
|
|
|
convert_ret_t ret = range_convert_str(&r, str,GPOINTER_TO_UINT(u3));
|
2015-01-10 00:50:09 +00:00
|
|
|
gboolean ret_value = FALSE;
|
2011-09-21 18:55:03 +00:00
|
|
|
|
|
|
|
switch ( ret ) {
|
|
|
|
case CVT_NO_ERROR:
|
|
|
|
*err = NULL;
|
2015-01-10 00:50:09 +00:00
|
|
|
ret_value = TRUE;
|
|
|
|
break;
|
2011-09-21 18:55:03 +00:00
|
|
|
case CVT_SYNTAX_ERROR:
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup_printf("syntax error in range: %s",str);
|
|
|
|
ret_value = FALSE;
|
|
|
|
break;
|
2011-09-21 18:55:03 +00:00
|
|
|
case CVT_NUMBER_TOO_BIG:
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup_printf("value too large in range: '%s' (max = %u)",str,GPOINTER_TO_UINT(u3));
|
|
|
|
ret_value = FALSE;
|
|
|
|
break;
|
2011-09-21 18:55:03 +00:00
|
|
|
default:
|
2015-01-10 00:50:09 +00:00
|
|
|
*err = g_strdup("This should not happen, it is a bug in wireshark! please report to wireshark-dev@wireshark.org");
|
|
|
|
ret_value = FALSE;
|
|
|
|
break;
|
2011-09-21 18:55:03 +00:00
|
|
|
}
|
2015-01-10 00:50:09 +00:00
|
|
|
|
|
|
|
g_free(str);
|
|
|
|
return ret_value;
|
2007-04-03 19:08:00 +00:00
|
|
|
}
|
|
|
|
|
2007-04-01 14:55:25 +00:00
|
|
|
char* uat_unbinstring(const char* si, guint in_len, guint* len_p) {
|
2011-09-21 18:55:03 +00:00
|
|
|
guint8* buf;
|
|
|
|
guint len = in_len/2;
|
|
|
|
int i = 0;
|
|
|
|
int d0, d1;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
if (in_len%2) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2013-03-18 20:44:36 +00:00
|
|
|
buf= (guint8 *)g_malloc0(len+1);
|
2011-09-21 18:55:03 +00:00
|
|
|
if (len_p) *len_p = len;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
while(in_len) {
|
2014-01-08 00:28:13 +00:00
|
|
|
d1 = ws_xton(*(si++));
|
|
|
|
d0 = ws_xton(*(si++));
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
buf[i++] = (d1 * 16) + d0;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
in_len -= 2;
|
|
|
|
}
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2011-09-21 18:55:03 +00:00
|
|
|
return (char*)buf;
|
2007-04-01 14:55:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char* uat_unesc(const char* si, guint in_len, guint* len_p) {
|
2013-03-18 20:44:36 +00:00
|
|
|
char* buf = (char *)g_malloc0(in_len+1);
|
2011-09-21 18:55:03 +00:00
|
|
|
char* p = buf;
|
|
|
|
guint len = 0;
|
|
|
|
const char* s;
|
|
|
|
const char* in_end = si+in_len;
|
|
|
|
|
2013-03-18 20:44:36 +00:00
|
|
|
for (s = (const char *)si; s < in_end; s++) {
|
2011-09-21 18:55:03 +00:00
|
|
|
switch(*s) {
|
|
|
|
case '\\':
|
|
|
|
switch(*(++s)) {
|
|
|
|
case 'a': *(p++) = '\a'; len++; break;
|
|
|
|
case 'b': *(p++) = '\b'; len++; break;
|
|
|
|
case 'e': *(p++) = '\033' /* '\e' is non ANSI-C */; len++; break;
|
|
|
|
case 'f': *(p++) = '\f'; len++; break;
|
|
|
|
case 'n': *(p++) = '\n'; len++; break;
|
|
|
|
case 'r': *(p++) = '\r'; len++; break;
|
|
|
|
case 't': *(p++) = '\t'; len++; break;
|
|
|
|
case 'v': *(p++) = '\v'; len++; break;
|
|
|
|
|
|
|
|
case '0':
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case '3':
|
|
|
|
case '4':
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
{
|
|
|
|
int c0 = 0;
|
|
|
|
int c1 = 0;
|
|
|
|
int c2 = 0;
|
|
|
|
int c = 0;
|
|
|
|
|
|
|
|
c0 = (*s) - '0';
|
|
|
|
|
|
|
|
if ( s[1] >= '0' && s[1] <= '7' ) {
|
|
|
|
c1 = c0;
|
|
|
|
c0 = (*++s) - '0';
|
|
|
|
|
|
|
|
if ( s[1] >= '0' && s[1] <= '7' ) {
|
|
|
|
c2 = c1;
|
|
|
|
c1 = c0;
|
|
|
|
c0 = (*++s) - '0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c = (64 * c2) + (8 * c1) + c0;
|
|
|
|
*(p++) = (char) (c > 255 ? 255 : c);
|
|
|
|
len++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 'x':
|
|
|
|
{
|
|
|
|
char c1 = *(s+1);
|
|
|
|
char c0 = *(s+2);
|
|
|
|
|
2014-10-17 23:10:53 +00:00
|
|
|
if (g_ascii_isxdigit(c1) && g_ascii_isxdigit(c0)) {
|
2014-01-08 00:28:13 +00:00
|
|
|
*(p++) = (ws_xton(c1) * 0x10) + ws_xton(c0);
|
2011-09-21 18:55:03 +00:00
|
|
|
s += 2;
|
|
|
|
} else {
|
|
|
|
*(p++) = *s;
|
|
|
|
}
|
|
|
|
len++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
*p++ = *s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*(p++) = *s;
|
|
|
|
len++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len_p) *len_p = len;
|
|
|
|
return buf;
|
2007-04-01 14:55:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char* uat_undquote(const char* si, guint in_len, guint* len_p) {
|
2011-09-21 18:55:03 +00:00
|
|
|
return uat_unesc(si+1,in_len-2,len_p);
|
2007-04-01 14:55:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char* uat_esc(const char* buf, guint len) {
|
2013-12-21 17:34:41 +00:00
|
|
|
const guint8* end = ((const guint8*)buf)+len;
|
2015-01-10 00:50:09 +00:00
|
|
|
char* out = (char *)g_malloc0((4*len)+1);
|
2011-09-21 18:55:03 +00:00
|
|
|
const guint8* b;
|
|
|
|
char* s = out;
|
|
|
|
|
2013-12-21 17:34:41 +00:00
|
|
|
for (b = (const guint8 *)buf; b < end; b++) {
|
2014-05-13 12:44:47 +00:00
|
|
|
if (g_ascii_isprint(*b) ) {
|
2011-09-21 18:55:03 +00:00
|
|
|
*(s++) = (*b);
|
|
|
|
} else {
|
|
|
|
g_snprintf(s,5,"\\x%.2x",((guint)*b));
|
|
|
|
s+=4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
2007-10-16 15:43:18 +00:00
|
|
|
|
2007-04-01 14:55:25 +00:00
|
|
|
}
|
|
|
|
|
2007-02-03 14:25:02 +00:00
|
|
|
CHK_STR_IS_DEF(isprint)
|
|
|
|
CHK_STR_IS_DEF(isalpha)
|
|
|
|
CHK_STR_IS_DEF(isalnum)
|
|
|
|
CHK_STR_IS_DEF(isdigit)
|
|
|
|
CHK_STR_IS_DEF(isxdigit)
|
|
|
|
|
2008-02-15 22:36:24 +00:00
|
|
|
/*
|
|
|
|
* Editor modelines
|
|
|
|
*
|
|
|
|
* Local Variables:
|
|
|
|
* c-basic-offset: 4
|
2011-09-21 18:55:03 +00:00
|
|
|
* tab-width: 8
|
2008-02-15 22:36:24 +00:00
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* End:
|
|
|
|
*
|
2011-09-21 18:55:03 +00:00
|
|
|
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
|
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
2008-02-15 22:36:24 +00:00
|
|
|
*/
|