From 68b2004757a24da102276307c9d49b045d786f19 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sat, 13 Jan 2018 12:39:09 +0000 Subject: [PATCH] [Rework] Improve readability of xmlrpc API --- src/lua/lua_xmlrpc.c | 272 ++++++++++++++++++++++++------------------- 1 file changed, 154 insertions(+), 118 deletions(-) diff --git a/src/lua/lua_xmlrpc.c b/src/lua/lua_xmlrpc.c index 01850af70..96edee804 100644 --- a/src/lua/lua_xmlrpc.c +++ b/src/lua/lua_xmlrpc.c @@ -26,9 +26,34 @@ static const struct luaL_reg xmlrpclib_m[] = { {NULL, NULL} }; +enum lua_xmlrpc_state { + read_method_responce = 0, + read_params = 1, + read_param = 2, + read_param_value = 3, + read_param_element = 4, + read_struct = 5, + read_struct_member_name = 6, + read_struct_member_value = 7, + read_struct_element = 8, + read_string = 9, + read_int = 10, + read_double = 11, + read_array = 12, + read_array_value = 13, + read_array_element = 14, + error_state = 99, + success_state = 100, +}; + +enum lua_xmlrpc_stack { + st_array = 1, + st_struct = 2, +}; + struct lua_xmlrpc_ud { - gint parser_state; - gint depth; + enum lua_xmlrpc_state parser_state; + GQueue *st; gint param_count; gboolean got_text; lua_State *L; @@ -76,206 +101,208 @@ xmlrpc_start_element (GMarkupParseContext *context, GError **error) { struct lua_xmlrpc_ud *ud = user_data; - int last_state; + enum lua_xmlrpc_state last_state; last_state = ud->parser_state; switch (ud->parser_state) { - case 0: + case read_method_responce: /* Expect tag methodResponse */ if (g_ascii_strcasecmp (name, "methodResponse") == 0) { - ud->parser_state = 1; + ud->parser_state =read_params; } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 1: + case read_params: /* Expect tag params */ if (g_ascii_strcasecmp (name, "params") == 0) { - ud->parser_state = 2; + ud->parser_state = read_param; /* result -> table of params indexed by int */ lua_newtable (ud->L); } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 2: + case read_param: /* Expect tag param */ if (g_ascii_strcasecmp (name, "param") == 0) { - ud->parser_state = 3; + ud->parser_state = read_param_value; /* Create new param */ } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 3: + case read_param_value: /* Expect tag value */ if (g_ascii_strcasecmp (name, "value") == 0) { - ud->parser_state = 4; + ud->parser_state = read_param_element; } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 4: + case read_param_element: /* Expect tag struct */ if (g_ascii_strcasecmp (name, "struct") == 0) { - ud->parser_state = 5; + ud->parser_state = read_struct; /* Create new param of table type */ lua_newtable (ud->L); - ud->depth++; + g_queue_push_head (ud->st, GINT_TO_POINTER (st_struct)); } else if (g_ascii_strcasecmp (name, "array") == 0) { - ud->parser_state = 14; + ud->parser_state = read_array; /* Create new param of table type */ lua_newtable (ud->L); - ud->depth++; + g_queue_push_head (ud->st, GINT_TO_POINTER (st_array)); } else if (g_ascii_strcasecmp (name, "string") == 0) { - ud->parser_state = 11; + ud->parser_state = read_string; ud->got_text = FALSE; } else if (g_ascii_strcasecmp (name, "int") == 0) { - ud->parser_state = 12; + ud->parser_state = read_int; ud->got_text = FALSE; } else if (g_ascii_strcasecmp (name, "double") == 0) { - ud->parser_state = 13; + ud->parser_state = read_double; ud->got_text = FALSE; } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 5: + case read_struct: /* Parse structure */ /* Expect tag member */ if (g_ascii_strcasecmp (name, "member") == 0) { - ud->parser_state = 6; + ud->parser_state = read_struct_member_name; } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 6: + case read_struct_member_name: /* Expect tag name */ if (g_ascii_strcasecmp (name, "name") == 0) { - ud->parser_state = 7; + ud->parser_state = read_struct_member_value; } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 7: + case read_struct_member_value: /* Accept value */ if (g_ascii_strcasecmp (name, "value") == 0) { - ud->parser_state = 8; + ud->parser_state = read_struct_element; } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 8: + case read_struct_element: /* Parse any values */ /* Primitives */ if (g_ascii_strcasecmp (name, "string") == 0) { - ud->parser_state = 11; + ud->parser_state = read_string; ud->got_text = FALSE; } else if (g_ascii_strcasecmp (name, "int") == 0) { - ud->parser_state = 12; + ud->parser_state = read_int; ud->got_text = FALSE; } else if (g_ascii_strcasecmp (name, "double") == 0) { - ud->parser_state = 13; + ud->parser_state = read_double; ud->got_text = FALSE; } /* Structure */ else if (g_ascii_strcasecmp (name, "struct") == 0) { - ud->parser_state = 5; + ud->parser_state = read_struct; /* Create new param of table type */ lua_newtable (ud->L); - ud->depth++; + g_queue_push_head (ud->st, GINT_TO_POINTER (st_struct)); } else if (g_ascii_strcasecmp (name, "array") == 0) { - ud->parser_state = 14; + ud->parser_state = read_array; /* Create new param of table type */ lua_newtable (ud->L); - ud->depth++; + g_queue_push_head (ud->st, GINT_TO_POINTER (st_array)); } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 14: + case read_array: /* Parse array */ /* Expect data */ if (g_ascii_strcasecmp (name, "data") == 0) { - ud->parser_state = 15; + ud->parser_state = read_array_value; } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 15: + case read_array_value: /* Accept array value */ if (g_ascii_strcasecmp (name, "value") == 0) { - ud->parser_state = 16; + ud->parser_state = read_array_element; } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 16: + case read_array_element: /* Parse any values */ /* Primitives */ if (g_ascii_strcasecmp (name, "string") == 0) { - ud->parser_state = 11; + ud->parser_state = read_string; ud->got_text = FALSE; } else if (g_ascii_strcasecmp (name, "int") == 0) { - ud->parser_state = 12; + ud->parser_state = read_int; ud->got_text = FALSE; } else if (g_ascii_strcasecmp (name, "double") == 0) { - ud->parser_state = 13; + ud->parser_state = read_double; ud->got_text = FALSE; } /* Structure */ else if (g_ascii_strcasecmp (name, "struct") == 0) { - ud->parser_state = 5; + ud->parser_state = read_struct; /* Create new param of table type */ lua_newtable (ud->L); - ud->depth++; + g_queue_push_head (ud->st, GINT_TO_POINTER (st_struct)); } else if (g_ascii_strcasecmp (name, "array") == 0) { - ud->parser_state = 14; + ud->parser_state = read_array; /* Create new param of table type */ lua_newtable (ud->L); - ud->depth++; + g_queue_push_head (ud->st, GINT_TO_POINTER (st_array)); } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; + default: + break; } - if (ud->parser_state == 99) { + if (ud->parser_state == error_state) { g_set_error (error, xmlrpc_error_quark (), 1, "xmlrpc parse error on state: %d, while parsing start tag: %s", last_state, name); @@ -289,108 +316,112 @@ xmlrpc_end_element (GMarkupParseContext *context, GError **error) { struct lua_xmlrpc_ud *ud = user_data; - int last_state; + enum lua_xmlrpc_state last_state; last_state = ud->parser_state; switch (ud->parser_state) { - case 0: - ud->parser_state = 99; + case read_method_responce: + ud->parser_state = error_state; break; - case 1: + case read_params: /* Got methodResponse */ if (g_ascii_strcasecmp (name, "methodResponse") == 0) { /* End processing */ - ud->parser_state = 100; + ud->parser_state = success_state; } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 2: + case read_param: /* Got tag params */ if (g_ascii_strcasecmp (name, "params") == 0) { - ud->parser_state = 1; + ud->parser_state = read_params; } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 3: + case read_param_value: /* Got tag param */ if (g_ascii_strcasecmp (name, "param") == 0) { - ud->parser_state = 2; + ud->parser_state = read_param; lua_rawseti (ud->L, -2, ++ud->param_count); } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 4: + case read_param_element: /* Got tag value */ if (g_ascii_strcasecmp (name, "value") == 0) { - if (ud->depth == 0) { - ud->parser_state = 3; + if (g_queue_get_length (ud->st) == 0) { + ud->parser_state = read_param_value; } else { - /* Parse other members */ - ud->parser_state = 6; + if (GPOINTER_TO_INT (g_queue_peek_head (ud->st)) == st_struct) { + ud->parser_state = read_struct_member_name; + } + else { + ud->parser_state = read_array_value; + } } } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 5: + case read_struct: /* Got tag struct */ if (g_ascii_strcasecmp (name, "struct") == 0) { - ud->parser_state = 4; - ud->depth--; + ud->parser_state = read_param_element; + g_queue_pop_head (ud->st); } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 6: + case read_struct_member_name: /* Got tag member */ if (g_ascii_strcasecmp (name, "member") == 0) { - ud->parser_state = 5; + ud->parser_state = read_struct; /* Set table */ lua_settable (ud->L, -3); } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 7: + case read_struct_member_value: /* Got tag name */ if (g_ascii_strcasecmp (name, "name") == 0) { - ud->parser_state = 7; + ud->parser_state = read_struct_member_value; } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 8: + case read_struct_element: /* Got tag value */ if (g_ascii_strcasecmp (name, "value") == 0) { - ud->parser_state = 6; + ud->parser_state = read_struct_member_name; } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 11: - case 12: - case 13: + case read_string: + case read_int: + case read_double: /* Parse any values */ /* Handle empty tags */ if (!ud->got_text) { @@ -400,32 +431,33 @@ xmlrpc_end_element (GMarkupParseContext *context, ud->got_text = FALSE; } /* Primitives */ - if (g_ascii_strcasecmp (name, "string") == 0) { - ud->parser_state = 8; - } - else if (g_ascii_strcasecmp (name, "int") == 0) { - ud->parser_state = 8; - } - else if (g_ascii_strcasecmp (name, "double") == 0) { - ud->parser_state = 8; + if (g_ascii_strcasecmp (name, "string") == 0 || + g_ascii_strcasecmp (name, "int") == 0 || + g_ascii_strcasecmp (name, "double") == 0) { + if (GPOINTER_TO_INT (g_queue_peek_head (ud->st)) == st_struct) { + ud->parser_state = read_struct_element; + } + else { + ud->parser_state = read_array_element; + } } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 14: + case read_array: /* Got tag array */ if (g_ascii_strcasecmp (name, "array") == 0) { - ud->parser_state = 4; - ud->depth--; + ud->parser_state = read_param_element; + g_queue_pop_head (ud->st); } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; - case 15: + case read_array_value: /* Got tag data */ if (g_ascii_strcasecmp (name, "data") == 0) { ud->parser_state = 14; @@ -435,21 +467,23 @@ xmlrpc_end_element (GMarkupParseContext *context, ud->parser_state = 99; } break; - case 17: + case read_array_element: /* Got tag value */ if (g_ascii_strcasecmp (name, "value") == 0) { guint tbl_len = rspamd_lua_table_size (ud->L, -2); lua_rawseti (ud->L, -2, tbl_len + 1); - ud->parser_state = 15; + ud->parser_state = read_array_value; } else { /* Error state */ - ud->parser_state = 99; + ud->parser_state = error_state; } break; + default: + break; } - if (ud->parser_state == 99) { + if (ud->parser_state == error_state) { g_set_error (error, xmlrpc_error_quark (), 1, "xmlrpc parse error on state: %d, while parsing end tag: %s", last_state, name); @@ -464,7 +498,7 @@ xmlrpc_text (GMarkupParseContext *context, GError **error) { struct lua_xmlrpc_ud *ud = user_data; - gint num; + gulong num; gdouble dnum; /* Strip line */ @@ -479,24 +513,26 @@ xmlrpc_text (GMarkupParseContext *context, if (text_len > 0) { switch (ud->parser_state) { - case 7: + case read_struct_member_value: /* Push key */ lua_pushlstring (ud->L, text, text_len); break; - case 11: + case read_string: /* Push string value */ lua_pushlstring (ud->L, text, text_len); break; - case 12: + case read_int: /* Push integer value */ - num = strtoul (text, NULL, 10); + rspamd_strtoul (text, text_len, &num); lua_pushnumber (ud->L, num); break; - case 13: + case read_double: /* Push integer value */ dnum = strtod (text, NULL); lua_pushnumber (ud->L, dnum); break; + default: + break; } ud->got_text = TRUE; } @@ -522,9 +558,9 @@ lua_xmlrpc_parse_reply (lua_State *L) if (data != NULL) { ud.L = L; - ud.parser_state = 0; - ud.depth = 0; + ud.parser_state = read_method_responce; ud.param_count = 0; + ud.st = g_queue_new (); ctx = g_markup_parse_context_new (&xmlrpc_parser, G_MARKUP_TREAT_CDATA_AS_TEXT, &ud, NULL); -- 2.39.5