1/*
2 * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB.  If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21#include "config.h"
22#include "SVGURIReference.h"
23
24#include "Attribute.h"
25#include "Document.h"
26#include "Element.h"
27#include "URL.h"
28#include "XLinkNames.h"
29
30namespace WebCore {
31
32bool SVGURIReference::parseAttribute(const QualifiedName& name, const AtomicString& value)
33{
34    if (name.matches(XLinkNames::hrefAttr)) {
35        setHrefBaseValue(value);
36        return true;
37    }
38
39    return false;
40}
41
42bool SVGURIReference::isKnownAttribute(const QualifiedName& attrName)
43{
44    return attrName.matches(XLinkNames::hrefAttr);
45}
46
47String SVGURIReference::fragmentIdentifierFromIRIString(const String& url, Document& document)
48{
49    size_t start = url.find('#');
50    if (start == notFound)
51        return emptyString();
52
53    URL base = start ? URL(document.baseURI(), url.substring(0, start)) : document.baseURI();
54    String fragmentIdentifier = url.substring(start);
55    URL kurl(base, fragmentIdentifier);
56    if (equalIgnoringFragmentIdentifier(kurl, document.url()))
57        return fragmentIdentifier.substring(1);
58
59    // The url doesn't have any fragment identifier.
60    return emptyString();
61}
62
63static inline URL urlFromIRIStringWithFragmentIdentifier(const String& url, Document& document, String& fragmentIdentifier)
64{
65    size_t startOfFragmentIdentifier = url.find('#');
66    if (startOfFragmentIdentifier == notFound)
67        return URL();
68
69    // Exclude the '#' character when determining the fragmentIdentifier.
70    fragmentIdentifier = url.substring(startOfFragmentIdentifier + 1);
71    if (startOfFragmentIdentifier) {
72        URL base(document.baseURI(), url.substring(0, startOfFragmentIdentifier));
73        return URL(base, url.substring(startOfFragmentIdentifier));
74    }
75
76    return URL(document.baseURI(), url.substring(startOfFragmentIdentifier));
77}
78
79Element* SVGURIReference::targetElementFromIRIString(const String& iri, Document& document, String* fragmentIdentifier, Document* externalDocument)
80{
81    // If there's no fragment identifier contained within the IRI string, we can't lookup an element.
82    String id;
83    URL url = urlFromIRIStringWithFragmentIdentifier(iri, document, id);
84    if (url == URL())
85        return 0;
86
87    if (fragmentIdentifier)
88        *fragmentIdentifier = id;
89
90    if (id.isEmpty())
91        return 0;
92
93    if (externalDocument) {
94        // Enforce that the referenced url matches the url of the document that we've loaded for it!
95        ASSERT(equalIgnoringFragmentIdentifier(url, externalDocument->url()));
96        return externalDocument->getElementById(id);
97    }
98
99    // Exit early if the referenced url is external, and we have no externalDocument given.
100    if (isExternalURIReference(iri, document))
101        return 0;
102
103    return document.getElementById(id);
104}
105
106void SVGURIReference::addSupportedAttributes(HashSet<QualifiedName>& supportedAttributes)
107{
108    supportedAttributes.add(XLinkNames::hrefAttr);
109}
110
111}
112