/********************************************************************
 * 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 */
Example #2
0
/********************************************************************
* 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 */
Example #3
0
/********************************************************************
* 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 */