4 * User Accessible Tables
5 * Maintain an array of user accessible data structures
7 * (c) 2007, Luis E. Garcia Ontanon <luis@ontanon.org>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 2001 Gerald Combs
13 * SPDX-License-Identifier: GPL-2.0-or-later
25 #include <wsutil/file_util.h>
26 #include <wsutil/str_util.h>
27 #include <wsutil/report_message.h>
28 #include <wsutil/ws_assert.h>
30 #include <wsutil/filesystem.h>
31 #include <epan/packet.h>
32 #include <epan/range.h>
37 * XXX Files are encoded as ASCII. We might want to encode them as UTF8
41 static GPtrArray
* all_uats
;
43 uat_t
* uat_new(const char* name
,
48 unsigned* numitems_ptr
,
51 uat_copy_cb_t copy_cb
,
52 uat_update_cb_t update_cb
,
53 uat_free_cb_t free_cb
,
54 uat_post_update_cb_t post_update_cb
,
55 uat_reset_cb_t reset_cb
,
56 uat_field_t
* flds_array
) {
58 uat_t
* uat
= g_new(uat_t
, 1);
61 /* Add to global array of uats */
63 all_uats
= g_ptr_array_new();
65 g_ptr_array_add(all_uats
,uat
);
68 ws_assert(name
&& size
&& filename
&& data_ptr
&& numitems_ptr
);
70 /* Set uat values from inputs */
71 uat
->name
= g_strdup(name
);
72 uat
->record_size
= size
;
73 uat
->filename
= g_strdup(filename
);
74 uat
->from_profile
= from_profile
;
75 /* Callers of uat_new() pass in (void*) for data_ptr, because
76 * that is the "universal" pointer type that can be cast to
77 * anything. However, for our purposes, we want a (void**).
78 * So, we cast (void*) data_ptr to (void**) here. That keeps
79 * gcc -fstrict-aliasing from complaining. */
80 uat
->user_ptr
= (void**) data_ptr
;
81 uat
->nrows_p
= numitems_ptr
;
82 uat
->copy_cb
= copy_cb
;
83 uat
->update_cb
= update_cb
;
84 uat
->free_cb
= free_cb
;
85 uat
->post_update_cb
= post_update_cb
;
86 uat
->reset_cb
= reset_cb
;
87 uat
->fields
= flds_array
;
88 uat
->default_values
= NULL
;
89 uat
->user_data
= g_array_new(false,false,(unsigned)uat
->record_size
);
90 uat
->raw_data
= g_array_new(false,false,(unsigned)uat
->record_size
);
91 uat
->valid_data
= g_array_new(false,false,sizeof(bool));
96 uat
->help
= g_strdup(help
);
99 for (i
=0;flds_array
[i
].title
;i
++) {
100 fld_data_t
* f
= g_new(fld_data_t
, 1);
106 flds_array
[i
].priv
= f
;
111 *((void**)data_ptr
) = NULL
;
117 void* uat_add_record(uat_t
* uat
, const void* data
, bool valid_rec
) {
121 uat_insert_record_idx(uat
, uat
->raw_data
->len
, data
);
124 /* Add a "known good" record to the list to be used by the dissector */
125 g_array_append_vals (uat
->user_data
, data
, 1);
127 rec
= UAT_USER_INDEX_PTR(uat
, uat
->user_data
->len
- 1);
130 uat
->copy_cb(rec
, data
, (unsigned int) uat
->record_size
);
135 valid
= &g_array_index(uat
->valid_data
, bool, uat
->valid_data
->len
-1);
144 /* Updates the validity of a record. */
145 void uat_update_record(uat_t
*uat
, const void *record
, bool valid_rec
) {
149 /* Locate internal UAT data pointer. */
150 for (pos
= 0; pos
< uat
->raw_data
->len
; pos
++) {
151 if (UAT_INDEX_PTR(uat
, pos
) == record
) {
155 if (pos
== uat
->raw_data
->len
) {
156 /* Data is not within list?! */
157 ws_assert_not_reached();
160 valid
= &g_array_index(uat
->valid_data
, bool, pos
);
164 void uat_swap(uat_t
* uat
, unsigned a
, unsigned b
) {
165 size_t s
= uat
->record_size
;
169 ws_assert( a
< uat
->raw_data
->len
&& b
< uat
->raw_data
->len
);
174 memcpy(tmp
, UAT_INDEX_PTR(uat
,a
), s
);
175 memcpy(UAT_INDEX_PTR(uat
,a
), UAT_INDEX_PTR(uat
,b
), s
);
176 memcpy(UAT_INDEX_PTR(uat
,b
), tmp
, s
);
179 tmp_bool
= *(bool*)(uat
->valid_data
->data
+ (sizeof(bool) * (a
)));
180 *(bool*)(uat
->valid_data
->data
+ (sizeof(bool) * (a
))) = *(bool*)(uat
->valid_data
->data
+ (sizeof(bool) * (b
)));
181 *(bool*)(uat
->valid_data
->data
+ (sizeof(bool) * (b
))) = tmp_bool
;
186 void uat_insert_record_idx(uat_t
* uat
, unsigned idx
, const void *src_record
) {
187 /* Allow insert before an existing item or append after the last item. */
188 ws_assert( idx
<= uat
->raw_data
->len
);
190 /* Store a copy of the record and invoke copy_cb to clone pointers too. */
191 g_array_insert_vals(uat
->raw_data
, idx
, src_record
, 1);
192 void *rec
= UAT_INDEX_PTR(uat
, idx
);
194 uat
->copy_cb(rec
, src_record
, (unsigned int) uat
->record_size
);
196 memcpy(rec
, src_record
, (unsigned int) uat
->record_size
);
199 /* Initially assume that the record is invalid, it is not copied to the
200 * user-visible records list. */
201 bool valid_rec
= false;
202 g_array_insert_val(uat
->valid_data
, idx
, valid_rec
);
205 void uat_remove_record_idx(uat_t
* uat
, unsigned idx
) {
207 ws_assert( idx
< uat
->raw_data
->len
);
210 uat
->free_cb(UAT_INDEX_PTR(uat
,idx
));
213 g_array_remove_index(uat
->raw_data
, idx
);
214 g_array_remove_index(uat
->valid_data
, idx
);
217 void uat_remove_record_range(uat_t
* uat
, unsigned idx
, unsigned count
) {
219 ws_assert( idx
+ count
<= uat
->raw_data
->len
);
226 for (unsigned i
= 0; i
< count
; i
++) {
227 uat
->free_cb(UAT_INDEX_PTR(uat
, idx
+ i
));
231 g_array_remove_range(uat
->raw_data
, idx
, count
);
232 g_array_remove_range(uat
->valid_data
, idx
, count
);
235 void uat_move_index(uat_t
* uat
, unsigned old_idx
, unsigned new_idx
)
238 unsigned start
= old_idx
;
239 if ( old_idx
> new_idx
)
242 while ( start
!= new_idx
)
244 uat_swap(uat
, start
, start
+ dir
);
249 /* The returned filename was g_malloc()'d so the caller must free it */
250 char* uat_get_actual_filename(uat_t
* uat
, bool for_writing
) {
251 char *pers_fname
= NULL
;
253 pers_fname
= get_persconffile_path(uat
->filename
, uat
->from_profile
);
254 if ((! for_writing
) && (! file_exists(pers_fname
) )) {
255 char* data_fname
= get_datafile_path(uat
->filename
);
257 if (file_exists(data_fname
)) {
270 uat_t
* uat_get_table_by_name(const char* name
) {
273 for (i
=0; i
< all_uats
->len
; i
++) {
274 uat_t
* u
= (uat_t
*)g_ptr_array_index(all_uats
,i
);
275 if ( g_str_equal(u
->name
,name
) ) {
283 void uat_set_default_values(uat_t
*uat_in
, const char *default_values
[])
285 uat_in
->default_values
= default_values
;
288 char *uat_fld_tostr(void *rec
, uat_field_t
*f
) {
293 f
->cb
.tostr(rec
, &ptr
, &len
, f
->cbdata
.tostr
, f
->fld_data
);
299 case PT_TXTMOD_FILENAME
:
300 case PT_TXTMOD_DIRECTORYNAME
:
301 case PT_TXTMOD_DISPLAY_FILTER
:
302 case PT_TXTMOD_PROTO_FIELD
:
303 case PT_TXTMOD_COLOR
:
304 case PT_TXTMOD_STRING
:
305 case PT_TXTMOD_DISSECTOR
:
306 out
= g_strndup(ptr
, len
);
308 case PT_TXTMOD_HEXBYTES
: {
309 GString
*s
= g_string_sized_new( len
*2 + 1 );
312 for (i
=0; i
<len
;i
++) g_string_append_printf(s
, "%.2X", ((const uint8_t*)ptr
)[i
]);
314 out
= g_string_free(s
, FALSE
);
318 ws_assert_not_reached();
327 static void putfld(FILE* fp
, void* rec
, uat_field_t
* f
) {
331 f
->cb
.tostr(rec
,&fld_ptr
,&fld_len
,f
->cbdata
.tostr
,f
->fld_data
);
336 case PT_TXTMOD_FILENAME
:
337 case PT_TXTMOD_DIRECTORYNAME
:
338 case PT_TXTMOD_DISPLAY_FILTER
:
339 case PT_TXTMOD_PROTO_FIELD
:
340 case PT_TXTMOD_COLOR
:
341 case PT_TXTMOD_STRING
:
342 case PT_TXTMOD_DISSECTOR
:
348 for(i
=0;i
<fld_len
;i
++) {
351 if (c
== '"' || c
== '\\' || ! g_ascii_isprint((unsigned char)c
) ) {
352 fprintf(fp
,"\\x%02x", (unsigned char) c
);
361 case PT_TXTMOD_HEXBYTES
: {
364 for(i
=0;i
<fld_len
;i
++) {
365 fprintf(fp
,"%02x", (unsigned char)fld_ptr
[i
]);
370 case PT_TXTMOD_BOOL
: {
371 fprintf(fp
,"\"%s\"", fld_ptr
);
375 ws_assert_not_reached();
381 bool uat_save(uat_t
* uat
, char** error
) {
383 char* fname
= uat_get_actual_filename(uat
,true);
386 if (! fname
) return false;
388 fp
= ws_fopen(fname
,"w");
390 if (!fp
&& errno
== ENOENT
) {
391 /* Parent directory does not exist, try creating first */
392 char *pf_dir_path
= NULL
;
393 if (create_persconffile_dir(&pf_dir_path
) != 0) {
394 *error
= ws_strdup_printf("uat_save: error creating '%s'", pf_dir_path
);
395 g_free (pf_dir_path
);
398 fp
= ws_fopen(fname
,"w");
402 *error
= ws_strdup_printf("uat_save: error opening '%s': %s",fname
,g_strerror(errno
));
410 /* Ensure raw_data is synced with user_data and all "good" entries have been accounted for */
412 /* Start by clearing current user_data */
413 for ( i
= 0 ; i
< uat
->user_data
->len
; i
++ ) {
415 uat
->free_cb(UAT_USER_INDEX_PTR(uat
,i
));
418 g_array_set_size(uat
->user_data
,0);
420 *((uat
)->user_ptr
) = NULL
;
421 *((uat
)->nrows_p
) = 0;
423 /* Now copy "good" raw_data entries to user_data */
424 for ( i
= 0 ; i
< uat
->raw_data
->len
; i
++ ) {
425 void *rec
= UAT_INDEX_PTR(uat
, i
);
426 bool valid
= g_array_index(uat
->valid_data
, bool, i
);
428 g_array_append_vals(uat
->user_data
, rec
, 1);
430 uat
->copy_cb(UAT_USER_INDEX_PTR(uat
, uat
->user_data
->len
- 1),
431 rec
, (unsigned int) uat
->record_size
);
439 fprintf(fp
,"# This file is automatically generated. BE CAREFUL MODIFYING.\n");
440 fprintf(fp
,"# You can add (but not modify or delete) records with the command line option:\n");
442 /* Powershell 7.3 has UN*X-like treatment of double quotes inside quotes.
443 * Since it's not shipped with Windows, assume someone using PS 7.3 or
444 * later knows how to quote with it.
446 fprintf(fp
,"# -o \"uat:%s:", uat
->filename
);
448 fprintf(fp
,"# -o 'uat:%s:", uat
->filename
);
450 for (i
= 0; i
< uat
->ncols
; ++i
) {
451 uat_field_t
*field
= &uat
->fields
[i
];
452 switch(field
->mode
) {
453 case PT_TXTMOD_HEXBYTES
:
454 fprintf(fp
, "%s", field
->name
);
458 fprintf(fp
, "\\\"%s\\\"", field
->name
);
460 fprintf(fp
, "\"%s\"", field
->name
);
464 fputs((i
== uat
->ncols
- 1) ? "\"\n" : "," ,fp
);
466 fputs((i
== uat
->ncols
- 1) ? "'\n" : "," ,fp
);
471 for (i
= 0; i
< uat
->ncols
; ++i
) {
472 uat_field_t
*field
= &uat
->fields
[i
];
473 switch(field
->mode
) {
474 case PT_TXTMOD_HEXBYTES
:
475 fprintf(fp
, "%s", field
->title
);
478 fprintf(fp
, "\"%s\"", field
->title
);
480 fputs((i
== uat
->ncols
- 1) ? "\n" : "," ,fp
);
483 for ( i
= 0 ; i
< uat
->user_data
->len
; i
++ ) {
484 void* rec
= uat
->user_data
->data
+ (uat
->record_size
* i
);
491 for( j
=0 ; j
< uat
->ncols
; j
++ ) {
492 putfld(fp
, rec
, &(f
[j
]));
493 fputs((j
== uat
->ncols
- 1) ? "\n" : "," ,fp
);
500 uat
->changed
= false;
505 uat_t
*uat_find(char *name
) {
508 for (i
=0; i
< all_uats
->len
; i
++) {
509 uat_t
* u
= (uat_t
*)g_ptr_array_index(all_uats
,i
);
511 if (strcmp(u
->name
, name
) == 0 || strcmp(u
->filename
, name
) == 0) {
518 void uat_clear(uat_t
* uat
) {
521 for ( i
= 0 ; i
< uat
->user_data
->len
; i
++ ) {
523 uat
->free_cb(UAT_USER_INDEX_PTR(uat
,i
));
527 for ( i
= 0 ; i
< uat
->raw_data
->len
; i
++ ) {
529 uat
->free_cb(UAT_INDEX_PTR(uat
,i
));
533 g_array_set_size(uat
->raw_data
,0);
534 g_array_set_size(uat
->user_data
,0);
535 g_array_set_size(uat
->valid_data
,0);
537 *((uat
)->user_ptr
) = NULL
;
538 *((uat
)->nrows_p
) = 0;
545 void uat_unload_all(void) {
548 for (i
=0; i
< all_uats
->len
; i
++) {
549 uat_t
* u
= (uat_t
*)g_ptr_array_index(all_uats
,i
);
550 /* Do not unload if not in profile */
551 if (u
->from_profile
) {
558 static void free_uat(uat_t
*uat
)
565 g_free(uat
->filename
);
566 g_array_free(uat
->user_data
, true);
567 g_array_free(uat
->raw_data
, true);
568 g_array_free(uat
->valid_data
, true);
569 for (j
= 0; uat
->fields
[j
].title
; j
++)
570 g_free(uat
->fields
[j
].priv
);
574 void uat_cleanup(void) {
578 for (i
= 0; i
< all_uats
->len
; i
++) {
579 uat
= (uat_t
*)g_ptr_array_index(all_uats
, i
);
583 g_ptr_array_free(all_uats
,true);
586 void uat_destroy(uat_t
*uat
)
588 g_ptr_array_remove(all_uats
, uat
);
592 void uat_foreach_table(uat_cb_t cb
,void* user_data
) {
595 for (i
=0; i
< all_uats
->len
; i
++)
596 cb(g_ptr_array_index(all_uats
,i
), user_data
);
600 void uat_load_all(void) {
604 for (i
=0; i
< all_uats
->len
; i
++) {
605 uat_t
* u
= (uat_t
*)g_ptr_array_index(all_uats
,i
);
609 if (!uat_load(u
, NULL
, &err
)) {
610 report_failure("Error loading table '%s': %s",u
->name
,err
);
618 bool uat_fld_chk_str(void* u1 _U_
, const char* strptr
, unsigned len _U_
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
619 if (strptr
== NULL
) {
620 *err
= g_strdup("NULL pointer");
628 bool uat_fld_chk_oid(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
632 if (strptr
== NULL
) {
633 *err
= g_strdup("NULL pointer");
638 *err
= g_strdup("Empty OID");
642 for(i
= 0; i
< len
; i
++)
643 if(!(g_ascii_isdigit(strptr
[i
]) || strptr
[i
] == '.')) {
644 *err
= g_strdup("Only digits [0-9] and \".\" allowed in an OID");
648 if(strptr
[len
-1] == '.') {
649 *err
= g_strdup("OIDs must not be terminated with a \".\"");
653 if(!((*strptr
== '0' || *strptr
== '1' || *strptr
=='2') && (len
> 1 && strptr
[1] == '.'))) {
654 *err
= g_strdup("OIDs must start with \"0.\" (ITU-T assigned), \"1.\" (ISO assigned) or \"2.\" (joint ISO/ITU-T assigned)");
658 /* should also check that the second arc is in the range 0-39 */
663 bool uat_fld_chk_proto(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
665 char* name
= g_strndup(strptr
,len
);
668 if (find_dissector(name
)) {
673 *err
= g_strdup("dissector not found");
683 static bool uat_fld_chk_num_check_result(bool result
, const char* strn
, char** err
) {
684 if (result
&& ((*strn
!= '\0') && (*strn
!= ' '))) {
685 /* string valid, but followed by something other than a space */
693 *err
= g_strdup("Invalid value");
697 *err
= g_strdup("Value too large");
701 *err
= g_strdup(g_strerror(errno
));
709 static bool uat_fld_chk_num(int base
, const char* strptr
, unsigned len
, char** err
) {
711 char* str
= g_strndup(strptr
, len
);
716 result
= ws_basestrtou32(str
, &strn
, &value
, base
);
717 result
= uat_fld_chk_num_check_result(result
, strn
, err
);
726 static bool uat_fld_chk_num64(int base
, const char* strptr
, unsigned len
, char** err
) {
728 char* str
= g_strndup(strptr
, len
);
733 result
= ws_basestrtou64(str
, &strn
, &value64
, base
);
734 result
= uat_fld_chk_num_check_result(result
, strn
, err
);
743 bool uat_fld_chk_num_dec(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
744 return uat_fld_chk_num(10, strptr
, len
, err
);
747 bool uat_fld_chk_num_hex(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
748 return uat_fld_chk_num(16, strptr
, len
, err
);
751 bool uat_fld_chk_num_dec64(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
752 return uat_fld_chk_num64(10, strptr
, len
, err
);
755 bool uat_fld_chk_num_hex64(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
756 return uat_fld_chk_num64(16, strptr
, len
, err
);
759 bool uat_fld_chk_num_signed_dec(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
761 char* str
= g_strndup(strptr
,len
);
766 result
= ws_strtoi32(str
, &strn
, &value
);
767 result
= uat_fld_chk_num_check_result(result
, strn
, err
);
777 bool uat_fld_chk_num_signed_dec64(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
779 char* str
= g_strndup(strptr
, len
);
784 result
= ws_strtoi64(str
, &strn
, &value
);
785 result
= uat_fld_chk_num_check_result(result
, strn
, err
);
795 bool uat_fld_chk_bool(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
)
797 char* str
= g_strndup(strptr
,len
);
799 if ((g_strcmp0(str
, "TRUE") == 0) ||
800 (g_strcmp0(str
, "FALSE") == 0)) {
806 *err
= ws_strdup_printf("invalid value: %s (must be true or false)", str
);
812 bool uat_fld_chk_enum(void* u1 _U_
, const char* strptr
, unsigned len
, const void* v
, const void* u3 _U_
, char** err
) {
813 char* str
= g_strndup(strptr
,len
);
815 const value_string
* vs
= (const value_string
*)v
;
817 for(i
=0;vs
[i
].strptr
;i
++) {
818 if (g_strcmp0(vs
[i
].strptr
,str
) == 0) {
825 *err
= ws_strdup_printf("invalid value: %s",str
);
830 bool uat_fld_chk_range(void* u1 _U_
, const char* strptr
, unsigned len
, const void* v _U_
, const void* u3
, char** err
) {
831 char* str
= g_strndup(strptr
,len
);
833 convert_ret_t ret
= range_convert_str(NULL
, &r
, str
,GPOINTER_TO_UINT(u3
));
834 bool ret_value
= false;
841 case CVT_SYNTAX_ERROR
:
842 *err
= ws_strdup_printf("syntax error in range: %s",str
);
845 case CVT_NUMBER_TOO_BIG
:
846 *err
= ws_strdup_printf("value too large in range: '%s' (max = %u)",str
,GPOINTER_TO_UINT(u3
));
850 *err
= g_strdup("Unable to convert range. Please report this to wireshark-dev@wireshark.org");
860 bool uat_fld_chk_color(void* u1 _U_
, const char* strptr
, unsigned len
, const void* v _U_
, const void* u3 _U_
, char** err
) {
862 if ((len
!= 7) || (*strptr
!= '#')) {
863 *err
= g_strdup("Color must be of the format #RRGGBB");
867 /* Color is just # followed by hex string, so use hex verification */
868 return uat_fld_chk_num(16, strptr
+ 1, len
- 1, err
);
871 char* uat_unbinstring(const char* si
, unsigned in_len
, unsigned* len_p
) {
873 unsigned len
= in_len
/2;
881 buf
= (uint8_t *)g_malloc0(len
+1);
882 if (len_p
) *len_p
= len
;
885 d1
= ws_xton(*(si
++));
886 d0
= ws_xton(*(si
++));
888 buf
[i
++] = (d1
* 16) + d0
;
896 char* uat_unesc(const char* si
, unsigned in_len
, unsigned* len_p
) {
897 char* buf
= (char *)g_malloc0(in_len
+1);
901 const char* in_end
= si
+in_len
;
903 for (s
= si
; s
< in_end
; s
++) {
907 case 'a': *(p
++) = '\a'; len
++; break;
908 case 'b': *(p
++) = '\b'; len
++; break;
909 case 'e': *(p
++) = '\033' /* '\e' is non ANSI-C */; len
++; break;
910 case 'f': *(p
++) = '\f'; len
++; break;
911 case 'n': *(p
++) = '\n'; len
++; break;
912 case 'r': *(p
++) = '\r'; len
++; break;
913 case 't': *(p
++) = '\t'; len
++; break;
914 case 'v': *(p
++) = '\v'; len
++; break;
932 if ( s
[1] >= '0' && s
[1] <= '7' ) {
936 if ( s
[1] >= '0' && s
[1] <= '7' ) {
942 c
= (64 * c2
) + (8 * c1
) + c0
;
943 *(p
++) = (char) (c
> 255 ? 255 : c
);
953 if (g_ascii_isxdigit(c1
) && g_ascii_isxdigit(c0
)) {
954 *(p
++) = (ws_xton(c1
) * 0x10) + ws_xton(c0
);
974 if (len_p
) *len_p
= len
;
978 char* uat_undquote(const char* si
, unsigned in_len
, unsigned* len_p
) {
979 return uat_unesc(si
+1,in_len
-2,len_p
);
983 char* uat_esc(const char* buf
, unsigned len
) {
984 const uint8_t* end
= ((const uint8_t*)buf
)+len
;
985 char* out
= (char *)g_malloc0((4*len
)+1);
989 for (b
= (const uint8_t *)buf
; b
< end
; b
++) {
990 if (*b
== '"' || *b
== '\\' || ! g_ascii_isprint(*b
) ) {
991 snprintf(s
,5,"\\x%02x",((unsigned)*b
));
1002 bool uat_fld_chk_str_isprint(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
1005 for (i
= 0; i
< len
; i
++) {
1007 if (! g_ascii_isprint(c
)) {
1008 *err
= ws_strdup_printf("invalid char pos=%d value=%02x", i
, (unsigned char) c
);
1016 bool uat_fld_chk_str_isalpha(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
1019 for (i
= 0; i
< len
; i
++) {
1021 if (! g_ascii_isalpha(c
)) {
1022 *err
= ws_strdup_printf("invalid char pos=%d value=%02x", i
, (unsigned char) c
);
1030 bool uat_fld_chk_str_isalnum(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
1033 for (i
= 0; i
< len
; i
++) {
1035 if (! g_ascii_isalnum(c
)) {
1036 *err
= ws_strdup_printf("invalid char pos=%d value=%02x", i
, (unsigned char) c
);
1044 bool uat_fld_chk_str_isdigit(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
1047 for (i
= 0; i
< len
; i
++) {
1049 if (! g_ascii_isdigit(c
)) {
1050 *err
= ws_strdup_printf("invalid char pos=%d value=%02x", i
, (unsigned char) c
);
1058 bool uat_fld_chk_str_isxdigit(void* u1 _U_
, const char* strptr
, unsigned len
, const void* u2 _U_
, const void* u3 _U_
, char** err
) {
1061 for (i
= 0; i
< len
; i
++) {
1063 if (! g_ascii_isxdigit(c
)) {
1064 *err
= ws_strdup_printf("invalid char pos=%d value=%02x", i
, (unsigned char) c
);
1079 * indent-tabs-mode: nil
1082 * ex: set shiftwidth=4 tabstop=8 expandtab:
1083 * :indentSize=4:tabSize=8:noTabs=true: