6a9fdb38a784b8ae482e904c88456145e20d708b
[obnox/wireshark/wip.git] / plugins / lua / lua_tree.c
1 /*
2  * lua_tree.c
3  *
4  * Ethereal's interface to the Lua Programming Language
5  *
6  * (c) 2006, Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
7  *
8  * $Id$
9  *
10  * Ethereal - Network traffic analyzer
11  * By Gerald Combs <gerald@ethereal.com>
12  * Copyright 1998 Gerald Combs
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #include "packet-lua.h"
30 #include <epan/expert.h>
31
32 LUA_CLASS_DEFINE(ProtoTree,PROTO_TREE,NOP);
33 LUA_CLASS_DEFINE(ProtoItem,ITEM,NOP);
34
35 /* ProtoTree class */
36
37 static int ProtoTree_add_item_any(lua_State *L, gboolean little_endian) {
38     /*
39      called with:
40      tree,field,tvb,offset,len,datum
41      tree,field,tvb,offset,len
42      tree,tvb,offset,len,text
43      tree,tvb,text
44      */
45     ProtoTree tree = checkProtoTree(L,1);
46     ProtoField field;
47     ProtoItem item = NULL;
48     Tvb tvb;
49     
50     if (!tree) {
51         pushProtoItem(L,NULL);
52         return 1;
53     }
54     
55     if (( luaL_checkudata (L, 2, TVB) )) {
56         tvb = checkTvb(L,2);
57
58         TRY {
59             const char* str;
60             int offset;
61             int len;
62
63             if (lua_isnumber(L,3)) {
64                 offset = luaL_checkint(L,3);
65                 len = luaL_checkint(L,4);
66                 str = lua_tostring(L,5);
67             } else if (lua_isstring(L,3)) {
68                 offset = 0;
69                 len = 0;
70                 str = lua_tostring(L,3);
71             } else {
72                 luaL_error(L,"First arg must be either TVB or ProtoField");
73                 return 0;
74             }
75         
76             item = proto_tree_add_text(tree,tvb,offset,len,"%s",str);
77         } CATCH(ReportedBoundsError) {
78             proto_tree_add_protocol_format(lua_tree, lua_malformed, lua_tvb, 0, 0, "[Malformed Frame: Packet Length]" );
79             luaL_error(L,"Malformed Frame");
80             return 0;
81         } ENDTRY;
82             
83     } else if (( luaL_checkudata (L, 2, PROTO_FIELD) )) {
84         field = checkProtoField(L,2);
85         tvb = checkTvb(L,3);
86
87         TRY {
88             int offset = luaL_checkint(L,4);
89             int len = luaL_checkint(L,5);
90
91             if ( lua_gettop(L) == 6 ) {
92                 switch(field->type) {
93                     case FT_UINT8:
94                     case FT_UINT16:
95                     case FT_UINT24:
96                     case FT_UINT32:
97                     case FT_FRAMENUM:
98                         item = proto_tree_add_uint(tree,field->hfid,tvb,offset,len,(guint32)luaL_checknumber(L,6));
99                         break;
100                     case FT_INT8:
101                     case FT_INT16:
102                     case FT_INT24:
103                     case FT_INT32:
104                         item = proto_tree_add_int(tree,field->hfid,tvb,offset,len,(gint32)luaL_checknumber(L,6));
105                         break;
106                     case FT_FLOAT:
107                         item = proto_tree_add_float(tree,field->hfid,tvb,offset,len,(float)luaL_checknumber(L,6));
108                         break;
109                     case FT_DOUBLE:
110                         item = proto_tree_add_double(tree,field->hfid,tvb,offset,len,(double)luaL_checknumber(L,6));
111                         break;
112                     case FT_STRING:
113                     case FT_STRINGZ:
114                         item = proto_tree_add_string(tree,field->hfid,tvb,offset,len,luaL_checkstring(L,6));
115                         break;
116                     case FT_UINT64:
117                     case FT_INT64:
118                     case FT_ETHER:
119                     case FT_BYTES:
120                     case FT_UINT_BYTES:
121                     case FT_IPv4:
122                     case FT_IPv6:
123                     case FT_IPXNET:
124                     case FT_GUID:
125                     case FT_OID:
126                     default:
127                         luaL_error(L,"FT_ not yet supported");
128                         return 0;
129                 }
130             } else {
131                 item = proto_tree_add_item(tree,field->hfid,tvb,offset,len,little_endian);
132             }
133         } CATCH(ReportedBoundsError) {
134             proto_tree_add_protocol_format(lua_tree, lua_malformed, lua_tvb, 0, 0, "[Malformed Frame: Packet Length]" );
135             luaL_error(L,"Malformed Frame");
136             return 0;
137         } ENDTRY;
138         
139     } else {
140         luaL_error(L,"First arg must be either TVB or ProtoField");
141         return 0;
142     }
143     
144     pushProtoItem(L,item);
145     return 1;
146 }
147
148 static int ProtoTree_add_item(lua_State *L) { return ProtoTree_add_item_any(L,FALSE); }
149 static int ProtoTree_add_item_le(lua_State *L) { return ProtoTree_add_item_any(L,TRUE); }
150
151 static int ProtoTree_tostring(lua_State *L) {
152     ProtoTree tree = checkProtoTree(L,1);
153     lua_pushstring(L,ep_strdup_printf("ProtoTree %p",tree));
154     return 1;
155 }
156
157
158 static int ProtoTree_get_parent(lua_State *L) {
159     ProtoTree tree = checkProtoTree(L,1);
160     proto_item* item = NULL;
161     
162     if (tree) {
163         item = proto_tree_get_parent(tree);
164     }
165     
166     pushProtoItem(L,item);
167     
168     return 1;
169 }
170
171 static const luaL_reg ProtoTree_methods[] = {
172     {"add_item",       ProtoTree_add_item},
173     {"add_item_le",       ProtoTree_add_item_le},
174     {"get_parent",       ProtoTree_get_parent},
175     {0, 0}
176 };
177
178 static const luaL_reg ProtoTree_meta[] = {
179     {"__tostring", ProtoTree_tostring},
180     {0, 0}
181 };
182
183 int ProtoTree_register(lua_State* L) {
184     luaL_openlib(L, PROTO_TREE, ProtoTree_methods, 0);
185     luaL_newmetatable(L, PROTO_TREE);
186     luaL_openlib(L, 0, ProtoTree_meta, 0);
187     lua_pushliteral(L, "__index");
188     lua_pushvalue(L, -3);
189     lua_rawset(L, -3);
190     lua_pushliteral(L, "__metatable");
191     lua_pushvalue(L, -3);
192     lua_rawset(L, -3);
193     lua_pop(L, 1);
194     
195     return 1;
196 }
197
198 /* ProtoItem class */
199 static int ProtoItem_tostring(lua_State *L) {
200     ProtoItem item = checkProtoItem(L,1);
201     lua_pushstring(L,ep_strdup_printf("ProtoItem %p",item));
202     return 1;
203 }
204
205 static int ProtoItem_add_subtree(lua_State *L) {
206     ProtoItem item = checkProtoItem(L,1);
207     SubTreeType ett;
208     ProtoTree tree = NULL;
209     
210     if (item) {
211         ett = checkSubTreeType(L,2);
212         
213         if (ett && *ett >= 0) {
214             tree = proto_item_add_subtree(item,*ett);
215         } else {
216             luaL_argerror(L,2,"bad ett");
217         }
218     }
219     
220     pushProtoTree(L,tree);
221     return 1;
222 }
223
224 static int ProtoItem_set_text(lua_State *L) {
225     ProtoItem item = checkProtoItem(L,1);
226     
227     if (!item) {
228         const gchar* s = luaL_checkstring(L,2);
229         proto_item_set_text(item,"%s",s);
230     }
231     
232     return 0;
233 }
234
235 static int ProtoItem_append_text(lua_State *L) {
236     ProtoItem item = checkProtoItem(L,1);
237     const gchar* s;
238     
239     if (item) {
240         s = luaL_checkstring(L,2);
241         proto_item_append_text(item,"%s",s);
242     }
243     return 0;
244 }
245
246 static int ProtoItem_set_len(lua_State *L) {
247     ProtoItem item = checkProtoItem(L,1);
248     int len;
249
250     if (item) {
251         len = luaL_checkint(L,2);
252         proto_item_set_len(item,len);
253     }
254     
255     return 0;
256 }
257
258 struct _expert_severity {
259     const gchar* str;
260     int val;
261 };
262
263 static const struct _expert_severity severities[] = {
264     {"PI_CHAT",PI_CHAT},
265     {"PI_NOTE",PI_NOTE},
266     {"PI_WARN",PI_WARN},
267     {"PI_ERROR",PI_ERROR},
268     {"PI_CHECKSUM",PI_CHECKSUM},
269     {"PI_SEQUENCE",PI_SEQUENCE},
270     {"PI_RESPONSE_CODE",PI_RESPONSE_CODE},
271     {"PI_UNDECODED",PI_UNDECODED},
272     {"PI_REASSEMBLE",PI_REASSEMBLE},
273     {"PI_MALFORMED",PI_MALFORMED},
274     {"PI_DEBUG",PI_DEBUG},
275     {NULL,0}
276 };
277
278 static int str_to_expert(const gchar* str) {
279     const struct _expert_severity* s;
280
281     if (!str) return 0;
282     
283     for(s = severities; s->str; s++) {
284         if (g_str_equal(str,s->str)) {
285             return s->val;
286         }
287     }
288     return 0;
289 }
290
291 #if 0
292 static const gchar* expert_to_str(int val) {
293     const struct _expert_severity* s;
294     for(s = severities; s->str; s++) {
295         if (s->val == val) {
296             return s->str;
297         }
298     }
299     return NULL;
300 }
301 #endif
302
303 static int ProtoItem_set_expert_flags(lua_State *L) {
304     ProtoItem item = checkProtoItem(L,1);
305     int group;
306     int severity;
307
308     if (item) {
309         group = str_to_expert(luaL_checkstring(L,2));
310         severity = str_to_expert(luaL_checkstring(L,3));
311
312         if (group && severity) {
313             proto_item_set_expert_flags(item,group,severity);
314         }
315     }
316
317     return 0;
318 }
319
320 static int ProtoItem_add_expert_info(lua_State *L) {
321     ProtoItem item = checkProtoItem(L,1);
322
323     if (item) {
324         int group = str_to_expert(luaL_checkstring(L,2));
325         int severity = str_to_expert(luaL_checkstring(L,3));
326         const gchar* str = luaL_optstring(L,4,"Expert Info");
327         
328         expert_add_info_format(lua_pinfo, item, group, severity, "%s", str);
329     }
330     
331     return 0;
332 }
333
334 static int ProtoItem_set_generated(lua_State *L) {
335     ProtoItem item = checkProtoItem(L,1);
336     if (item) {
337         PROTO_ITEM_SET_GENERATED(item);
338     }
339     return 0;
340 }
341
342
343 static int ProtoItem_set_hidden(lua_State *L) {
344     ProtoItem item = checkProtoItem(L,1);
345     if (item) {
346         PROTO_ITEM_SET_HIDDEN(item);
347     }
348     return 0;
349 }
350
351 static const luaL_reg ProtoItem_methods[] = {
352     {"add_subtree",       ProtoItem_add_subtree},
353     {"set_text",       ProtoItem_set_text},
354     {"append_text",       ProtoItem_append_text},
355     {"set_len",       ProtoItem_set_len},
356     {"set_expert_flags",       ProtoItem_set_expert_flags},
357     {"add_expert_info",       ProtoItem_add_expert_info},
358     {"set_generated",       ProtoItem_set_generated},
359     {"set_hidden",       ProtoItem_set_hidden},
360     {0, 0}
361 };
362
363 static const luaL_reg ProtoItem_meta[] = {
364     {"__tostring", ProtoItem_tostring},
365     {0, 0}
366 };
367
368
369
370 int ProtoItem_register(lua_State *L) {
371    const struct _expert_severity* s;
372     
373     luaL_openlib(L, ITEM, ProtoItem_methods, 0);
374     luaL_newmetatable(L, ITEM);
375     luaL_openlib(L, 0, ProtoItem_meta, 0);
376     lua_pushliteral(L, "__index");
377     lua_pushvalue(L, -3);
378     lua_rawset(L, -3);
379     lua_pushliteral(L, "__metatable");
380     lua_pushvalue(L, -3);
381     lua_rawset(L, -3);
382     lua_pop(L, 1);
383     
384     for(s = severities; s->str; s++) {
385         lua_pushstring(L, s->str);
386         lua_pushstring(L, s->str);
387         lua_settable(L, LUA_GLOBALSINDEX);
388     }
389     
390     return 1;
391 }