3 * Copyright 2005, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include <epan/emem.h>
35 #include <epan/proto.h>
36 #include <epan/tvbparse.h>
38 typedef enum _tvbparse_wanted_type_t {
39 TVBPARSE_WANTED_NONE, /* currently unused */
42 TVBPARSE_WANTED_SIMPLE_CHAR, /* just one matching char */
43 TVBPARSE_WANTED_SIMPLE_CHARS, /* a sequence of matching chars */
44 TVBPARSE_WANTED_SIMPLE_NOT_CHAR, /* one non matching char */
45 TVBPARSE_WANTED_SIMPLE_NOT_CHARS, /* a sequence of non matching chars */
46 TVBPARSE_WANTED_SIMPLE_STRING, /* a string */
47 TVBPARSE_WANTED_SIMPLE_CASESTRING, /* a caseless string */
48 TVBPARSE_WANTED_UNTIL, /* all the characters until the first matching token */
51 TVBPARSE_WANTED_SET_ONEOF, /* one of the given types */
52 TVBPARSE_WANTED_SET_SEQ, /* an exact sequence of tokens of the given types */
53 TVBPARSE_WANTED_CARDINALITY /* one or more tokens of the given type */
62 const tvbparse_wanted_t* ignore;
66 struct _tvbparse_wanted_t {
77 tvbparse_action_t before;
78 tvbparse_action_t after;
84 tvbparse_wanted_t* tvbparse_char(int id,
87 tvbparse_action_t before_cb,
88 tvbparse_action_t after_cb) {
89 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
92 w->type = TVBPARSE_WANTED_SIMPLE_CHAR;
98 w->before = before_cb;
100 w->elems = g_ptr_array_new();
105 tvbparse_wanted_t* tvbparse_chars(int id,
110 tvbparse_action_t before_cb,
111 tvbparse_action_t after_cb) {
112 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
115 w->type = TVBPARSE_WANTED_SIMPLE_CHARS;
118 w->min = min_len ? min_len : 1;
119 w->max = max_len ? max_len : G_MAXINT;
121 w->before = before_cb;
123 w->elems = g_ptr_array_new();
128 tvbparse_wanted_t* tvbparse_not_char(int id,
131 tvbparse_action_t before_cb,
132 tvbparse_action_t after_cb) {
133 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
136 w->type = TVBPARSE_WANTED_SIMPLE_NOT_CHAR;
142 w->before = before_cb;
144 w->elems = g_ptr_array_new();
149 tvbparse_wanted_t* tvbparse_not_chars(int id,
154 tvbparse_action_t before_cb,
155 tvbparse_action_t after_cb){
156 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
159 w->type = TVBPARSE_WANTED_SIMPLE_NOT_CHARS;
162 w->min = min_len ? min_len : 1;
163 w->max = max_len ? max_len : G_MAXINT;
165 w->before = before_cb;
167 w->elems = g_ptr_array_new();
173 tvbparse_wanted_t* tvbparse_string(int id,
176 tvbparse_action_t before_cb,
177 tvbparse_action_t after_cb) {
178 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
181 w->type = TVBPARSE_WANTED_SIMPLE_STRING;
183 w->len = strlen(str);
187 w->before = before_cb;
189 w->elems = g_ptr_array_new();
194 tvbparse_wanted_t* tvbparse_casestring(int id,
197 tvbparse_action_t before_cb,
198 tvbparse_action_t after_cb) {
199 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
202 w->type = TVBPARSE_WANTED_SIMPLE_CASESTRING;
204 w->len = strlen(str);
208 w->before = before_cb;
210 w->elems = g_ptr_array_new();
216 tvbparse_wanted_t* tvbparse_set_oneof(int id,
218 tvbparse_action_t before_cb,
219 tvbparse_action_t after_cb,
221 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
226 w->type = TVBPARSE_WANTED_SET_ONEOF;
232 w->before = before_cb;
234 w->elems = g_ptr_array_new();
236 va_start(ap,after_cb);
238 while(( el = va_arg(ap,tvbparse_t*) )) {
239 g_ptr_array_add(w->elems,el);
247 tvbparse_wanted_t* tvbparse_set_seq(int id,
249 tvbparse_action_t before_cb,
250 tvbparse_action_t after_cb,
252 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
253 tvbparse_wanted_t* el = NULL;
257 w->type = TVBPARSE_WANTED_SET_SEQ;
263 w->before = before_cb;
265 w->elems = g_ptr_array_new();
267 va_start(ap,after_cb);
269 while(( el = va_arg(ap,tvbparse_wanted_t*) )) {
270 g_ptr_array_add(w->elems,el);
278 tvbparse_wanted_t* tvbparse_some(int id,
282 tvbparse_action_t before_cb,
283 tvbparse_action_t after_cb,
284 const tvbparse_wanted_t* el) {
286 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
288 g_assert(from <= to);
291 w->type = TVBPARSE_WANTED_CARDINALITY;
297 w->before = before_cb;
299 w->elems = g_ptr_array_new();
301 g_ptr_array_add(w->elems,(gpointer)el);
306 tvbparse_wanted_t* tvbparse_until(int id,
308 tvbparse_action_t before_cb,
309 tvbparse_action_t after_cb,
310 const tvbparse_wanted_t* el,
311 gboolean include_term) {
312 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
315 w->type = TVBPARSE_WANTED_UNTIL;
317 /* XXX this is ugly */
318 w->ctl = include_term ? "include" : "do not include";
324 w->before = before_cb;
326 w->elems = g_ptr_array_new();
328 g_ptr_array_add(w->elems,(gpointer)el);
334 tvbparse_wanted_t* tvbparse_quoted(int id,
336 tvbparse_action_t before_cb,
337 tvbparse_action_t after_cb,
341 gchar* esc_quot = g_strdup_printf("%c%c",esc,quote);
342 gchar* quot = g_strdup_printf("%c",quote);
343 tvbparse_wanted_t* want_quot = tvbparse_char(-1,quot,NULL,NULL,NULL);
345 return tvbparse_set_oneof(id, data, before_cb, after_cb,
346 tvbparse_set_seq(-1, NULL, NULL, NULL,
348 tvbparse_set_seq(-1,NULL,NULL,NULL,
349 tvbparse_set_oneof(-1, NULL, NULL, NULL,
350 tvbparse_string(-1,esc_quot,NULL,NULL,NULL),
351 tvbparse_not_chars(-1,0,0,quot,NULL,NULL,NULL),
356 tvbparse_set_seq(-1, NULL, NULL, NULL,
364 void tvbparse_shrink_token_cb(void* tvbparse_data _U_,
365 const void* wanted_data _U_,
366 tvbparse_elem_t* tok) {
371 tvbparse_t* tvbparse_init(tvbuff_t* tvb,
375 const tvbparse_wanted_t* ignore) {
376 tvbparse_t* tt = ep_alloc(sizeof(tvbparse_t));
380 tt->max_len = (len == -1) ? (int) tvb_length(tvb) : len;
387 gboolean tvbparse_reset(tvbparse_t* tt,
391 len = (len == -1) ? (int) tvb_length(tt->tvb) : len;
393 if( tvb_length_remaining(tt->tvb, offset) >= len) {
404 static tvbparse_elem_t* new_tok(tvbparse_t* tt,
408 const tvbparse_wanted_t* wanted) {
409 tvbparse_elem_t* tok = ep_alloc(sizeof(tvbparse_elem_t));
413 tok->offset = offset;
418 tok->wanted = wanted;
424 guint tvbparse_curr_offset(tvbparse_t* tt) {
427 guint tvbparse_len_left(tvbparse_t* tt) {
431 tvbparse_elem_t* tvbparse_get(tvbparse_t* tt,
432 const tvbparse_wanted_t* wanted) {
433 tvbparse_elem_t* tok = NULL;
434 int save_offset = tt->offset;
435 int save_len = tt->max_len;
439 if (tt->ignore && tt->ignore != wanted) {
440 tvbparse_wanted_t* save = (void*)tt->ignore;
442 while ( tvbparse_get(tt,save) ) {
448 switch(wanted->type) {
449 case TVBPARSE_WANTED_NONE:
451 case TVBPARSE_WANTED_SIMPLE_NOT_CHAR:
455 gboolean not_matched = FALSE;
460 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
462 for(i = 0; (c = wanted->ctl[i]) && tt->max_len; i++) {
473 tok = new_tok(tt,wanted->id,tt->offset-1,1,wanted);
477 case TVBPARSE_WANTED_SIMPLE_CHAR:
485 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
487 for(i = 0; (c = wanted->ctl[i]) && tt->max_len; i++) {
491 tok = new_tok(tt,wanted->id,tt->offset-1,1,wanted);
497 case TVBPARSE_WANTED_SIMPLE_NOT_CHARS:
501 guint offset = tt->offset;
504 while( tt->max_len && length < wanted->max) {
505 gboolean not_matched = FALSE;
506 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
509 while ( (c = wanted->ctl[i]) && tt->max_len ) {
526 if ( length < wanted->min ) {
529 tok = new_tok(tt,wanted->id,offset,length,wanted);
533 case TVBPARSE_WANTED_SIMPLE_CHARS:
537 guint offset = tt->offset;
540 while( tt->max_len && length < wanted->max) {
541 gboolean matched = FALSE;
542 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
545 while ( (c = wanted->ctl[i]) && tt->max_len ) {
563 if (length < wanted->min) {
566 tok = new_tok(tt,wanted->id,offset,length,wanted);
570 case TVBPARSE_WANTED_SIMPLE_STRING:
572 if ( tvb_strneql(tt->tvb, tt->offset, wanted->ctl, wanted->len) == 0 ) {
573 int offset = tt->offset;
574 tt->offset += wanted->len;
575 tt->max_len -= wanted->len;
576 tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
582 case TVBPARSE_WANTED_SIMPLE_CASESTRING:
584 if ( tvb_strncaseeql(tt->tvb, tt->offset, wanted->ctl, wanted->len) == 0 ) {
585 int offset = tt->offset;
586 tt->offset += wanted->len;
587 tt->max_len -= wanted->len;
588 tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
594 case TVBPARSE_WANTED_SET_ONEOF:
598 for(i=0; i < wanted->elems->len; i++) {
599 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,i);
600 tvbparse_elem_t* new = tvbparse_get(tt, w);
603 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
610 case TVBPARSE_WANTED_SET_SEQ:
614 for(i=0; i < wanted->elems->len; i++) {
615 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,i);
616 tvbparse_elem_t* new = tvbparse_get(tt, w);
620 tok->len = (new->offset - tok->offset) + new->len;
621 tok->sub->last->next = new;
622 tok->sub->last = new;
624 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
635 case TVBPARSE_WANTED_CARDINALITY:
637 guint got_so_far = 0;
638 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,0);
640 if ( wanted->min == 0 ) {
641 new_tok(tt,wanted->id,tt->offset,0,wanted);
644 while (got_so_far < wanted->max) {
645 tvbparse_elem_t* new = tvbparse_get(tt, w);
649 tok->len = (new->offset - tok->offset) + new->len;
650 tok->sub->last->next = new;
651 tok->sub->last = new;
653 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
663 if(got_so_far < wanted->min) {
669 case TVBPARSE_WANTED_UNTIL:
671 int offset = tt->offset;
672 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,0);
673 tvbparse_elem_t* new = tvbparse_find(tt, w);
678 /* XXX this is ugly */
679 if (*(wanted->ctl) == 'i' ) {
680 tok->len = (tok->offset - offset) + tok->len;
682 tok->len = (tok->offset - offset);
684 tt->offset = save_offset + tok->len;
685 tt->max_len = save_len - tok->len;
688 tok->offset = offset;
689 tok->id = wanted->id;
692 tok->wanted = wanted;
701 DISSECTOR_ASSERT_NOT_REACHED();
706 if( tt->depth == 1 ) {
707 GPtrArray* stack = g_ptr_array_new();
708 tvbparse_elem_t* curr = tok;
712 if(curr->wanted->before) {
713 curr->wanted->before(tt->data, curr->wanted->data, curr);
717 g_ptr_array_add(stack,curr);
721 if(curr->wanted->after) curr->wanted->after(tt->data, curr->wanted->data, curr);
726 while( !curr && stack->len ) {
727 curr = g_ptr_array_remove_index_fast(stack,stack->len - 1);
728 if( curr->wanted->after ) curr->wanted->after(tt->data, curr->wanted->data, curr);
734 g_ptr_array_free(stack,FALSE);
742 tt->offset = save_offset;
743 tt->max_len = save_len;
750 tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted) {
751 int save_offset = tt->offset;
752 int save_len = tt->max_len;
753 tvbparse_elem_t* tok = NULL;
755 while ( tvb_length_remaining(tt->tvb,tt->offset) >= wanted->len ) {
756 if (( tok = tvbparse_get(tt, wanted) )) {
763 tt->offset = save_offset;
764 tt->max_len = save_len;