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 */
61 const tvbparse_wanted_t* ignore;
65 struct _tvbparse_wanted_t {
76 tvbparse_action_t before;
77 tvbparse_action_t after;
83 tvbparse_wanted_t* tvbparse_char(int id,
86 tvbparse_action_t before_cb,
87 tvbparse_action_t after_cb) {
88 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
91 w->type = TVBPARSE_WANTED_SIMPLE_CHAR;
97 w->before = before_cb;
99 w->elems = g_ptr_array_new();
104 tvbparse_wanted_t* tvbparse_chars(int id,
109 tvbparse_action_t before_cb,
110 tvbparse_action_t after_cb) {
111 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
114 w->type = TVBPARSE_WANTED_SIMPLE_CHARS;
117 w->min = min_len ? min_len : 1;
118 w->max = max_len ? max_len : G_MAXINT;
120 w->before = before_cb;
122 w->elems = g_ptr_array_new();
127 tvbparse_wanted_t* tvbparse_not_char(int id,
130 tvbparse_action_t before_cb,
131 tvbparse_action_t after_cb) {
132 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
135 w->type = TVBPARSE_WANTED_SIMPLE_NOT_CHAR;
141 w->before = before_cb;
143 w->elems = g_ptr_array_new();
148 tvbparse_wanted_t* tvbparse_not_chars(int id,
153 tvbparse_action_t before_cb,
154 tvbparse_action_t after_cb){
155 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
158 w->type = TVBPARSE_WANTED_SIMPLE_NOT_CHARS;
161 w->min = min_len ? min_len : 1;
162 w->max = max_len ? max_len : G_MAXINT;
164 w->before = before_cb;
166 w->elems = g_ptr_array_new();
172 tvbparse_wanted_t* tvbparse_string(int id,
175 tvbparse_action_t before_cb,
176 tvbparse_action_t after_cb) {
177 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
180 w->type = TVBPARSE_WANTED_SIMPLE_STRING;
182 w->len = strlen(str);
186 w->before = before_cb;
188 w->elems = g_ptr_array_new();
193 tvbparse_wanted_t* tvbparse_casestring(int id,
196 tvbparse_action_t before_cb,
197 tvbparse_action_t after_cb) {
198 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
201 w->type = TVBPARSE_WANTED_SIMPLE_CASESTRING;
203 w->len = strlen(str);
207 w->before = before_cb;
209 w->elems = g_ptr_array_new();
215 tvbparse_wanted_t* tvbparse_set_oneof(int id,
217 tvbparse_action_t before_cb,
218 tvbparse_action_t after_cb,
220 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
225 w->type = TVBPARSE_WANTED_SET_ONEOF;
231 w->before = before_cb;
233 w->elems = g_ptr_array_new();
235 va_start(ap,after_cb);
237 while(( el = va_arg(ap,tvbparse_t*) )) {
238 g_ptr_array_add(w->elems,el);
246 tvbparse_wanted_t* tvbparse_set_seq(int id,
248 tvbparse_action_t before_cb,
249 tvbparse_action_t after_cb,
251 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
252 tvbparse_wanted_t* el = NULL;
256 w->type = TVBPARSE_WANTED_SET_SEQ;
262 w->before = before_cb;
264 w->elems = g_ptr_array_new();
266 va_start(ap,after_cb);
268 while(( el = va_arg(ap,tvbparse_wanted_t*) )) {
269 g_ptr_array_add(w->elems,el);
277 tvbparse_wanted_t* tvbparse_some(int id,
281 tvbparse_action_t before_cb,
282 tvbparse_action_t after_cb,
283 const tvbparse_wanted_t* el) {
285 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
287 g_assert(from > 0 && from < to);
290 w->type = TVBPARSE_WANTED_CARDINALITY;
296 w->before = before_cb;
298 w->elems = g_ptr_array_new();
300 g_ptr_array_add(w->elems,(gpointer)el);
305 tvbparse_wanted_t* tvbparse_until(int id,
307 tvbparse_action_t before_cb,
308 tvbparse_action_t after_cb,
309 const tvbparse_wanted_t* el,
310 gboolean include_term) {
311 tvbparse_wanted_t* w = g_malloc(sizeof(tvbparse_wanted_t));
314 w->type = TVBPARSE_WANTED_UNTIL;
316 /* XXX this is ugly */
317 w->ctl = include_term ? "include" : "do not include";
323 w->before = before_cb;
325 w->elems = g_ptr_array_new();
327 g_ptr_array_add(w->elems,(gpointer)el);
333 tvbparse_wanted_t* tvbparse_quoted(int id,
335 tvbparse_action_t before_cb,
336 tvbparse_action_t after_cb,
340 gchar* esc_quot = g_strdup_printf("%c%c",esc,quote);
341 gchar* quot = g_strdup_printf("%c",quote);
342 tvbparse_wanted_t* want_quot = tvbparse_char(-1,quot,NULL,NULL,NULL);
344 return tvbparse_set_oneof(id, data, before_cb, after_cb,
345 tvbparse_set_seq(-1, NULL, NULL, NULL,
347 tvbparse_set_seq(-1,NULL,NULL,NULL,
348 tvbparse_set_oneof(-1, NULL, NULL, NULL,
349 tvbparse_string(-1,esc_quot,NULL,NULL,NULL),
350 tvbparse_not_chars(-1,0,0,quot,NULL,NULL,NULL),
355 tvbparse_set_seq(-1, NULL, NULL, NULL,
363 void tvbparse_shrink_token_cb(void* tvbparse_data _U_,
364 const void* wanted_data _U_,
365 tvbparse_elem_t* tok) {
370 tvbparse_t* tvbparse_init(tvbuff_t* tvb,
374 const tvbparse_wanted_t* ignore) {
375 tvbparse_t* tt = ep_alloc(sizeof(tvbparse_t));
379 tt->max_len = (len == -1) ? (int) tvb_length(tvb) : len;
386 gboolean tvbparse_reset(tvbparse_t* tt,
390 len = (len == -1) ? (int) tvb_length(tt->tvb) : len;
392 if( tvb_length_remaining(tt->tvb, offset) >= len) {
403 static tvbparse_elem_t* new_tok(tvbparse_t* tt,
407 const tvbparse_wanted_t* wanted) {
408 tvbparse_elem_t* tok = ep_alloc(sizeof(tvbparse_elem_t));
412 tok->offset = offset;
417 tok->wanted = wanted;
423 tvbparse_elem_t* tvbparse_get(tvbparse_t* tt,
424 const tvbparse_wanted_t* wanted) {
425 tvbparse_elem_t* tok = NULL;
426 int save_offset = tt->offset;
427 int save_len = tt->max_len;
431 if (tt->ignore && tt->ignore != wanted) {
432 tvbparse_wanted_t* save = (void*)tt->ignore;
434 while ( tvbparse_get(tt,save) ) {
440 switch(wanted->type) {
441 case TVBPARSE_WANTED_NONE:
443 case TVBPARSE_WANTED_SIMPLE_NOT_CHAR:
447 gboolean not_matched = FALSE;
452 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
454 for(i = 0; (c = wanted->ctl[i]) && tt->max_len; i++) {
465 tok = new_tok(tt,wanted->id,tt->offset-1,1,wanted);
469 case TVBPARSE_WANTED_SIMPLE_CHAR:
477 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
479 for(i = 0; (c = wanted->ctl[i]) && tt->max_len; i++) {
483 tok = new_tok(tt,wanted->id,tt->offset-1,1,wanted);
489 case TVBPARSE_WANTED_SIMPLE_NOT_CHARS:
493 guint offset = tt->offset;
496 while( tt->max_len && length < wanted->max) {
497 gboolean not_matched = FALSE;
498 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
501 while ( (c = wanted->ctl[i]) && tt->max_len ) {
518 if ( length < wanted->min ) {
521 tok = new_tok(tt,wanted->id,offset,length,wanted);
525 case TVBPARSE_WANTED_SIMPLE_CHARS:
529 guint offset = tt->offset;
532 while( tt->max_len && length < wanted->max) {
533 gboolean matched = FALSE;
534 t = (gchar) tvb_get_guint8(tt->tvb,tt->offset);
537 while ( (c = wanted->ctl[i]) && tt->max_len ) {
555 if (length < wanted->min) {
558 tok = new_tok(tt,wanted->id,offset,length,wanted);
562 case TVBPARSE_WANTED_SIMPLE_STRING:
564 if ( tvb_strneql(tt->tvb, tt->offset, wanted->ctl, wanted->len) == 0 ) {
565 int offset = tt->offset;
566 tt->offset += wanted->len;
567 tt->max_len -= wanted->len;
568 tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
574 case TVBPARSE_WANTED_SIMPLE_CASESTRING:
576 if ( tvb_strncaseeql(tt->tvb, tt->offset, wanted->ctl, wanted->len) == 0 ) {
577 int offset = tt->offset;
578 tt->offset += wanted->len;
579 tt->max_len -= wanted->len;
580 tok = new_tok(tt,wanted->id,offset,wanted->len,wanted);
586 case TVBPARSE_WANTED_SET_ONEOF:
590 for(i=0; i < wanted->elems->len; i++) {
591 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,i);
592 tvbparse_elem_t* new = tvbparse_get(tt, w);
595 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
602 case TVBPARSE_WANTED_SET_SEQ:
606 for(i=0; i < wanted->elems->len; i++) {
607 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,i);
608 tvbparse_elem_t* new = tvbparse_get(tt, w);
612 tok->len = (new->offset - tok->offset) + new->len;
613 tok->sub->last->next = new;
614 tok->sub->last = new;
616 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
627 case TVBPARSE_WANTED_CARDINALITY:
629 guint got_so_far = 0;
630 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,0);
632 while (got_so_far < wanted->max) {
633 tvbparse_elem_t* new = tvbparse_get(tt, w);
637 tok->len = (new->offset - tok->offset) + new->len;
638 tok->sub->last->next = new;
639 tok->sub->last = new;
641 tok = new_tok(tt, wanted->id, new->offset, new->len, wanted);
651 if(got_so_far < wanted->min) {
657 case TVBPARSE_WANTED_UNTIL:
659 int offset = tt->offset;
660 tvbparse_wanted_t* w = g_ptr_array_index(wanted->elems,0);
661 tvbparse_elem_t* new = tvbparse_find(tt, w);
666 /* XXX this is ugly */
667 if (*(wanted->ctl) == 'i' ) {
668 tok->len = (tok->offset - offset) + tok->len;
670 tok->len = (tok->offset - offset);
672 tt->offset = save_offset + tok->len;
673 tt->max_len = save_len - tok->len;
676 tok->offset = offset;
677 tok->id = wanted->id;
680 tok->wanted = wanted;
689 DISSECTOR_ASSERT_NOT_REACHED();
694 if( tt->depth == 1 ) {
695 GPtrArray* stack = g_ptr_array_new();
696 tvbparse_elem_t* curr = tok;
700 if(curr->wanted->before) {
701 curr->wanted->before(tt->data, curr->wanted->data, curr);
705 g_ptr_array_add(stack,curr);
709 if(curr->wanted->after) curr->wanted->after(tt->data, curr->wanted->data, curr);
714 while( !curr && stack->len ) {
715 curr = g_ptr_array_remove_index_fast(stack,stack->len - 1);
716 if( curr->wanted->after ) curr->wanted->after(tt->data, curr->wanted->data, curr);
722 g_ptr_array_free(stack,FALSE);
730 tt->offset = save_offset;
731 tt->max_len = save_len;
738 tvbparse_elem_t* tvbparse_find(tvbparse_t* tt, const tvbparse_wanted_t* wanted) {
739 int save_offset = tt->offset;
740 int save_len = tt->max_len;
741 tvbparse_elem_t* tok = NULL;
743 while ( tvb_length_remaining(tt->tvb,tt->offset) >= wanted->len ) {
744 if (( tok = tvbparse_get(tt, wanted) )) {
751 tt->offset = save_offset;
752 tt->max_len = save_len;