13473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
23473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xlink.c : implementation of the hyperlinks detection module
33473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           This version supports both XML XLinks and HTML simple links
43473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
53473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * See Copyright for the status of this software.
63473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
7c5d64345cf19bfd72418eb0a837869b0462e9130Daniel Veillard * daniel@veillard.com
83473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
93473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1134ce8bece2f22cc99d25221b77315cd008f4866bDaniel Veillard#define IN_LIBXML
1270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese#include "libxml.h"
133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
144432df239b7aba6bff86c838e0be11d08f283b76Daniel Veillard#ifdef LIBXML_XPTR_ENABLED
153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <string.h> /* for memset() only */
163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_CTYPE_H
173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <ctype.h>
183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_STDLIB_H
203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <stdlib.h>
213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_SYS_STAT_H
233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <sys/stat.h>
243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_FCNTL_H
263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <fcntl.h>
273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_UNISTD_H
293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <unistd.h>
303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#ifdef HAVE_ZLIB_H
323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <zlib.h>
333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#endif
343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xmlmemory.h>
363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/tree.h>
373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/parser.h>
383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/valid.h>
393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xlink.h>
403c01b1d81b696fe8624b6d7e26ec0ebffcc7c06bDaniel Veillard#include <libxml/globals.h>
413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define XLINK_NAMESPACE (BAD_CAST "http://www.w3.org/1999/xlink/namespace/")
433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define XHTML_NAMESPACE (BAD_CAST "http://www.w3.org/1999/xhtml/")
443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/****************************************************************
463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *								*
473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           Default setting and related functions		*
483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *								*
493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ****************************************************************/
50f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard
51d0463560300f1d8b3e41d70c3728ed84fdc8dd30Daniel Veillardstatic xlinkHandlerPtr xlinkDefaultHandler = NULL;
52d0463560300f1d8b3e41d70c3728ed84fdc8dd30Daniel Veillardstatic xlinkNodeDetectFunc	xlinkDefaultDetect = NULL;
533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xlinkGetDefaultHandler:
563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Get the default xlink handler.
583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the current xlinkHandlerPtr value.
603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
613473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxlinkHandlerPtr
623473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxlinkGetDefaultHandler(void) {
633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xlinkDefaultHandler);
643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xlinkSetDefaultHandler:
693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @handler:  the new value for the xlink handler block
703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Set the default xlink handlers
723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorvoid
743473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxlinkSetDefaultHandler(xlinkHandlerPtr handler) {
753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xlinkDefaultHandler = handler;
763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xlinkGetDefaultDetect:
803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Get the default xlink detection routine
823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the current function or NULL;
843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
853473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxlinkNodeDetectFunc
863473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxlinkGetDefaultDetect	(void) {
873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(xlinkDefaultDetect);
883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xlinkSetDefaultDetect:
92cbaf399537a1fb69ef97b079e4cb553869aaa4d9Daniel Veillard * @func: pointer to the new detection routine.
933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Set the default xlink detection routine
953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
96f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillardvoid
973473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxlinkSetDefaultDetect	(xlinkNodeDetectFunc func) {
983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xlinkDefaultDetect = func;
993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
1003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/****************************************************************
1023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *								*
1033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *                  The detection routines			*
1043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *								*
1053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ****************************************************************/
1063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
107f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard
1083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xlinkIsLink:
1103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @doc:  the document containing the node
1113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @node:  the node pointer itself
1123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Check whether the given node carries the attributes needed
1143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * to be a link element (or is one of the linking elements issued
1153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * from the (X)HTML DtDs).
1163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * This routine don't try to do full checking of the link validity
1173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * but tries to detect and return the appropriate link type.
1183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns the xlinkType of the node (XLINK_TYPE_NONE if there is no
1203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         link detected.
1213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
122f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel VeillardxlinkType
1233473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxlinkIsLink	(xmlDocPtr doc, xmlNodePtr node) {
1243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *type = NULL, *role = NULL;
1253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xlinkType ret = XLINK_TYPE_NONE;
1263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (node == NULL) return(XLINK_TYPE_NONE);
1283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (doc == NULL) doc = node->doc;
1293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((doc != NULL) && (doc->type == XML_HTML_DOCUMENT_NODE)) {
1303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        /*
1313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * This is an HTML document.
1323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
1333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    } else if ((node->ns != NULL) &&
1343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor               (xmlStrEqual(node->ns->href, XHTML_NAMESPACE))) {
1353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
1363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * !!!! We really need an IS_XHTML_ELEMENT function from HTMLtree.h @@@
1373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
1383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor        /*
1393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * This is an XHTML element within an XML document
1403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * Check whether it's one of the element able to carry links
1413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * and in that case if it holds the attributes.
1423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
1433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
1463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * We don't prevent a-priori having XML Linking constructs on
1473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * XHTML elements
1483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
1493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    type = xmlGetNsProp(node, BAD_CAST"type", XLINK_NAMESPACE);
1503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (type != NULL) {
151ef4d3bc36c22f6a9742e672d0bdd8342caf80c2eDaniel Veillard	if (xmlStrEqual(type, BAD_CAST "simple")) {
1523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor            ret = XLINK_TYPE_SIMPLE;
15333a25af71f78c370850a057f430d874710169a6fAmi Fischman	} else if (xmlStrEqual(type, BAD_CAST "extended")) {
1543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    role = xmlGetNsProp(node, BAD_CAST "role", XLINK_NAMESPACE);
1553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (role != NULL) {
1563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xmlNsPtr xlink;
1573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		xlink = xmlSearchNs(doc, node, XLINK_NAMESPACE);
1583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		if (xlink == NULL) {
1593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    /* Humm, fallback method */
160f8e3db0445a1bc8cfe3f77326b07ec161482caa2Daniel Veillard		    if (xmlStrEqual(role, BAD_CAST"xlink:external-linkset"))
1613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			ret = XLINK_TYPE_EXTENDED_SET;
1623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		} else {
1633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    xmlChar buf[200];
1643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    snprintf((char *) buf, sizeof(buf), "%s:external-linkset",
1653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			     (char *) xlink->prefix);
1663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor                    buf[sizeof(buf) - 1] = 0;
1673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		    if (xmlStrEqual(role, buf))
1683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor			ret = XLINK_TYPE_EXTENDED_SET;
1693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		}
1713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
1733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret = XLINK_TYPE_EXTENDED;
1743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
1753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (type != NULL) xmlFree(type);
1783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (role != NULL) xmlFree(role);
1793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
1803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
1814432df239b7aba6bff86c838e0be11d08f283b76Daniel Veillard#endif /* LIBXML_XPTR_ENABLED */
1825d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#define bottom_xlink
1835d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#include "elfgcchack.h"
184