PEAR2_Services_LinkbackPEAR2_Services_Linkback-0.2.1/src/PEAR2/Services/Linkback/Server/Callback/LinkExists.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<?php
/**
 * This file is part of the PEAR2\Services\Linkback package.
 *
 * PHP version 5
 *
 * @category Services
 * @package  PEAR2\Services\Linkback
 * @author   Christian Weiske <cweiske@php.net>
 * @license  http://www.opensource.org/licenses/lgpl-license.php LGPL
 * @link     http://pear2.php.net/package/Services_Linkback
 */
namespace PEAR2\Services\Linkback\Server\Callback;
use PEAR2\Services\Linkback\DomLoader;

/**
 * Default implementation for the ILinkExists interface:
 * Verifies that the source body contains a link to the target URL.
 *
 * You may use it in your own linkback server.
 *
 * @category Services
 * @package  PEAR2\Services\Linkback
 * @author   Christian Weiske <cweiske@php.net>
 * @license  http://www.opensource.org/licenses/lgpl-license.php LGPL
 * @link     http://pear2.php.net/package/Services_Linkback
 */
class LinkExists implements ILink
{
    /**
     * Verifies that a link from $source to $target exists.
     *
     * @param string $target     Target URI that should be linked in $source
     * @param string $source     Linkback source URI that should link to target
     * @param string $sourceBody Content of $source URI
     * @param object $res        HTTP response from fetching $source
     *
     * @return boolean True if $source links to $target
     */
    public function verifyLinkExists(
        $target, $source, $sourceBody, \HTTP_Request2_Response $res
    ) {
        $doc = DomLoader::load($sourceBody, $res);
        $xpath = new \DOMXPath($doc);
        $xpath->registerNamespace('h', 'http://www.w3.org/1999/xhtml');

        $targetNoQuotes = str_replace('"', '', $target);
        $nodeList = $xpath->query(
            '//*[(self::a or self::h:a)'
            . ' and (@href="' . $target . '"'
            . ' or starts-with(@href, "' . $targetNoQuotes . '#")'
            . ')'
            . ']'
        );

        if ($nodeList->length > 0) {
            return true;
        }

        //now check for relative links - needed when pages on the same server
        // link each other
        if (parse_url($source, PHP_URL_HOST) != parse_url($target, PHP_URL_HOST)) {
            //not on the same server
            return false;
        }

        $sourceUrl = new \Net_URL2($source);
        //FIXME: base URL in html code

        $xpath = new \DOMXPath($doc);
        $xpath->registerNamespace('h', 'http://www.w3.org/1999/xhtml');
        $links = $xpath->query('//*[self::a or self::h:a]');
        foreach ($links as $link) {
            $url = (string)$sourceUrl->resolve(
                $link->attributes->getNamedItem('href')->nodeValue
            );
            if ($url == $target) {
                return true;
            }
        }

        return false;
    }
}

?>
EOF