Ejemplo n.º 1
0
/**
 * Declare user-defined mapping between a URI and a namespace.
 */
static void
xfmt_prefix_declare(struct xfmt_pass2 *xp2, const char *uri, const char *prefix)
{
    nv_pair_t *nv;

    nv = nv_table_lookup(xp2->uri2prefix, uri);
    if (nv != NULL) {
        /*
         * Silently ignore the mapping if we already have seen an identical one
         * in the XML tree during the first pass.
         */

        if (strcmp(prefix, nv_pair_value_str(nv)) != 0) {
            g_carp("XFMT ignoring supplied prefix '%s' for '%s': "
                   "already saw '%s' in the tree", prefix, uri,
                   nv_pair_value_str(nv));
        }
    } else {
        /*
         * New mapping.
         */

        nv = nv_pair_make_static_str(uri, prefix);
        nv_table_insert_pair(xp2->uri2prefix, nv);
    }
}
Ejemplo n.º 2
0
/**
 * Record a tree-defined mapping between a prefix and a namespace URI.
 */
static void
xfmt_prefix_record(struct xfmt_pass1 *xp1, const char *prefix, const char *uri)
{
    nv_pair_t *nv;

    /*
     * Our policy is to use one single prefix for a given namespace URI
     * throughout the document.  Although several prefixes could be used.
     * this is confusing to read and serves no value: a human will be mislead
     * into thinking the two namespaces are different because they carry
     * distinct prefixes, and a machine will not care about the prefix value.
     */

    nv = nv_table_lookup(xp1->uri2prefix, uri);
    if (nv != NULL) {
        /*
         * Silently ignore the mapping if we already have seen an identical one
         * in the XML tree.
         */

        if (strcmp(prefix, nv_pair_value_str(nv)) != 0) {
            g_carp("XFMT ignoring prefix '%s' for '%s': "
                   "already saw '%s' earlier in the tree", prefix, uri,
                   nv_pair_value_str(nv));
        }
    } else {
        /*
         * New mapping.
         */

        nv = nv_pair_make_static_str(uri, prefix);
        nv_table_insert_pair(xp1->uri2prefix, nv);
    }
}
Ejemplo n.º 3
0
/**
 * Successful SOAP RPC reply callback.
 *
 * @param sr	the SOAP RPC request
 * @param root	XML tree of SOAP reply
 * @param arg	the UPnP control request
 */
static void
upnp_ctrl_soap_reply(const soap_rpc_t *sr, xnode_t *root, void *arg)
{
	upnp_ctrl_t *ucd = arg;
	xnode_t *xn;
	nv_table_t *nvt;
	void *reply;
	size_t reply_len;
	host_addr_t local_addr;
	int code;

	upnp_ctrl_check(ucd);

	if (GNET_PROPERTY(upnp_debug) > 1) {
		g_debug("UPNP got SOAP reply for %s", ucd->action);

		if (GNET_PROPERTY(upnp_debug) > 2)
			xfmt_tree_dump(root, stderr);
	}

	ucd->sr = NULL;		/* Done with SOAP request */

	if (soap_rpc_local_addr(sr, &local_addr))
		upnp_set_local_addr(local_addr);

	/*
	 * Decompile the returned values.
	 *
	 * <u:actionResponse xmlns:u="urn:schemas-upnp-org:service:serviceType:v">
	 *	 <arg1>out value1</arg1>
	 *	 <arg2>out value2</arg2>
	 *       :  :  :  :
	 *   <argn>out valuen</argn>
	 * </u:actionResponse>
	 *
	 * Values are inserted in name / value pairs: "arg1" -> "out value 1" and
	 * given to the launch callback for extracting and decompiling the values.
	 */

	nvt = nv_table_make(TRUE);

	for (xn = xnode_first_child(root); xn; xn = xnode_next_sibling(xn)) {
		nv_pair_t *nv;
		xnode_t *xt;

		if (!xnode_is_element(xn)) {
			if (GNET_PROPERTY(upnp_debug)) {
				g_warning("UPNP \"%s\" skipping XML node %s",
					ucd->action, xnode_to_string(xn));
			}
			continue;
		}

		xt = xnode_first_child(xn);

		if (NULL == xt || !xnode_is_text(xt)) {
			if (GNET_PROPERTY(upnp_debug)) {
				g_warning("UPNP \"%s\" bad child node %s in %s",
					ucd->action, xnode_to_string(xt), xnode_to_string2(xn));
			}
		} else {
			/*
			 * Name/value strings point in the tree, which is going to be
			 * alive for the duration of the processing, so we can use the
			 * strings without copying them.
			 */

			nv = nv_pair_make_static_str(
				xnode_element_name(xn), xnode_text(xt));

			nv_table_insert_pair(nvt, nv);

			if (xnode_next_sibling(xt) != NULL) {
				if (GNET_PROPERTY(upnp_debug)) {
					g_warning("UPNP \"%s\" content of %s is not pure text",
						ucd->action, xnode_to_string(xt));
				}
			}
		}
	}

	/*
	 * Attempt to decompile the replied values, if any are expected.
	 *
	 * Allocated data is done via walloc(), and the returned structure is flat.
	 * It will be freed after invoking the user callback.
	 */

	if (ucd->lcb != NULL) {
		reply = (*ucd->lcb)(nvt, &reply_len);
		code = NULL == reply ? UPNP_ERR_OK : UPNP_ERR_BAD_REPLY;
	} else {
		code = UPNP_ERR_OK;
		reply = NULL;
		reply_len = 0;
	}

	/*
	 * Let UPnP control invoker know about the result of the query.
	 */

	(*ucd->cb)(code, reply, reply_len, ucd->cb_arg);

	/*
	 * Done, final cleanup.
	 */

	WFREE_NULL(reply, reply_len);
	nv_table_free(nvt);
	upnp_ctrl_free(ucd);
}