/******************************************************************** * FUNCTION clear_current_level * Clear the current level without changing it * * INPUTS: * session_cb == session control block to use *********************************************************************/ static void clear_current_level (session_cb_t *session_cb) { val_value_t *target = session_cb->config_ecurval; if (target == NULL) { return; } if (session_cb->config_estartval == NULL) { /* clear everything out */ val_free_value(session_cb->config_etree); session_cb->config_etree = NULL; session_cb->config_ecurval = NULL; return; } boolean islist = obj_is_list(target->obj); val_value_t *chval = val_get_first_child(target); val_value_t *nextval = NULL; for (; chval; chval = nextval) { nextval = val_get_next_child(chval); if (islist && obj_is_key(chval->obj)) { continue; } val_remove_child(chval); val_free_value(chval); } } /* clear_current_level */
/******************************************************************** * FUNCTION write_full_check_val * * generate entire val_value_t *w/filter) * Write an entire val_value_t out as XML, including the top level * Using an optional testfn to filter output * * INPUTS: * scb == session control block * msg == xml_msg_hdr_t in progress * val == value to write * startindent == start indent amount if indent enabled * testcb == callback function to use, NULL if not used * justone == TRUE if just one of these; FALSE if more than one * isfirst == TRUE if this is the first (top) val printed * isfirstchild == TRUE if this is the first value of an array * == FALSE if this is the 2nd - Nth value of an array * RETURNS: * status *********************************************************************/ static status_t write_full_check_val (ses_cb_t *scb, xml_msg_hdr_t *msg, val_value_t *val, int32 startindent, val_nodetest_fn_t testfn, boolean justone, boolean isfirst, boolean isfirstchild) { val_value_t *out; boolean malloced = FALSE; status_t res = NO_ERR; out = val_get_value(scb, msg, val, testfn, TRUE, &malloced, &res); if (!out || res != NO_ERR) { if (res == ERR_NCX_SKIPPED) { res = NO_ERR; } if (out && malloced) { val_free_value(out); } return res; } /* check if this is an external file to send */ if (out->btyp == NCX_BT_EXTERN || out->btyp == NCX_BT_INTERN || typ_is_simple(out->btyp)) { if (isfirst) { write_json_string_value(scb, out); } else { /* write the name of the node */ ses_putchar(scb, '"'); ses_putjstr(scb, out->name, -1); ses_putchar(scb, '"'); ses_putchar(scb, ':'); switch (out->btyp) { case NCX_BT_EXTERN: ses_putchar(scb, '"'); val_write_extern(scb, out); ses_putchar(scb, '"'); break; case NCX_BT_INTERN: ses_putchar(scb, '"'); val_write_intern(scb, out); ses_putchar(scb, '"'); break; case NCX_BT_ENUM: ses_putchar(scb, '"'); if (VAL_ENUM_NAME(out)) { ses_putjstr(scb, VAL_ENUM_NAME(out), -1); } ses_putchar(scb, '"'); break; case NCX_BT_EMPTY: if (out->v.boo) { ses_putjstr(scb, NCX_EL_NULL, -1); } // else skip this value! should already be checked break; case NCX_BT_BOOLEAN: if (out->v.boo) { ses_putjstr(scb, NCX_EL_TRUE, -1); } else { ses_putjstr(scb, NCX_EL_FALSE, -1); } break; default: write_json_string_value(scb, out); } } } else { val_value_t *chval; val_value_t *lastch = NULL; val_value_t *nextch = NULL; int32 indent = (startindent < 0) ? -1 : startindent + ses_indent_count(scb); if (isfirst) { ses_putchar(scb, '{'); } /* render a complex type; either an object or an array */ if (isfirstchild) { ses_putchar(scb, '"'); ses_putjstr(scb, out->name, -1); ses_putchar(scb, '"'); ses_putchar(scb, ':'); if (!justone) { ses_putchar(scb, '['); } } ses_indent(scb, indent); ses_putchar(scb, '{'); for (chval = val_get_first_child(out); chval != NULL; chval = nextch) { /* JSON ignores XML namespaces, so foo:a and bar:a * are both encoded in the same array */ uint32 childcnt = val_instance_count(out, NULL, chval->name); boolean firstchild = (lastch && !xml_strcmp(lastch->name, chval->name)) ? FALSE : TRUE; lastch = chval; nextch = val_get_next_child(chval); res = write_full_check_val(scb, msg, chval, indent, testfn, (childcnt > 1) ? FALSE : TRUE, FALSE, firstchild); if (res == ERR_NCX_SKIPPED) { ; } else if (res != NO_ERR) { /* FIXME: do something about error; * may not always be OK to continue to next child node */ ; } else if (nextch) { ses_putchar(scb, ','); if (indent >= 0 && (typ_is_simple(nextch->btyp) || xml_strcmp(nextch->name, chval->name))) { ses_indent(scb, indent); ses_putchar(scb, ' '); } } } ses_indent(scb, indent); ses_putchar(scb, '}'); if (!justone) { val_value_t *peeknext = val_get_next_child(val); if (!peeknext || xml_strcmp(val->name, peeknext->name)) { ses_putchar(scb, ']'); } } if (isfirst) { ses_indent(scb, startindent); ses_putchar(scb, '}'); } } if (malloced && out) { val_free_value(out); } return res; } /* write_full_check_val */
/******************************************************************** * FUNCTION mgr_not_dispatch * * Dispatch an incoming <rpc-reply> response * handle the <notification> element * called by mgr_top.c: * This function is registered with top_register_node * for the module 'notification', top-node 'notification' * * INPUTS: * scb == session control block * top == top element descriptor *********************************************************************/ void mgr_not_dispatch (ses_cb_t *scb, xml_node_t *top) { #ifdef DEBUG if (!scb || !top) { SET_ERROR(ERR_INTERNAL_PTR); return; } #endif /* check if the notification template is already cached */ if (notification_obj == NULL) { log_error("\nNo notification module found\n"); mgr_xml_skip_subtree(scb->reader, top); return; } /* the current node is 'notification' in the notifications namespace * First get a new notification msg struct */ mgr_not_msg_t *msg = new_msg(); if (!msg) { log_error("\nError: mgr_not: skipping incoming message"); mgr_xml_skip_subtree(scb->reader, top); return; } /* parse the notification as a val_value_t tree, * stored in msg->notification */ msg->res = mgr_val_parse_notification(scb, notification_obj, top, msg->notification); if (msg->res != NO_ERR && LOGINFO) { log_info("\nmgr_not: got invalid notification on session %d (%s)", scb->sid, get_error_string(msg->res)); } /* check that there is nothing after the <rpc-reply> element */ if (msg->res==NO_ERR && !xml_docdone(scb->reader) && LOGINFO) { log_info("\nmgr_not: got extra nodes in notification on session %d", scb->sid); } boolean consumed = FALSE; if (msg->res == NO_ERR && msg->notification) { val_value_t *child = val_get_first_child(msg->notification); if (child) { if (!xml_strcmp(child->name, (const xmlChar *)"eventTime")) { msg->eventTime = child; } else { log_error("\nError: expected 'eventTime' in " "notification, got '%s'", child->name); } child = val_get_next_child(child); if (child) { /* eventType is expected to be next!! */ msg->eventType = child; } } else { log_error("\nError: expected 'eventTime' in " "notification, got nothing"); } /* invoke the notification handler */ if (callbackfn) { (*callbackfn)(scb, msg, &consumed); } } if (!consumed) { mgr_not_free_msg(msg); } } /* mgr_not_dispatch */